In this tutorial, we will set up the Cairo environment and write our first Cairo program.
Getting Started with Cairo
Scarb: The Cairo build tool and package manager
We recommend installing Scarb via the asdf version manager. Each Scarb version is associated with a specific Cairo version, and using asdf will allow you to switch between different compiler versions conveniently. Run the commands below after installing asdf (make sure to add asdf to your ~/.bashrc or ~/.zshrc files as detailed in the installing instructions).
asdf plugin add scarb
asdf install scarb latest
asdf global scarb latest
To verify that Scarb was installed successfully, run the following in your terminal of choice:
scarb --version
You can learn more about Scarb in the official documentation.
Creating a new Cairo project
You can create a new Scarb package by running:
scarb new hello_cairo
The above will create the following directory package:
hello_cairo
|- Scarb.toml
|- src
|- lib.cairo
Scarb.toml is the manifest file for Cairo. It’s where you keep your project metadata and dependencies.
lib.cairo is where you write your code, scarb new creates a default template for us with a main function that calculates the 16’th Fibonacci number:
fn main() -> felt252 {
fib(16)
}
fn fib(mut n: felt252) -> felt252 {
let mut a: felt252 = 0;
let mut b: felt252 = 1;
while n != 0 {
n = n - 1;
let temp = b;
b = a + b;
a = temp;
};
a
}
#[cfg(test)]
mod tests {
use super::fib;
#[test]
fn it_works() {
assert(fib(16) == 987, 'it works!');
}
}
We can see that the above code has a function called fib for calculating the n’th Fibonnaci number, and a main function that returns fib(16). Additionally, we have a test module with a single test function that asserts that the value return by fib(16) is 987. For those familiar with Rust, the similarity between the languages is evident. If you’re unfamiliar with Rust, don’t let it discourage you, you can read all about the language’s internals in the cairo-book.
Usually, lib.cairo contains your main function or declaration of other modules.
To build your Cairo package, you should run:
scarb build
To execute main you can use the cairo-run command:
scarb cairo-run
If the template project is not changed, this should print:
Run completed successfully, returning [987]
To run all the test functions (functions annotated with #[test] inside modules annotated with #[cfg(test)]) you can use the scarb test command:
scarb test
If the template project is not changed, this should print:
testing hello_cairo ...
running 1 tests
test hello_cairo::tests::it_works ... ok (gas usage est.: 33260)
test result: ok. 1 passed; 0 failed; 0 ignored; 0 filtered out;
Creating a Starknet smart-contract package
Cairo is a programming language for writing provable programs, but it is more widely known as the smart-contract language of Starknet. A smart-contract does not have a main function but rather a list of entry points, each callable from other contracts. While their high-level structure differs, smart-contracts have the same syntax as “regular” Cairo programs.
To build a smart-contract package, you need to add the following to your Scarb.toml:
[dependencies]
starknet = ">=2.6.0"
[[target.starknet-contract]]
We can add a new cairo file to our project, simple_storage.cairo with simple smart-contract that externalizes a setter and getter functions for a single u128 storage variable:
#[starknet::interface]
trait ISimpleStorage<TContractState> {
fn set(ref self: TContractState, x: u128);
fn get(self: @TContractState) -> u128;
}
#[starknet::contract]
mod simple_storage {
use starknet::get_caller_address;
use starknet::ContractAddress;
#[storage]
struct Storage {
stored_data: u128
}
#[abi(embed_v0)]
impl SimpleStorage of super::ISimpleStorage<ContractState> {
fn set(ref self: ContractState, x: u128) {
self.stored_data.write(x);
}
fn get(self: @ContractState) -> u128 {
self.stored_data.read()
}
}
}
You can learn more about the anatomy of this contract in the Cairo book.
Our project hierarchy now looks like this:
hello_cairo
|- Scarb.toml
|- src
|- lib.cairo
|- simple_storage.cairo
To add the new simple_storage module to our project, we need to add the following line to the lib.cairo file:
mod simple_storage;
This line will cause the compiler to build the contents of simple_storage.cairo.
Now, running scarb build will create a smart-contract artifact hello_cairo_simple_storage.contract_class.json inside ./target/dev. The name of the artifact is <package_name>_<contract_module_name>. These artifacts are known in Starknet as contract classes, and you can learn more about them in the Starknet documentation.
To interact with Starknet and deploy your new contract, you’ll need a Starknet account with enough funds to pay the transaction fees. To this end, we recommend using Starkli, the Starknet-CLI that will allow you to create accounts and interact with the blockchain.