The following is a demo of an exercise in the Cairo Smart Contract Hacking Course by JohnnyTime. A Live workshop was held at the Blockchain Security Academy, where we went through the exercise and explained the solution.
YouTube video of the workshop recording: TBD.
- Install asdf
- Using asdf, add scrab 2.6.3 as a plugin:
asdf plugin add scarb - Using asdf, install scarb 2.6.3 -
asdf install scarb 2.6.3 - Using asdf, set as a global var version -
asdf global scarb 2.6.3 - Install Starknet-Foundry 0.24.0
- Run -
curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | sh - Install version
0.23.0|snfoundryup -v 0.23.0
- Run -
- Install Universal Sierra Compiler
- Run -
curl -L https://raw.githubusercontent.com/software-mansion/universal-sierra-compiler/master/scripts/install.sh | sh
- Run -
In the following exercise, your goal is to create a simple smart contract with Storage, and Events, and the test is using Starknet-Foundry.
If you are not sure about the syntax, you can always refer to the Lecture video or to the Cheatsheet File.
In the file src\lib.cairo:
- Define an interface
IMyFirstCairoContractwith 2 functions:set_number()- receives a u256numberand returns nothing.get_number()- received nothing and returns a u256.
- Create a new cairo smart contract
MyFirstCairoContract:- Define the contract storage with one
u256variable namednumber. - Define an event that is called
NumberChanged, which will be emitted anytime the number is being changed in the storage, the event should be emitted with the old and new number - Create a constructor function that receives an
initial_valueu256 and writes it to storage, don't forget to emit aNumberChangedevent. - Implement the
IMyFirstCairoContractinterface, and bothset_number()andget_number()accordingly so they will set and get the number from the contract's storage, and emi$$ $$t an event in case the number is changed.
- Define the contract storage with one
In the file tests\test_contract.cairo:
- Import all the relevant libraries:
- Starknet Contract Address -
starknet::ContractAddress; - Starknet Foundry -
snforge_std::{declare, ContractClassTrait, start_prank, stop_prank, CheatTarget, start_warp}; - Your Cairo contract Dispatcher and Dispatcher Trait.
- Starknet Contract Address -
- Inside the test
first_cairo_contract_tests:- Declare the contract class.
- Prepare the constructor call data using
Serde. - Deploy the contract and create a Dispatcher.
- Check the initial value in the contract storage, and make sure it's correct (use
assert). - Update the number in storage to
1337. - Check the new value in the contract storage, and make sure it's correct (use
assert).
Bonus: In your test file, check that the right events were emitted after the number was changed.
To run all tests, use the command snforge test.