Author: Zhu Chunlei

Author’s note: We won’t go into ink! Syntax details, mainly introduces the construction of the programming environment, and guide readers to gradually complete the creation, compilation, testing and deployment of smart contract, specific INK! The syntax will be explained in detail in the next article. In addition, this series of articles will assume that the reader already knows the basic syntax of Rust, so it will not cover the interpretation of Rust syntax. If you are not familiar with the basic syntax of Rust, you can refer to the relevant resources or purchase the Rust Primer, Rust Programming, Practice, and Progression, which is recommended below.

1.1 ink! Introduction to the

Parity official link! The definition of “INK! is an eDSL to write smart contracts in Rust for blockchains built on the Substrate framework. ink! Contracts are compiled to WebAssembly. “That is, ink! The embedded Domain Specific Language (eDSL) developed by Rust is used to write WASM (WebAssembly) smart contract for blockchain built on Substrate framework.

WASM is a new bytecode format, a new low-level binary syntax, which compiles code instructions with small size, portability, fast loading and other characteristics. Compared to evM-based Solidity Smart contracts, WASM smart contracts consume less resources, run contracts faster and more reliably, and network transfer information more efficiently. WASM supports bytecode compiled by smart contracts written in Rust, C/C++, C#, Go, and Typescript. Currently, Substrate, ETH 2.0, and several alliance chains all indicate that they will support WASM smart contracts.

1.2 Setting up the programming environment

“To do a good job, you must sharpen your tools.” At the start of ink! Before programming, you need to install and configure the associated programming environment.

1.2.1 Installation and Configuration in the Rust Environment

1. Install the Rust

Rust is installed and managed by the tool Rustup. Rustup is both a Rust installer and a version management tool.

Run the following command from your terminal to download and install the latest stable version of Rust.

Curl, proto '= HTTPS' - tlsv1.2 - sSf https://sh.rustup.rs | shCopy the code

If the installation is successful, the following will appear.

Rust is installed now. Great!
Copy the code

2. Set the PATH environment variable

In the Rust development environment, all Rust tools such as RUSTC, cargo, and Rustup are installed in ~/.cargo/bin, which we can add to the PATH environment variable.

Add the following to the ~/.bash_profile file:

export PATH="$HOME/.cargo/bin:$PATH"
Copy the code

Save the file, return to the terminal command line window, and use the source command to make the configuration take effect immediately.

source ~/.bash_profile
Copy the code

Run the following command to check that the PATH environment variable is set correctly.

rustc --version
Copy the code

The environment variable is set successfully if the version number, commit hash, and date of the latest stable release of Rust are displayed. If you do not see this information, check that the PATH environment variable in the ~/.bash_profile file is set to the correct PATH.

1.2.2 ink! Environment installation and configuration

With the basic Rust environment configured, let’s configure ink! The required development environment.

1. Install the WASM tool chain

Because of the ink! Rust WASM tool chain is required, and WASM can only run under the Nightly tool chain. We need to prepare the WASM compilation environment.

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

2. Install the cargo – contract

You can install Parity’s cargo Contract tool for compiling smart contracts.

Cargo install cargo-contract --force --feature= "binaryen-as-dependency"Copy the code

You can also use the cargo Contract provided by Patract, which prints detailed error messages in conjunction with Europa.

Cargo install cargo - contract - git https://github.com/patractlabs/cargo-contract - branch = v0.10.0 - forceCopy the code

3. Install blockchain nodes

Smart contracts must run on blockchain and the sandbox Europa developed by Patract for smart contract testing is recommended (github.com/patractlabs… Providing detailed logs during the deployment and invocation of smart contracts can show the operation of the “black box” of contract modules to the maximum extent, which is of great help to developers.

You can run the following command to install Europa locally.

cargo install europa --git https://github.com/patractlabs/europa --locked --force
Copy the code

1.2.3 Node Environment Installation and Configuration

The Redspot used below requires Node, so make sure your system has Node version >= 12.0 installed. If not, you can visit the official website (nodejs.org/zh-cn) to install it or…

1.3 use the ink! CLI development ink! project

1.3.1 Creating a FLIpper contract

Use the cargo Contract new command to create the smart contract project flipper under the current directory.

cargo contract new flipper
Copy the code

The directory structure for flipper is shown below.

flipper|+-- .gitignore|+-- Cargo.toml|+-- lib.rs
Copy the code

The core code for the flipper contract is in the lib.rs file, as shown in Listing 1-1. A flipper is a simple contract containing only a Boolean object that converts a Boolean value (from true to false, or from false to true) through the flip method and returns the current state of the Boolean object through the GET method.

Listing 1-1 Flipper contract code

#! [cfg_attr(not(feature = "std"), no_std)]use ink_lang as ink; #[ink::contract]mod flipper { /// 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 Flipper { /// Stores a single `bool` value on the storage. value: bool, } impl Flipper { /// Constructor that initializes the `bool` value to the given `init_value`. #[ink(constructor)] pub fn  new(init_value: bool) -> Self { Self { value: init_value } } /// Constructor that initializes the `bool` value to `false`. /// /// 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 flips the value of the stored `bool` from `true` /// to `false` and vice versa. #[ink(message)] pub fn flip(&mut self) { self.value = ! self.value; } /// Simply returns the current value of our `bool`. #[ink(message)] pub fn get(&self) -> bool { 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::*; /// Imports `ink_lang` so we can use `#[ink::test]`. use ink_lang as ink; /// We test if the default constructor does its job. #[ink::test] fn default_works() { let flipper = Flipper::default();  assert_eq! (flipper.get(), false); } /// We test a simple use case of our contract. #[ink::test] fn it_works() { let mut flipper = Flipper::new(false); assert_eq! (flipper.get(), false); flipper.flip(); assert_eq! (flipper.get(), true); }}}Copy the code

1.3.2 Compiling the Flipper contract

To compile the contract, run the following command.

cargo +nightly contract build
Copy the code

The target/ink folder will be created in the current directory after the code is successfully compiled. The folder contains three important files: flipper. Contract, flipper. Flipper. Wasm is a bytecode file for compiled code, and metadata.json is a metadata file that contains information about methods that can be invoked as provided by the contract. Flipper. Contract is a file that combines flipper. Wasm and metadata.json to be used when deploying contracts on the blockchain.

1.3.3 Testing the flipper contract

You can unit test the contract by running the following command.

cargo +nightly test
Copy the code

If you see the following results, the test has successfully completed.

running 2 teststest flipper::tests::it_works ... oktest flipper::tests::default_works ... oktest result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; Finished in 0.00 sCopy the code

1.4 Developing INK! Using the Patract tool suite project

Patract Labs provides a comprehensive solution for Boca WASM smart contract development, providing developers with a full stack of tools and services that cover the development, testing, debugging, deployment, monitoring and front-end development phases.

Here we mainly use Redspot and Europa from the Patract tool suite. Redspot is a scaffolding tool for smart contract development, testing and debugging. Europa provides simulation nodes of the smart contract operating environment and logs contract execution information during the running process.

1.4.1 Creating a Flipper Contract

Redspot offers contract development templates that allow users to quickly build a project. Executing the following command will pull the latest version of Redspot and build the project using erC20 as a template.

npx redspot-new flipper
Copy the code

The directory structure for flipper is shown below.

flipper|+-- contracts|  ||  +-- Cargo.toml|  ||  +-- lib.rs|+-- scripts|  ||  +-- deploy.ts|+-- tests|  ||  +-- erc20.test.ts|+-- .gitignore|+-- package.json|+-- redspot.config.ts|+-- tsconfig.json
Copy the code

Modify the contracts/lib.rs file to replace the original code with the code in Listing 1-1.

1.4.2 Compiling the Flipper contract

Run the NPX redspot compile command to compile the contract. With the compile command, we can pass in the path of contracts to specify which contracts to compile, and the command shown below will compile only contracts under the contracts/flipper directory.

npx redspot compile contracts/flipper
Copy the code

After compiling, you can find the Flipper. Contract and Flipper. Json files in the artifacts directory. Flipper. Json is the metadata file and Flipper. Contract is used when deploying contracts on the blockchain.

1.4.3 Testing the FLIpper contract

You can use Redspot to unit test contracts. First, delete the default erc20.test.ts file in the Tests directory and create flipper.

Listing 1-2 flipper unit test script

import BN from 'bn.js'; import { expect } from 'chai'; import { patract, network, artifacts } from 'redspot'; const { getContractFactory, getRandomSigner } = patract; const { api, getSigners } = network; describe('Flipper', () => { after(() => { return api.disconnect(); }); async function setup() { const one = new BN(10).pow(new BN(api.registry.chainDecimals[0])); const signers = await getSigners(); const Alice = signers[0]; const sender = await getRandomSigner(Alice, one.muln(10000)); const contractFactory = await getContractFactory('Flipper', sender); const contract = await contractFactory.deploy('new', false); const abi = artifacts.readArtifact('Flipper'); const receiver = await getRandomSigner(); return { sender, contractFactory, contract, abi, receiver, Alice, one }; } it('Initial value', async () => { const { contract } = await setup(); const result = await contract.query.get(); expect(result.output).to.equal(false); }); it('Flip value', async () => { const { contract } = await setup(); await contract.tx.flip(); const result = await contract.query.get(); expect(result.output).to.equal(true); }); });Copy the code

Second, ensure that the blockchain node information is correctly configured before running the test command, using the default configuration in the redspot.config.ts file.

Finally, start the local development node with the Europa command.

europa --tmp
Copy the code

Run the NPX redspot test command for unit tests. For the test command, we can pass in the path of the unit test script to specify which contracts to test. The command shown below will unit test only flipper contracts, with –no-compile to avoid running the compile command automatically.

npx redspot test tests/flipper.test.ts --no-compile
Copy the code

If you see the following result, the test has been successfully completed, and Redspot’s plug-in automatically calculates and prints out the Gas charges for performing the contract operation.

1.4.4 Deploying the FLIpper contract

In Substrate, the process of deploying the contract is divided into two steps:

  • Upload the code to the blockchain
  • Creating a contract instance

In this mode, code such as standard ERC20 contract can be instantiated any number of times after being uploaded once, avoiding wasting storage space on the blockchain by uploading source code for the same function.

The next step is to start the local development node using the Europa command as well.

europa --tmp
Copy the code

Open the urlpolkadot.js.org/apps, configure local connection…

On the menu bar, click the submenu “Contract” under “Developer”, open the contract page, and click the “Upload & Deploy Code” button.

The upload & Deploy Code 1/2 window corresponds to the first step of the deployment contract — uploading code to the blockchain. Select the deployment account with the balance, upload the Flipper. Contract file, confirm the smart contract information, and click the “Next” button.

The upload & Deploy Code 2/2 window corresponds to the second step of the deployment contract, creating the contract instance. Set the donation amount to pay the contracted storage rent and Gas, and click the Deploy button.

In the Approve Transaction window, click the Sign and Submit button to complete the contract deployment.

1.4.5 Invoking the FLIpper contract

The Flipper contract has been successfully deployed and is ready to interact with it!

We can see that the current value of the Boolean object is false because the initial value was set to false when the contract instance was created.

Click the “exec” button to the left of “flip()” to call the flip method of the contract, and the current value of the Boolean object becomes true after the signature is submitted. The contract interaction results as expected.

We can see the Patract tool suite for developing INK! The project brings great convenience, and the examples in future articles in this series will be built using the Patract suite of tools.

1.5 Reference Materials

  1. ink! Smart Contracts Tutorial

Substrate. The dev/substrate – c… 2. ink! The official document is paritytech.github. IO /ink-docs

  1. Official document of Patract

docs.patract.io