An example repository to demonstrate how to build on Kakarot.
- Docker
- Yarn
- Foundry
- Scarb and Starkli if you want to deploy Cairo contracts. Make sure to install starkli version
0.2.9
withstarkliup -v v0.2.9
Run the following command to setup the git submodules.
make setup
To get started, you will need to run the local nodes. You can do this by running:
make start
This will start an Anvil Node (that runs the L1 contracts for L1 <> L2 messaging) at address http://127.0.0.1:8545
and a Kakarot Node at address http://127.0.0.1:3030
Kakarot is deployed along with commonly used contracts, such as Multicall3, CreateX and the Arachnid Proxy.
To deploy the L1 messaging contracts, you can run:
make deploy-l1
This will deploy the L1 messaging contracts on the Anvil node.
You can deploy contracts on Kakarot using the regular EVM tooling, without any modifications. For example, this is how you would deploy a simple Counter contract:
export PRIVATE_KEY = <your_private_key>
export ETH_RPC_URL=http://127.0.0.1:3030
forge create solidity_contracts/src/examples/Counter.sol:Counter --private-key $PRIVATE_KEY
This will deploy the Counter contract on Kakarot and return the address of the deployed contract.
You can then interact with the contract using cast
.
- Increment the counter
cast send 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 "increment()" --private-key $PRIVATE_KEY
- Check the current counter value:
cast call 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 "number()"
As Kakarot is an EVM-L2 using the Starknet Stack, you can natively interact with Cairo contracts from the EVM. This opens up a world of possibilities complex and resource-intensive applications on Kakarot, while benefiting from the performance of the cheapest zkVM, Cairo.
Once scarb is installed in version 2.5.4
, cd
into the cairo_contracts
directory and build the Counter
cairo contract:
cd cairo_contracts && scarb build && ../
Once built, you can deploy the contract using the starkli
. First, set an account up (using the default Katana private key, no password):
export STARKNET_KEYSTORE="katana.key.json"
export STARKNET_ACCOUNT="katana.account.json"
export STARKNET_RPC="http://127.0.0.1:5050"
starkli declare cairo_contracts/target/dev/cairo_contracts_Counter.contract_class.json
This will output the contract's class hash. You can use this hash to deploy the contract:
starkli deploy 0x0358920a52bd68242bcef41f40531dac7243c8f0e308ebfb440d269cf063ad92 --salt 1
This will give you the starknet address of the deployed Counter contract. You can interact with it using the starkli
tool.
starkli invoke 0x01bdce28ce9c2a69e36a89a1c6cb2a927847a8991f9deda62086fb79f51955a0 increment
starkli call 0x01bdce28ce9c2a69e36a89a1c6cb2a927847a8991f9deda62086fb79f51955a0 number
The CairoCounterCaller.sol
contract demonstrates how one can interact with the Cairo Counter contract from Solidity. The Cairo Counter is deployed on the "Starknet side" of Kakarot and can be interacted with from the "EVM side" of Kakarot.
Let's deploy the CairoCounterCaller
contract, providing as constructor argument the starknet address of the deployed Cairo Counter contract:
⚠️ Don't forget to update the commands with your actual values
forge create solidity_contracts/src/examples/CairoCounterCaller.sol:CairoCounterCaller --constructor-args 0x01bdce28ce9c2a69e36a89a1c6cb2a927847a8991f9deda62086fb79f51955a0 --private-key $PRIVATE_KEY
This will deploy a solidity contract, on Kakarot, that is able to interact with the Cairo Counter contract. However, before that, we need to whitelist this contract to authorize it to call arbitrary contracts on the Starknet side.
make whitelist-contract CONTRACT_ADDRESS=0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9
You can then interact with the CairoCounterCaller
contract using cast
. By calling incrementCairoCounter()
, the contract will call the Cairo Counter contract to increment the counter.
cast send 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 "setCairoNumber(uint256 newNumber)" 10 --private-key $PRIVATE_KEY
We can then verify the counter value by calling getCairoNumber()
on the solidity contract, or number
on the Cairo contract.:
cast call 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 "getCairoNumber()"
> 0x000000000000000000000000000000000000000000000000000000000000000a
The DualVMToken
contract demonstrates how one can deploy a token that is able to interact with both the EVM and Cairo contracts. The token is deployed on the Cairo side and can be interacted with from the EVM side.
Let's deploy the DualVMToken
Cairo contract:
starkli declare cairo_contracts/target/dev/cairo_contracts_DualVMToken.contract_class.json
starkli deploy 0x007cadcf5c04b02dae809a2700b85ff87aca8a3117e67e9aec24c5513730b1c1 100 0 0xb3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca --salt 1
This will deploy a token contract on the Cairo side. You can interact with it using the starkli
tool.
starkli call 0x015c370e6ad1799fc94b61982b72f2507bb88d0fc788153f7b052e55f7ea59bf "balance_of" 0xb3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca
[
"0x0000000000000000000000000000000000000000000000000000000000000064",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
Now, let's build the EVM contract that will enable interactions with this token from the EVM side.
make copy-env
KAKAROT_ADDRESS=$(grep KAKAROT_ADDRESS .env | cut -d '=' -f2)
forge create solidity_contracts/src/examples/DualVMToken.sol:DualVMToken --constructor-args $KAKAROT_ADDRESS 0x015c370e6ad1799fc94b61982b72f2507bb88d0fc788153f7b052e55f7ea59bf --private-key $PRIVATE_KEY
Don't forget to whitelist the contract to authorize it to call arbitrary contracts on the Starknet side.
make whitelist-contract CONTRACT_ADDRESS=0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
You can now interact with the DualVMToken
contract using cast
. By calling name()
, the contract will call the Cairo token contract to get the token name. When transferring tokens, the contract will resolve the Starknet addresses of the EVM accounts, and perform the transfer on the Cairo side. This is entirely transparent, and the user does not need to know about what happens under the hood: it acts as a regular ERC20.
cast call 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 "name()"
To run the hardhat test suite, you can run:
make test