Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

🐺 Cairo wishlist 🦀 #1714

AbdelStark started this conversation in General
Jan 9, 2023 · 57 comments · 66 replies
Discussion options

Hey Cairo builders 🐺, let's discuss about what you would like to see for Cairo.
It can be:

  • new features in Cairo
  • quality of life improvements

Ultimately we would need to create issues for feature requests, but for the moment we don't have a clear process on how to handle external demands. So let's discuss those here and we will try to review / filter the requests and see if we can integrate some of them in the roadmap.

We appreciate your feedback and we will try to do our best to fit your needs!
Abdel__StarkWare_a_wolf_wearing_Santa_Clauss_hat_in_Santas_slei_311ca34c-dc44-4a47-8ba1-076cf2a4feab

You must be logged in to vote

Replies: 57 comments 66 replies

Comment options

Add is_some and is_none to Option type.

Description

The is_some and is_none methods return true if the Option is Some or None, respectively.
See https://doc.rust-lang.org/std/option/#querying-the-variant for the description of those functions.

Proposition

Proposed signature for is_some():

fn is_some() -> bool

Proposed signature for is_none():

fn is_none() -> bool
You must be logged in to vote
1 reply
Comment options

these are now supported - you currently need to add use option::OptionTrait; and use option::OptionTraitImpl;
similarly for Result.

Comment options

Less verbose/cheaper struct storage updates

Description

To read single attribute full struct needs to be read into memory, to update single struct attribute full struct needs to be rewritten. It is both more verbose than necessary and probably (depending on implementation) inefficient. More in depth problem description is here: https://hackmd.io/@RoboTeddy/BJZFu56wF#Concisely-update-large-structs.

You must be logged in to vote
2 replies
Comment options

+1, compiler level struct packing would be great too

Comment options

This would be so sweet!

Comment options

Automaticaly generate trivial view functions for storage variables

Description

Trivial storage related view functions take a lot of space and make contracts diffucult to read and understand. It should be possible to mark storage variables as public (similar to Solidity public modifier). As a result a view function should be generated.

Proposition

Instead of:

struct Storage { 
 value: felt,
}
#[view]
fn value() -> felt {
 value::read()
}

use public 'modifier':

struct Storage { 
 #[public]
 value: felt,
}
You must be logged in to vote
0 replies
Comment options

bytes32 equivalent

Description

When working on cross chain apps, Cairo short strings are very inconvenient. Felt based short strings and their solidity counterpart bytes32 are of diffrent lenght(251 vs 256) and of different encoding (left vs right padding). There is no easy conversion between the two.

Proposition

There should be a bytes32 equivalent type available in Cairo. The usual operations: comparison, bit operators, shift operators, index access should be available.

See: https://docs.soliditylang.org/en/v0.8.17/types.html#fixed-size-byte-arrays

You must be logged in to vote
0 replies
Comment options

I would love to have /* */ multi-line commenting as I often need to add large blocks of text to contextualize the code I write.

You must be logged in to vote
0 replies
Comment options

Support structs as l1_handler parameters

Description

Currently when, for example Uint256 is send from l1 to l2 it needs to be manually converted to the desired type:

@l1_handler
func handle_deposit{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
 from_address: felt,
 amount_low: felt,
 amount_high: felt,
 sender_address: felt,
) {
 let amount = Uint256(low=amount_low, high=amount_high);

When there are more than one struct the code gets noisy.

Proposition

When structs are supported as l1_handler parameters, above would be more readble:

@l1_handler
func handle_deposit{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
 from_address: felt,
 amount: Uint256,
 sender_address: felt,
) {
You must be logged in to vote
0 replies
Comment options

It would be nice if we can have a float type. I know it's not as easy as people think to create but it would help a lot programmers 🚀

You must be logged in to vote
1 reply
Comment options

Do you mean an IEEE-754 float type, or do you mean a fixed point decimal type?
If its the first then I think it should be a library rather than a language built-in.

Comment options

It's functionality can be improve

You must be logged in to vote
0 replies
Comment options

It would be awesome to have a cairo plugin for Intellij.

You must be logged in to vote
1 reply
Comment options

@software-mansion team plans to work on this 😃

Comment options

StarkNet Cairo should allow function overloading. To make this possible, we will need to modify the function selector calculation to include the input types and the function name.
This change will affect type-checking and remote contract calls from the language perspective. However, resolving these is easy because we can statically determine which instance of the function is being used.
Since we can statically resolve function overloading, it doesn't introduce any performance overhead.

You must be logged in to vote
0 replies
Comment options

Adding an is_empty() fn on Array Trait could be very handy
(I know I could do arr.len() == 0_usize, but isn't arr.is_empty() way more readable?)

You must be logged in to vote
1 reply
Comment options

orizi Feb 7, 2023
Maintainer

added it to the trait now - available at main or at next release :)

Comment options

add address type

Description

Currently felt type is used to represent contract addreses, e.g.:

 fn transfer_from(sender: felt, recipient: felt, amount: u256)

Proposition

There should be an address type to represent contract addresses:

 fn transfer_from(sender: address, recipient: address, amount: u256)
You must be logged in to vote
6 replies
Comment options

will this also be reflected in the ABI?

Comment options

Does that mean this type can only be used on contract addresses? I mean the ContractAddress type?

Comment options

orizi Feb 8, 2023
Maintainer

  • if the address is the type of the inputs - it'd be reflected in the ABI, of course a different abi can decide different strategies.

  • you'd be able to construct it from felts i guess - but its meaning is a contract-address.

Comment options

we already have such a type ContractAddress - will change ERC20 impl to use it. would also consider adding an alias type address = ContractAddress;

address would be more in line with felt, u256. On the other hand, having to many conventions (CamelCase, short types?) is not sth we want.

Comment options

The alias type address = ContractAddress is very handy, I'm for including it in the lang.

Comment options

Optimize usage of storage

Let's assume I have a struct:
struct { some_field1: u8, some_field2: u32, some_field3: u64 }

It should underneath be all contained in one felt rather than 3 separate felts to use the less possible storage on L1.

You must be logged in to vote
5 replies
Comment options

I think this should be opt-in behaviour, like Rust's #[repr(...)], because as far as I remember, this involves doing extra operations while reading/writing compressed fields?

Comment options

I think it does indeed (lot of masks and bitwise operations), so depending on how optimized the costs for those is, it may or may not be more gas efficient...

Comment options

IMO if when creating a struct, you can somehow specify the masks that need to be used to only perform the bitwise related operation it can already help.
But then it creates some burdens on the developper as he can make a mistake and not define a correct mask.

Comment options

That brings unsafety issues. I think this should be entirely automated and hidden from the programmer, so that a) we will have space to investigate various optimization patterns throughout time because there won't be any internal stability guarantees, and b) users won't be able to mess up things.

I think following would do the job:

#[repr(packed)]
struct Foo { some_field1: u8, some_field2: u32, some_field3: u64 }

or perhaps introduce versioning, because people will store this on the chain so there must be a possibility for backward and perhaps forward compatibility:

#[repr(packed, version = 1)]
struct Foo { some_field1: u8, some_field2: u32, some_field3: u64 }
Comment options

This is handled by the StorageAccess trait, which will allow packing to be finely controlled. For example, here is how we store a custom struct in Dojo:

It could be extended to handle packing / unpacking and we can introduce procmacros to generate the logic

impl StorageAccessPosition of starknet::StorageAccess::<Position> {
 fn read(
 address_domain: felt, base: starknet::StorageBaseAddress
 ) -> starknet::SyscallResult::<Position> {
 Result::Ok(
 Position {
 x: starknet::storage_read_syscall(
 address_domain, starknet::storage_address_from_base_and_offset(base, 0_u8)
 )?,
 y: starknet::storage_read_syscall(
 address_domain, starknet::storage_address_from_base_and_offset(base, 1_u8)
 )?,
 }
 )
 }
 fn write(
 address_domain: felt, base: starknet::StorageBaseAddress, value: Position
 ) -> starknet::SyscallResult::<()> {
 starknet::storage_write_syscall(
 address_domain, starknet::storage_address_from_base_and_offset(base, 0_u8), value.x
 )?;
 starknet::storage_write_syscall(
 address_domain, starknet::storage_address_from_base_and_offset(base, 1_u8), value.y
 )
 }
 }
Comment options

What do you think about providing access the contract context inside of starknets StorageAccess trait? I'm not sure exactly how that would look. Perhaps it is easier once we have the new contract syntax.

It would allow us to add access control directly at the storage level, which seems much more robust and less error prone.

One approach could be a Ownable<T> struct that wraps values but that would duplicate the owner state for each variable.

You must be logged in to vote
1 reply
Comment options

I think Ownable is a wonderful idea, and with some clever type engineering we can avoid the extra state.
Let me try,:

struct AdminToken{}
fn getAdminToken()->Option<AdminToken>{...}
#[storage]
struct MyContract{
 sensitive: LockedWith<felt, AdminToken>
}
fn get_sensitive(self: MyContract) -> Option<felt> {
 Some(self.sensitive.read().unlock(getAdminToken()?))
}
Comment options

Support for get_blockhash

You must be logged in to vote
1 reply
Comment options

This and / or a get_random potentially associated with the need for leader election randomness would be wonderful and a huge boost to games.

Comment options

Arrays can be defined in the constant pool and support initialization data.

Description

We are using Cairo to rewrite a Solidity ERC721 contract. This contract defines five arrays, each containing 30 to 60 different short strings. In the contract functions, a random string from each array is selected and concatenated to form a complete name. In Cairo, we cannot define and initialize arrays directly in the contract. Currently, we are manually writing indexes using LegacyMap to achieve this.

21693301815_ pic
31693301850_ pic
41693301884_ pic

Proposition

We want to directly define string array data in the contract.

You must be logged in to vote
0 replies
Comment options

I want a map-like data structure (Array or Dict) that supports multiple levels of nesting, random write and can be used in memory, without relying on LegacyMap structures in storage.

You must be logged in to vote
1 reply
Comment options

map-like data structure (Array or Dict)

So an array or a dict?

Do you want to manipulate data only in memory or should it support contract storage?

Comment options

Sorry I left some confusing things there. Actually I want a structure like 'Array<Array<T>>' that I can directly change the elements of whichever index I choose. Cause Array just supports append() and pop() now due to the unchanged memory, so I mention the dict implements the mutable feature there. And it is good enough that it can support the memory I think. So kind of you, have a good day! Get Outlook for iOS<https://aka.ms/o0ukef>
...
________________________________ From: Milan Cermak ***@***.***> Sent: Monday, September 11, 2023 10:01:46 PM To: starkware-libs/cairo ***@***.***> Cc: Ryan ***@***.***>; Comment ***@***.***> Subject: Re: [starkware-libs/cairo] 🐺 Cairo wishlist 🦀 (Discussion #1714) map-like data structure (Array or Dict) So an array or a dict? Do you want to manipulate data only in memory or should it support contract storage? — Reply to this email directly, view it on GitHub<#1714 (reply in thread)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AJX3WXT6MDVD5J4XMJPGBGLXZ4KUVANCNFSM6AAAAAATVSDLAA>. You are receiving this because you commented.Message ID: ***@***.***>
You must be logged in to vote
0 replies
Comment options

I want '<<' and '>>' Operators. They provide left shift and right shift features with less gas cost.

You must be logged in to vote
0 replies
Comment options

In solidity contract, we can user block.number to get current block number, but i do not know how to get block number in cairo contract.

You must be logged in to vote
1 reply
Comment options

You can use starknet::info::get_block_number() (see corelib).

Comment options

I know i can use get_caller_address() to get like msg.sender. but how can i get msg.value in cairo?

You must be logged in to vote
3 replies
Comment options

And in solidity, type(unit).max if i am not wrong that can get the max number for this type. Are there some function like that in cairo?

Comment options

There is no msg.value in Starknet. All value transfers are ERC20 transfers.

Comment options

ok

Comment options

how can i remove a element in Array by index? I can not find this method.

You must be logged in to vote
0 replies
Comment options

if we write legacyMap use the same key, whether will replace the value??

You must be logged in to vote
0 replies
Comment options

Proof verification within a cairo program would be a massive step forward in building fully decentralized state machines!

You must be logged in to vote
0 replies
Comment options

I want Base64 utils that could support type like Array<felt252>

You must be logged in to vote
0 replies
Comment options

i wanna deploy contract on remix easily

You must be logged in to vote
0 replies
Comment options

Make it possible to store functions inside variables.

This will make it possible to, among other things, support more functional programming paradigms:

  • Pass functions as parameters to other functions - e.g. will allow to define map, filter, reduce etc. on Arrays. Will allow iterator-related methods.
  • Return functions as results from other functions
  • Define scoped (local) functions inside other functions
You must be logged in to vote
0 replies
Comment options

Big DEV QOL improvement would be the possibility to make mutation testing.
You'd run the tool, it would make some tweak in the code (for example changing a <= to a <) and expect a test to fail.
This could be a big improvement for checking some edge cases that are not correctly tested or detect a big if the tests are correct.
Existing tools are:

You must be logged in to vote
1 reply
Comment options

Comment options

Hey guys! Does the VSCode extension works on Windows? I'm struggling to make it work on Windows but it doesn't work. Someone use it on Windows?

You must be logged in to vote
3 replies
Comment options

Hey! I don't think why it shouldn't work. But I can't help you if you don't tell me what's happening 😛

Try running the Troubleshooting guide from extension's readme

Comment options

Oh, ok! Let me try to explain. When I open the project in VSCode with WSL in remote mode, the extension works normally. In WSL I have the scarb installed through the asdf manager. So when I open the project through the WSL, the extension is able to communicate with the cairo-language-server.

image

On other hand, when I open the project directly through the Windows, where I have the scarb installed manualy, cause asdf doesn't work in the Windows, the extension isn't able to communicate with the cairo-language-server.

image

If any moment you're want to make a video conference through Discord or any other platform I'm available.

Comment options

The extension is unable to find scarb.exe automatically on your Windows machine.

  1. Do you have scarb.exe searchable from PATH environment variable? In other words: does running scarb work from PowerShell/Batch?
  2. You can always manually put path to scarb in your VSCode configuration. Look up in preferences GUI.

When the extension gets to a valid Scarb installation, it should automatically find the scarb-cairo-language-server.exe binary which ships the LS.

Comment options

  1. Yep, my scarb is running in PowerShell.
    image

  2. I changed manually the path to scarb in my VSCode configuration:

image

This notification appeared on the screen:
image

In the output this is the error message:
image

You must be logged in to vote
2 replies
Comment options

Draggu Jul 31, 2024
Collaborator

Hey! you have to specify path with binary C:\Program Files\scarb\bin\scarb.exe (same for LS).

Comment options

@Draggu hey man! Thank you very much, it worked! I need to produce a tutorial for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

AltStyle によって変換されたページ (->オリジナル) /