Skip to content

Latest commit

 

History

History
209 lines (156 loc) · 7.22 KB

Cairo1.md

File metadata and controls

209 lines (156 loc) · 7.22 KB

Cairo 1&2 smart-contracts in Starknet network

Starknet.js

Introduction

Take advantage to use Starknet.js to deploy and use your new Cairo 1&2 smart-contracts.
The Cairo compiler provides an abi in the .sierra.json file. Today, this abi isn't fully mature, and some things are missing to have an handling similar to Cairo 0 contracts. Nevertheless, Starknet.js proposes a temporary solution for the early adopters of Cairo 1&2 smart-contracts.

It's realistic to hope to have a Cairo compiler providing a complete abi somewhere in May/2023 2023.

Prerequirements:

You need to have :

  • Starknet-devnet ^0.5.5 here.
  • Cairo installed, from Starkware repo, branch v2.0.0 here.
  • Starknet.js ^5.16.0 here.

Compilation of Cairo 1&2:

We will use a small Cairo smart-contract, available here.

compile the .cairo file:

Go in your cairo directory, launch the compiler (adapt the path to your config):

cd cairo
cargo run --bin starknet-compile -- ../contracts/cairo200/PhilTest2.cairo ../out/cairo200/PhilTest2.sierra.json

compile the .sierra file:

cargo run --bin starknet-sierra-compile -- ../out/cairo200/PhilTest2.sierra.json ../out/cairo200/PhilTest2.casm.json

Deploy a Cairo 1&2 contract with Starknet.js:

Launch starknet-devnet with this option :

starknet-devnet --seed 0

You can find 2 little scripts to deploy a contract :

  • one to declare and deploy in 2 steps here.
  • one to declare and deploy in 1 step here.

The first script can be launched with :

npx ts-node src/scripts/cairo11-devnet/4.declareThenDeployTest.ts

You can easily change the network to use :

  • Testnet :
const provider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI } });
  • Testnet-2 :
const provider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI2 } });

And adapt in consequence the address and the private key to one of your account present in this network.

You can find this contract already deployed in testnet :

  • Testnet address : 0x033de869eb1905fe503610527c51e245119bd05c231e7165c95d6fb630fe05ff

Interact with your Cairo 1&2 contract:

You can find a little script to interact with a Cairo 1 contract : here

Now, you have 2 ways to exchange data with Starknet :

For compatible types of data :

bool, u8, u16, u32, usize, u64, u128, u256, ContractAddress are compatible.
Tuple, struct and array (made of literal types) are compatible.
In this case, use this code :

const res = await myTestContract.test1(100) // send a felt252
    console.log("res1 =", res); // felt252 -> bigint

For not yet compatible types :

Complex objects, enums(Option or custom), some mix of types are not yet compatible. In this case, follow these rules (valid for all types, including compatible ones) :

Use CallData.compile() to prepare the parameters to send to the smart-contract.

Use only meta-class to interact with your contract (ex : contract.getBalance())

For a @view function, do not forget these options for Cairo :

{
    parseRequest: false,
    parseResponse: false,
}

The answer is in an array of Hex numbers. ex : result[0] for the first value. An array returns the size, then the elements. An Uint256 returns 2 numbers (low,high).

Ex :

const par1 = CallData.compile({ balance: 100 }) 
const res1 = await myTestContract.test1(par1, { parseRequest: false, parseResponse: false, });
const tx = await myTestContract.increase_counter(
CallData.compile({
        amount: 100,
    })
    );
console.log("res1 =", res1[0]); // Hex string

Debug

Debug.print() is not allowed in Cairo 1&2 code for Starknet network.

Hereafter is a way to debug anyway your Cairo contract, but a specific configuration is necessary :

Compilation

You need a customized lib_funcs.json file in your project.
The original file is in the Starkware repo : here. You have to insert a line with "print",, like this :

{
    "allowed_libfuncs": [
        "print",
        "alloc_local",
        "array_append",
        "array_get",
        "array_len",
        ...

My lib_funcs.json is here.

We will test the print function with this small example (available here) :

#[external(v0)]
    impl HelloContract of super::IHelloContract<ContractState> {
        fn Say_HelloPhil126(ref self: ContractState, message: felt252) {
            let caller = get_caller_address();
            self.emit(Hello { from: caller, value: message }); // event

            'Hello, Philippe!'.print();
            123.print();
            message.print();
        }
    }

Note the last lines, with the .print() command. The following commands are operational :

'Hello, Philippe!'.print();
123.print();
let a:u32 = 200;
a.print();

The compilation of the .cairo file needs some extra options :

cargo run --bin starknet-compile -- --allowed-libfuncs-list-file ./pathto/lib_funcs.json ./src/hello/hello.cairo ./out/hello/hello.sierra.json

Of course, adapt pathto to your config.

Same thing to compile the .sierra :

cargo run --bin starknet-sierra-compile -- --allowed-libfuncs-list-file ./pathto/lib_funcs.json ./out/hello/hello.sierra.json  ../out/hello/hello.casm.json 

Devnet

Launch Starknet-devnet with these options :

starknet-devnet --seed 0 --compiler-args '--allowed-libfuncs-list-file ./pathto/lib_funcs.json --add-pythonic-hints' 2> /dev/null &

Note the PID of process, displayed in the first line (ex : [1] 954825). It will be necessary at the end of the process.

Interact with the contract :

In the SAME bash window, launch the Starknet.js script that will deploy and interact with the contract (available here) :

npx ts-node src/scripts/cairo11-devnet/4c.declareAndDeployHello.ts

This script includes :

const th = await myTestContract.Say_HelloPhil126(200);

The following answer is printed in the bash window : 96231036770510887785732922765483205921

It can be decoded with this Starknet.js command :

console.log("Decoded message =", shortString.decodeShortString("96231036770510887785732922765483205921"));

(script available here)

And the answer is : Hello, Philippe!

Do not forget to kill the process of Devnet when you have ended to work with it (ex : kill 954825).

So, we can debug a Starknet Cairo 1 contract in Devnet with this process.

Questions?

Do not hesitate to report your feedback and your questions in Discord.