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 :

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 stored

Instantiate 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.

Here we can see ExtrinsicSuccess and Instantiated events and the contract account

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 instructions

And you will be able to interact with this contract

Git repository

https://github.com/GuiGou12358/astar-tutorials/tree/main/tuto1

0
GuiGouPost author

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

Tutorials to write Smart Contracts in Rust and Ink!