Lesson 1 - Getting started with ink!

In this lesson, you will learn how to install the necessary tools and deploy a simple smart contract.

1. Setup

This section demonstrates how to install the different tools to be able to develop on Aleph Zero.

To develop on Aleph Zero, you will need openssl installed. If it is not already installed, onpenssl can be installed with the following command:

+++ MacOS

brew install openssl

+++ Ubuntu

sudo apt-get install libssl-dev

+++ Protobuf is also needed and can be installed with the following command:

+++ MacOS

brew install protobuf

+++ Ubuntu

sudo apt update
sudo apt install protobuf-compiler

+++

You will need to first install Rust which means that you will need to have curl installed as well. Do not install curl with snap, use apt instead:

+++ MacOS

brew install curl  

+++ Ubuntu

sudo apt install curl  

+++ After installing curl, Rust can be installed with the following two commands.

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env 

The minimum version of rust that needs to be installed is 1.66.

==- ink! version 3 installation Following the Rust installation, toolchains need to be installed. This can be done thanks to the following commands

rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
rustup target add wasm32-unknown-unknown --toolchain nightly

Then, binaryen is needed and can be installed with the following command

+++ MacOS

brew install binaryen

+++ Ubuntu

sudo apt install binaryen

+++

Finally, the cargo package manager is required to develop on Aleph Zero and can be installed with one of the following commands

cargo install --git https://github.com/paritytech/cargo-contract.git --rev 4f831bc2e4b8f3fa5a6a4d1b3fa673e99807af8f

==- To install ink! v4, you just need to execute this command.

cargo install --force --locked cargo-contract

If you already started a project with ink! v3 please follow thise guidelines in order to migrate to ink! v4: Migration

  • Course_01:

2. Create and write your smart contract

The second section consists of writing a smart contract which plays the role of a computer which can perform addition and subtraction only. The smart contract will have the following element:

  • a global variable;

  • an addition function that will take a value as input to be added to the global variable;

  • a subtraction function that will take a value as input to be subtracted to the global variable.

The source code is avalaible ate the bottom of this page.

The command used to create the smart contract is the following.

cargo contract new computer 

The command above will create a folder computer with the following files:

  • Cargor.tolm: Rust Dependencies and ink! Configuration;

  • lib.rs: source code of your smart contract;

  • .gitingore.

  • Course_02:

3. Test & compile

In this this section, we will demonstrate how to test and compile your smart contract. First, we need to go in you project folder, this means for this example, we need to executed the command

cd computer

Then, the command to perform the tests on the contract is the following.

cargo test

After testing the smart contract, the compilation can be performed thanks to the following command ==- ink! v3 With ink! v3, we need the nightly toolchain, therefore, the following command needs to be executed:

cargo +nightly contract build

==-

cargo contract build
  • Course_03:

4. Deploy on the Aleph Zero Testnet

In this section, we will demonstrate how to deploy your contract on Aleph Zero testnet and how to interact with it. The video first demonstrates how to deploy and interact with a smart contract with a user interface. Then we will demonstrate a way to deploy and interact with your smart contract using the command line.

To deploy your smart contract you can first execute these two commands.

The first one to store your seed

export SEED="replace with your twelve words seed"

and the second one to store the URL of Aleph Zero testnet.

export URL="wss://ws.test.azero.dev"

Then you need to be in the folder of your project. In our case, we need to be inside the folder computer.

Then, this command will deploy the smart contract on Aleph Zero testnet

cargo contract instantiate --suri "$SEED" --url "$URL" --constructor new --args 100 -x

The command above will generate an address for your contract and this will generate

export CONTRACT="replace with address "

Then to interact, the following command can be used

cargo contract call --suri "$SEED" --url "$URL" --contract "$CONTRACT" --message add --args 101 -x

Note about the flag -x: This will execute your command on Aleph Zero testnet. Executing the command presented above without this flag will present you the expected command.

  • Course_04:

5. Deploy Locally

The last section demonstrate how to use substrate locally. First, we need to install the substrate you can download the binaries at the link binaries or build it locally from the git repository gitparitycheck

After downloading the binary, please open a terminal in the folder substrate-contracts-node-linux on linux or substrate-contracts-node-mac if you are using Mac and execute the following command:

./substrate-contracts-node

If you want have more information about substrate please visit substrate.io.

  • Course_05:

Sample Code

#![cfg_attr(not(feature = "std"), no_std)]

#[ink::contract]
mod computer {

    /// Defines the storage of your contract.
    /// Add new fields to the below struct in order
    /// to add new static storage fields to your contract.
    #[ink(storage)]
    pub struct Computer {
        /// Stores a single `i32` value on the storage.
        value: i32,
    }

    impl Computer {
        /// Constructor that initializes the `i32` value to the given `init_value`.
        #[ink(constructor)]
        pub fn new(init_value: i32) -> Self {
            Self { value: init_value }
        }

        /// Constructor that initializes the `i32` value to `0`.
        ///
        /// Constructors can delegate to other constructors.
        #[ink(constructor)]
        pub fn default() -> Self {
            Self::new(Default::default())
        }

        /// A message that can be called on instantiated contracts.
        /// This one add the input 'by' to the stored `value`
        #[ink(message)]
        pub fn add(&mut self, by: i32) {
            self.value += by;
        }

        /// A message that can be called on instantiated contracts.
        /// This one substact the input 'by' to the stored `value`
        #[ink(message)]
        pub fn sub(&mut self, by: i32) {
            self.value -= by;
        }

        /// Simply returns the current value of our `i32`.
        #[ink(message)]
        pub fn get(&self) -> i32 {
            self.value
        }
    }

    /// Unit tests in Rust are normally defined within such a `#[cfg(test)]`
    /// module and test functions are marked with a `#[test]` attribute.
    /// The below code is technically just normal Rust code.
    #[cfg(test)]
    mod tests {
        /// Imports all the definitions from the outer scope so we can use them here.
        use super::*;

        /// We test if the default constructor does its job.
        #[ink::test]
        fn default_works() {
            let computer = Computer::default();
            assert_eq!(computer.get(), 0);
        }

        /// We test a simple use case of our contract.
        #[ink::test]
        fn it_works() {
            let mut computer = Computer::new(100);
            assert_eq!(computer.get(), 100);
            computer.add(100);
            assert_eq!(computer.get(), 200);
            computer.sub(199);
            assert_eq!(computer.get(),1);
        }
    }
}

Last updated