In September last year, StarkWare made two major announcements that would significantly improve the developer experience on the network.
They were:
- Cairo 1.0: A huge upgrade to Cairo, the native programming language for Starknet, that promises a safer, simpler, and better programming experience for Starknet developers.
- Sierra: An intermediary representation layer that will offer greater long-term stability for Cairo programs.
The tedious experience many developers faced when writing code with older versions of Cairo will be a thing of the past, as Cairo 1.0 makes writing code significantly easier and neater as the language becomes similar to Rust.
With this change to Cairo, it has the additional benefit of onboarding new developers familiar with Rust into the Starknet ecosystem.
That’s why Cairo 1.0, with the introduction of Sierra, has gotten the Starknet developer community very excited, and for good reason.
In this article, we’ll teach you how to write and compile your first Cairo 1.0 contract and explore all the new features that come with improvement. Now let’s get into it all!
Setting up a development environment
Before we start writing our code, we need to set up a developer environment. Unfortunately, tools that you may be familiar with for Starknet, like Protostar, Nile, or the official Starknet CLI for development, currently don’t support Cairo 1.0. That means we’ll need to use an alternative solution…
We’ve solved this by creating a custom development environment for Cairo 1.0 by cloning and trimming the official repo. You will need to clone this repo to write and compile your Cairo 1.0 contract.
All our contracts will go into the src folder. We’ve already created a boilerplate contract which we will be compiling to sierra and casm in the next section of this article.
Once we’ve cloned the repo, we can now go ahead to activate our Cairo 1.0 VS code extension for syntax highlighting.
To do this:
1. Install Node.js 18 LTS
2. Navigate into the vscode-cairo folder
Run the commands below in a terminal:
3. Build the language server:
4. Open Vscode in your current directory
Run these commands:
5. Finally, reload VScode and press F5
PS: You should add this extra snippet to your settings.json file in VScode to ensure things run correctly.
If your installation was successful, head to src/hello.cairo, and you should have syntax highlighting activated, as seen in the image above.
Compiling your first Cairo 1.0 contract
Having set up our development environment, we can now move to compile our Cairo 1.0 contract.
We will be working with a straightforward contract located in src/hello.cairo
This contract implements simple functions to increase and get the balance variable. The #[contract] signifies that we are writing a Starknet contract rather than a Cairo program.
Unlike with 0.x contracts, where we compile straight to Cairo assembly (casm), with Cairo 1.0, compiling our contracts will be made in two stages:
- Cairo > Sierra
- Sierra > Casm
Sierra stands for Safe Intermediate Representation and aims to constitute a representation layer between Cairo programs and its bytecodes. Sierra opens up the possibility to prove every Cairo run, thereby allowing for robust Denial of Service attack (DoS) protection.
To compile to Sierra, run the command below:
If the compilation was successful, you should see the Sierra output in your src/hello.sierra.
To further compile from Sierra to Casm, run the command below:
If the compilation was successful, you should see the casm output in your src/hello.casm.
Starknet Alpha v0.11.0 hasn’t been released, so we can’t deploy our compiled contracts to testnet or mainnet. However, this network upgrade is expected to happen at the end of February 2023.
Key Cairo 1.0 features you need to know about
It will take more than a single article to go over all the new features that come with Cairo 1.0, but we’ll explore some key ones in this section:
A new syntax
As stated earlier, Cairo 1.0 comes with a cleaner and better syntax inspired by Rust. This includes adopting Rust-like features such as traits and their implementations, pattern matching, panic, etc.
Language directives and imports
With Cairo 1.0, to get started with writing a Starknet contract, you have to specify the macro:
While every Cairo program must implement a main function, importing a function has also become easier.
You can do that like this:
Alternatively, you can also import the entire 'package':
and use it like this:
Data types
The signature of Starknet’s ecosystem is the felt data type, and of course, they are not disappearing anytime soon!
In addition to the felt data type, there’s support for other Integer types, like u256, u128, u64, u32, and u8.
While these Integer types are implemented using felts behind the scenes, they are considered safer to use and can now support arithmetic operations without needing custom libraries. e.g., you can now perform operations such as:
The use of these operators is overflow protected and causes panic if an overflow is detected.
There is also support for a contractAddress data type similar to Solidity’s address, which has only just been recently implemented in Cairo 0.1.
Type literals
Numerical literals such as 1,2,3 are felts by default. However, you can specify a different data type for them by appending the data type, like this:
The Let keyword to rule them all
With Cairo 1.0, we finally eliminate multiple variable declaration patterns (tempvar, local, etc.) to embrace just using the let keyword.
This is very helpful as we finally say goodbye to Revoked references compiler errors.
You can now also create mutable variables using the mut keyword.
Structs and storage variables
Rather than using the @storage_var decorator, Cairo 1.0 divides a contract into three main sections: a storage struct, the contract traits, and its implementations.
All storage variables are packed into a single struct named Storage, though this is subject to change.
At the time of writing, here’s what it looks like:
And can be read or written in this manner:
Mappings can be created using the LegacyMap keyword, where the data types of the mapped variables are inserted between < and > . You can also map tuples.
Events
Events allow a contract to emit information during the course of its execution that can be used outside of Starknet.
An event can be created like this:
And subsequently emitted this way:
Functions
Functions in Cairo 1.0 look similar to the 0.x versions, with the omission of the implicit arguments and the change of the func keyword to fn following Rust’s convention. Here’s an example of a basic function signature in Cairo 1.0:
You’ll also notice that return variables no longer contain the variable names but just their data types.
Return statements
Just like Rust, functions in Cairo 1.0 can either return values implicitly by omitting the ending semi-colon like this:
In this case, the final expression of the function is automatically returned, or explicitly by using the return keyword, like this:
Decorators
Decorators still exist in Cairo 1.0 but with a new syntax similar to Rust’s macro.
You can declare a decorator like this:
Enums and Pattern matching
Enums are a special data type consisting of a fixed set of constants that you define.
You can create an Enum in Cairo 1.0, like this:
Cairo 1.0 also enables us to create pattern matchings similar to Rust using the match keyword. When combined with Enums, pattern matchings can allow us to adapt a function’s behavior depending on the data variant it encounters.
Arrays
Cairo 1.0 makes array manipulations much easier, as the core library exports an array type in addition to some associated functions such as append, array_at, and array_len. Some basic array operations include adding new elements to an existing array, getting an element index, getting the array length, etc. These can be accessed from ArrayTrait.
Error messages and access controls
You can create custom errors in Cairo, which are outputted to the user upon failed execution. This can be very useful for implementing checks and proper access control mechanisms.
With Cairo 1.0, you can easily do this using the assert statement in a similar pattern to the require statement in Solidity:
Where the error message must be less than 31 characters.
Traits and their Implementations
Cairo 1.0 introduces traits and implementations. Think of traits as a special type of contract interface, as they define functionalities a particular type has and can share with others. They are defined using the trait keyword.
On the other hand, an implementation implements specific trait behaviors. All functions from the trait must be defined in the implementation.
They are defined using the impl keyword like this:
Generics
Cairo 1.0, similar to Rust, also supports generics, which enables you to write codes that are flexible and can work with multiple types rather than being tied to a specific type.
A type parameter is specified as generic by the use of angle brackets <> like this:
Replace_class sysall
With Cairo 1.0 and Starknet v0.11, a new syscall will be added, enabling you to swap the underlying contract implementation (class hash) without changing the contract’s entry point. Think of a default proxy!
And the best part is you can do this using just a single line of code:
Conclusion
Congratulations, you’ve just written and compiled your first Cairo 1.0 contract and learned about key Cairo 1.0 features!
Again, Cairo 1.0 is still a work in progress and evolving quickly. New features are getting added daily, so always check out the official repo and the Discord discussion channel to stay up to date!
Here are some additional resources that we think will help you along your Cairo 0.10 journey:
- A First Look at Cairo 1.0: A Safer, Stronger & Simpler Provable Programming Language
- Cairo 1.0 — changes, features, release date
- https://github.com/starkware-libs/cairo/blob/main/docs/reference/src/SUMMARY.adoc
- https://github.com/argentlabs/starknet-build/tree/main/cairo1.0/examples
- Cairo 1.0 by StarkWare
If you have any questions regarding this, reach out to me @0xdarlington, I’d love to help you build on Starknet with Argent X.
For more developer resources, follow us across our socials:
Twitter — @argentHq
Engineering Twitter — @argentDeveloper
LinkedIn — @argentHq
Youtube — @argentHQ