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
- ink! Smart Contracts Tutorial
Substrate. The dev/substrate – c… 2. ink! The official document is paritytech.github. IO /ink-docs
- Official document of Patract
docs.patract.io