1- An Introduction to write Smart Contracts in Rust and Ink!
Prerequisites
Cargo contract installed: https://polkaverse.com/9768/technical-guide-install-cargo-contract-37738
At least on the following node is ready :
- swanky node: https://github.com/AstarNetwork/swanky-node/releases
- substrate contract node: https://github.com/paritytech/substrate-contracts-node/releases
This tutorial uses Ubuntu 22.04, cargo 1.67, cargo contract 2.0 and swanky node
Create a new project
Use the command “cargo contract new“ to create a new rust project (in this tutorial the project name is incrementer)
cargo contract new incrementer
A new rust project is created with two files:
- Cargo.toml : cargo manifest file
- lib.rs : source code file
These files are generated based on the template flipper (our « hello world » template)
In the cargo manifest file we can see the dependency on the crate ink
In the source code file (lib.rs) we have :
The macro #[ink :contract]
Applied to the module, this macro is responsible for generating all of the code necessary for interracting with the Contracts pallet
More information here: https://use.ink/macros-attributes/contract
The macro #[ink(storage)]
Applied on struct
types in order to flag them for being the contract's storage definition. There can only be one ink! storage definition per contract.
More information here: https://use.ink/macros-attributes/storage
The macro #[ink(constructor)]
Applicable to a method.
Flags a method (or multiple methods) for the ink! storage struct as constructor making it available to the API for instantiating the contract.
More information here: https://use.ink/macros-attributes/constructor
The macro #[ink(message)]
Applicable to methods.
Flags a method for the ink! storage struct as message making it available to the API for calling the contract.
More information here: https://use.ink/macros-attributes/message
In our tutorial, we will update the generated code based on the flippera template in order to have a contract who increments an integer.
So we will :
- change the struct Incrementer to manage an integer
- Update the constructor to manage an integer
- implement the method “inc” to increment the value
- implement the method get to read the data
Use the command “cargo contract build” to compile the project
cargo contract build
After building, you will have three artifacts :
- incrementer.wasm: the contract’s WebAssembly blob (the contract code)
- incrementer.json: a JSON file that contains just the contract’s metadata, used by the tools to interact with your contract
- incrementer.contract: bundle with the combination of the metadata and the wasm code
Note: you can see the size of the contract . The default is to build the contract in debug which is usefull for developement because you can use the debug messages but you can see the size of size is 17.2K
If you build with the release mode, the size will be significantly lower
cargo contract build --release
Contract size is really important from a cost perspective. Smaller is the contract, cheaper is the interaction with the contract.
Deploy the contract
Before deploying the contract we start a local node node in the background. In this tutorial we will swanky node
Upload the contract code
Use the command “cargo contract upload” to deploy the contract code
cargo contract upload --suri //Alice
Note : In the local node, some accounts are predefined: //Alice //Bob, ….
You can replace it by your mnemonic phrase but it is not recommended to do it! cargo contract cli is useful for development purpose.
Here we can see ExtrinsicSuccess and CodeStored events and the code hash storedInstantiate the contract
Use the command “cargo contract instantiate” to instantiate a new contract
cargo contract instantiate --suri //Bob --constructor new --args 3
Note :
- The account who uploads the contract code or instantiates a new contract can be different.
- Here we use the constructor “new“ with the value “3“ as parameter.
- First, a dry run is done to estimate the gas required. Enter Y to submit the call.
Note : If you instantiate the contract without uploading the code before, the system will automatically both of them
Interact with the contract - read a value
Use the command “cargo contract call” to call a method and use the option “dry-run” to read a value
cargo contract call --contract <<contract address>> --suri //Bob --message get --dry-run
Note : We call the method get and the current value is 3
Interact with the contract
Use the command “cargo contract call” to call a method to interact with the contract
cargo contract call --contract <<contract address>> --suri //Bob --message inc --args 2
Note :
- We call the method “inc“ with the value “2“ as parameter
- First, a dry run is done to estimate the gas required. Enter Y to submit the call.
If you read again the value (method get) you will see the new value is 5
cargo contract call --contract <<contract address>> --suri //Bob --message get --dry-run
Introduce debug message
You can display some messages for debugging. It can be usefull during developement.
This message will be display only :
- if you compile without release mode
- you use the option dry-run
Exemple:
cargo contract call --contract <<contract address>> --suri //Bob --message inc --args 8 --dry-run
Note: Sorry for the typo
Adding a custom event
Define an event, named “Incremented” with the following values:
- by: the increment value
- value: the new value
- who: the account id who incremented the value.
Emit the event in the method “inc”
Build and Instantiate the new contract and call the method inc
cargo contract build
cargo contract instantiate --suri //Bob --constructor new --args 3
cargo contract call --contract <<contract address>> --suri //Bob --message inc --args 5
Your custom event is emmitted!
Note: If you have the error “DuplicateContract“ when instantiate a new contract, just stop and start again your node
Contracts UI
You can use the app https://contracts-ui.substrate.io/ to instantiate new contracts and interact with them.
Select the correct node (local node for us)
Upload and Instantiate a new contract
Select the contract bundle (incrementer.contract in our case) and follow the instructionsAnd you will be able to interact with this contract
Git repository
https://github.com/GuiGou12358/astar-tutorials/tree/main/tuto1
Crypto-enthusiast, Defi & NFT believer, Dotsam Fam Astar Tech Amb & Phala Amb Web2 builder gradually migrating to Web3
Tutorials to write Smart Contracts in Rust and Ink!
0 comments