Getting Started with Cairo Lang

Rahul Ravindran


We recommend working inside a python virtual environment, but you can also install the Cairo package directly. To create and enter the virtual environment, type:

python3.7 -m venv ~/cairo_venv source ~/cairo_venv/bin/activate

Make sure the venv is activated – you should see (cairo_venv) in the command line prompt.

Make sure you can install the following pip packages: ecdsa, fastecdsa, sympy (using pip3 install ecdsa fastecdsa sympy). On Ubuntu, for example, you will have to first run:

sudo apt install -y libgmp3-dev

On Mac, you can use brew:

brew install gmp

Install the cairo-lang python package using:

pip3 install cairo-lang

Alternatively, you can download the package ( from, and install it using:

pip3 install

Cairo was tested with python3.7. To make it work with python3.6, you will have to install contextvars:

pip3 install contextvars

Compiling and running a Cairo program

  1. Create a file, named test.cairo, with the following lines:
    func main(): [ap] = 1000; ap++ [ap] = 2000; ap++ [ap] = [ap – 2] + [ap – 1]; ap++ ret end

  2. Compile: (make sure all commands are executed in the virtual environment)
    cairo-compile test.cairo –output test_compiled.json

  3. Run:
    cairo-run \ –program=test_compiled.json –print_output \ –print_info –relocate_prints

  4. You can open the Cairo tracer by providing the --tracer flag to cairo-run. Then open it at http://localhost:8100/.

Visual Studio Code setup

Download the Cairo Visual Studio Code extension (cairo-0.8.0.vsix) from, and install it using:

code –install-extension cairo-0.8.0.vsix

Configure Visual Studio Code settings:

“editor.formatOnSave”: true, “editor.formatOnSaveTimeout”: 1500

Note: You should start Visual Studio Code from the terminal running the virtual environment, by typing code. For instructions for macOS, see here.

Your first Cairo Program

# Use the output builtin.
%builtins output

# Import the serialize_word() function.
from starkware.cairo.common.serialize import serialize_word

func main{output_ptr : felt*}():
    # Output 100 by calling serialize_word.
    # Output 200.
    # Output 300.
    # Return.
    return ()

The above code outputs the numbers 100, 200, 300.

How Cairo Functions Work

Let’s start by looking at the following Cairo function which computes the sum of the elements of an array:

Computes the sum of the memory elements at addresses:

arr + 0, arr + 1, …, arr + (size – 1). func array_sum(arr : felt*, size) -> (sum): if size == 0: return (sum=0) end

# size is not zero.
let (sum_of_rest) = array_sum(arr=arr + 1, size=size - 1)
return (sum=[arr] + sum_of_rest)


The first two lines are comment lines, and are ignored by the compiler. Comments in Cairo start with # and continue until the end of the line.

The first non-comment line func array_sum(arr : felt*, size) -> (sum): defines a function named array_sum which takes two arguments: arr and size. arr points to an array of size elements. The type of arr is felt* which is a pointer (for more information about felt, see below). The function declares that it returns one value called sum. The scope of the function ends with the word end (although end doesn’t mean that the function returns – you must add the return statement explicitly).

The next line if size == 0: instructs Cairo to execute the code in the if statement’s body if size is zero, and skip to the end of the if statement’s body otherwise.

When size == 0, there are no elements in the array, and so we can return that the sum is zero. Note that the syntax sum= is not mandatory (you could write return (0)), but it is recommended as it increases the readability of the code. On the other hand, the parentheses are required. As with other programming languages, the return statement ends the execution of the function immediately and returns the control to the calling function.

Now to the interesting part. The line let (sum_of_rest) = array_sum(arr=arr + 1, size=size - 1) (which is executed only if size != 0) makes a recursive call to array_sum(), starting from the second element (as arr points to the first memory cell of the array, arr + 1 points to the second cell. Also note that we need to pass size - 1). As with named value in the return statement, you don’t have to write arr= and size=. The expression let (sum_of_rest) = says that the function returns one value, which can be accessed using sum_of_rest.

The scope of the return values of functions is restricted (for example, they may be revoked due to jumps or function calls). Later, we will see how to overcome this by using local variables. You can read more in Revoked references.

Note that you cannot call functions as part of other expressions. For example trying to write something like foo(bar()) will not compile.

Finally, we return the sum of the first element with the sum of the rest of the elements. [...] is the dereference operator, so [arr] is the value of the memory at address arr, or in our case the first element of the array.


Cairo is the first Turing-complete language for creating provable programs for general computation. Its Builtins and field elements enable efficient generation of proofs. Cairo-based systems are already in production on Ethereum mainnet and is an interesting skill to have have in the web3 landscape.


Leave a Reply

More great articles

Getting Started With Tenderly for Blockchain Development

Overview First things first, we need to get your Smart Contracts into Tenderly to use all of the timesaving features…

Read Story

Ethereum Scaling using Rollups

why is scaling up needed? The demand for blockchain space has been increasing substantially over the past years, in particular…

Read Story

Getting Started With Ganache V7

Intro OK developers welcome back! In this video I think it's time for us to revisit Ganache. Ganache is part…

Read Story

Never miss a minute

Get great content to your inbox every week. No spam.
[contact-form-7 id="6" title="Footer CTA Subscribe Form"]