Skip to content

Instantly share code, notes, and snippets.

@glihm
Last active February 25, 2024 17:42
Show Gist options
  • Save glihm/3f368d8cb1b0d02a9a16ea454d16dc24 to your computer and use it in GitHub Desktop.
Save glihm/3f368d8cb1b0d02a9a16ea454d16dc24 to your computer and use it in GitHub Desktop.
Docker for Cairo development

Docker for Cairo development

Cairo is the language used by Starknet to write smart contracts. Lately, the version was switched from Cairo 0 to Cairo 1, where the syntax has changed but the tooling is also evolving.

Moreover, the reference implementations of Starknet are migrating from python to rust. Cairo lang will soon be replaced by starknet-rs used by starkli. But until those tools become 100% functional, we need to compile Cairo 1 code, and use el cli of cairo-lang to deploy contracts on-chain.

To avoid the setting of dependency locally, this guide is an exploration as using Docker to manage those dependencies for us.

Prerequisites:

  • Docker installed on your machine.

Use the image from DockerHub

Images are available from DockerHub for cairo-lang and cairo compile.

We can then use both of them to quickly gain access to already configured environment.

Note about Docker containers

Using Docker, it is worth mentionning that after docker run command is issued, a new container is created. Once this container is deleted, all the memory associated with it is also erased. For this reason, we use volumes for persistent data. However, we can start and stop a container, without it's memory being erased.

To mount a simple volume, we use -v /host/computer/path:/path/in/container. Here, all the content in the directory /host/computer/path will be available into the container at /path/in/container. If the path in the container does not exist, Docker will create it for us.

This is important to note, as we will use two docker images, and we want the persistent available in each of them when we run the containers.

This guide shows some examples from starknet-edu, to have something applied to what we need to achieve with Cairo.

Prepare the data

Before we start, you have to locate your contracts written in Cairo.

You can copy the demo contract from starknet-edu. REMINDER, you have to change some lines of code for this contract to be deployed. The reason of that is that in Cairo, the hash of the contract class depends on it's content, and only changing functions names is not enough.

Consider to copy-paste some events (even if you don't use them), or add some lines of useless Cairo code.

In this tutorial, the contract file is created in the host computer at the following path: ~/cairo/contract.cairo.

Also, we need to define environment variables:

export STARKNET_NETWORK=alpha-goerli
export STARKNET_WALLET=starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount

It's convenient to export the variables in your local session, to capture them while running the docker run commands. At least, for the STARKNET_WALLET. The network may be passed at each command using -e STARKNET_NETWORK=alpha-goerli or -e STARKNET_NETWORK=alpha-mainnet if you prefer.

Running the commands

  1. Compile the contract:
docker run --rm \
           -v ~/cairo:/work \
           --entrypoint starknet-compile \
           starknet/cairo \
           /work/contract.cairo /work/contract.json --replace-ids

Some remarks:

  • --rm indicates that we want the container to be deleted after the command is run. For this reason, please take care to store persistent data into the volume. In this example, our persistent mounted location /work inside the container.
  • -v to mount the volume, and access/write to persisent data.
  • --entrypoint is the name of the command we want to execute. This is possible because the Dockerfile as an entrypoint as sh shell, where the binaries are in the PATH.
  • After comes the name of the image (in this example is starknet/cairo.
  • All that come after the name of the image is passed as argument to the entrypoint command into the container.
  1. Create a new account:
docker run --rm \
           -v ~/cairo:/work \
           -e STARKNET_NETWORK=$STARKNET_NETWORK \
           -e STARKNET_WALLET=$STARKNET_WALLET \
           --entrypoint starknet \
           starknet/cairo-lang \
           new_account --account starknet_1 --account_dir /work

Here it's important to use account_dir option to indicate where we want to save the account file. Once again is important to note that it's located in the persisten data location, because the default path would be ~/.starknet, which is not persistent after the container is deleted.

  1. Deploy an account (after adding some ETH to the account you just created) :
docker run --rm \
           -v ~/cairo:/work \
           -e STARKNET_NETWORK=$STARKNET_NETWORK \
           -e STARKNET_WALLET=$STARKNET_WALLET \
           --entrypoint starknet \
           starknet/cairo-lang \
           deploy_account --account starknet_1 --account_dir /work

You have to monitor the transaction to pass the PENDING status in order to continue.

  1. Declare the contract:
docker run --rm \
           -v ~/cairo:/work \
           -e STARKNET_NETWORK=$STARKNET_NETWORK \
           -e STARKNET_WALLET=$STARKNET_WALLET \
           --entrypoint starknet \
           starknet/cairo-lang \
           declare --contract /work/contract.json --account starknet_1 --account_dir /work
  1. Deploy the contract:
docker run --rm \
           -v ~/cairo:/work \
           -e STARKNET_NETWORK=$STARKNET_NETWORK \
           -e STARKNET_WALLET=$STARKNET_WALLET \
           --entrypoint starknet \
           starknet/cairo-lang \
           deploy --class_hash <class_hash> --account starknet_1 --account_dir /work

This is how you can use a container as a tool, making a script in your preferred language can help you run those commands easily.

If you want to have more separation between account and contract, you can mount several volumes. One for the contract, and the other for the account dir. This way, you can write some scripts to easily use the same account each time you are using those tools.

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