Technology Viewpoint | Want to develop dApp with Wasm? You have to read the introductory tutorial (1)

In the previous technical point of view article, we introduced how to implement a simple red envelope contract in C++ to help developers understand how to use C++ language to develop contracts on Ontology. In addition, we have briefly introduced development considerations for using the Rust language.

In this technical point of view and later related series, we will detail how to develop the Ontology Wasm contract using the Rust language. In this technical point of view, we will briefly introduce how to build and use contract templates for development.

Figure | Network

First, the environment to build

In order to improve the efficiency of development, it is recommended to prepare the following development environment before the development contract.

  • Rust development environment (required)
  • Integrated development environment (recommended)
  • Local Wasm Contract Test Node (recommended)

One thing to note here is that the local test node can be built to facilitate contract testing. At the same time, you can monitor the contract running information in the node log by adding debug information to the contract. Of course, if you feel that building a test node is complicated, we can also use the Ontology test network for contract testing.

1.1 Rust development environment to build

The Rust development environment can be completed in the following steps:

1. Install rustup . For Linux, Mac OS, and other Unix-like systems, you can execute the following commands directly and follow the on-screen prompts.

  Curl -sSf | sh 

If it is a system such as Windows, please visit the official website to download the appropriate version to install.

2. Install the rust compiler .

After installing rustup, you can install the rust compiler with the following command:

  Rusup install nightly 

Also, set the default compiled version to nightly:

  Rustus default nightly 

3. Install the Wasm32 compilation target .

Developers can install the Wasm32 compilation target with the following command:

  Rusup target add wasm32-unknown-unknown 
4. Install the ontio-wasm-build tool .
When we use the cargo tool to compile the contract into Wasm bytecode, the generated file will be larger. Ontio-wasm-build can optimize the bytecode, thus reducing the contract file size. Before deploying the contract to the chain, it must pass the Tools to optimize and check contracts.
  • The specific installation method is as follows: cargo install –git=

1.2 Installing the Integrated Development Environment

There are many options for integrated development environment IDEs and editing tools, such as Clion, IntelliJ, and vim. Among them, Clion is a powerful C/C++/Rust development tool that supports single-step tuning for local debugging of Wasm contracts. Developers can choose their favorite IDE or editing tools for development.

1.3 Local test node setup

Please refer to the Ontology official documentation for this section: Local Test Node Environment.

Note: As highlighted earlier, when the compiled executable is started, set the log level to debug mode. In this mode, developers can easily view the debug information of the contract run.

Second, the use of contract templates to develop Wasm contracts

To use the contract source code developed by Rust to run on the Ontology chain, go through the following steps:

1. You need to compile the source code into Wasm bytecode first.

2. Optimize the Wasm bytecode using the ontio-wasm-build tool.

3. Deploy the optimized Wasm bytecode to the chain.

4. Make a call to the method in the contract.

Below is a simple example of developing a Wasm contract using a contract template to introduce the entire process.

2.1 Obtaining Wasm Contract Template

In order to facilitate developers to start Ontology Wasm contract development, we provide a contract template (Rust version), developers only need to clone the code, and then add their own contract logic.

  Git clone 

The directory structure is as follows:
 ├── .cargo
 │ └── config
 ├── Cargo.toml
 └── src

We explain some of these files:

  • The configuration file of the contract compile is configured in the config file below the .cargo folder. The contents of the config file are as follows:
 Rustflags = [
 "-C", "link-args=-z stack-size=32768"

[target.wasm32-unknown-unknown] indicates the compilation target, rustflags configures the compiled link parameters. Here, the default stack size is set to 32768, which is 32 kb, and the maximum stack size that the contract can use during the running process.

  • The Cargo.toml file is some basic configuration information for the contract, and its contents are as follows:
 Name = "rust-wasm-contract-template"
 Version = "0.1.0"
 Authors = ["name <>"]
 Edition = "2018" 

# See more keys and their definitions at

Crate-type = ["cdylib"] #Compile as a dynamic link library

Ontio-std = {git = ""}

Mock = ["ontio-std/mock"]

Among them, in the [lib] configuration module, crate-type = ["cdylib"] means that the project is compiled into a dynamic link library for being called by other languages.
[dependencies] is used to configure project dependency information. The ontio-std library required for Ontology Wasm contract development is introduced here.
[features] is used to turn on some unstable features and can only be used in the nightly version of the compiler.
  • The file encapsulates the functions of compiling the contract and optimizing the contract. After the contract is developed, executing the script will place the optimized contract bytecode under the output directory.
  • Src/ is used to write contract logic code. The code in the contract template is as follows:
 Use ontio_std::runtime; 

Fn invoke() {

The contract template implements a simple return hello function. Some simple instructions for this template are as follows:
  • #![no_std] means to mask the interfaces in the rust std library, but developers can call the apis in the rust core library.
  • #[no_mangle] indicates that the invoke function is exported when compiled into wasm bytecode. The invoke function is the entry function of the Ontology Wasm contract and needs to be exported.
  • The runtime module encapsulates the interface between the contract and the chain, and runtime::ret() is used to return the result of the contract execution to the caller.

2.2 Compilation contract

Developers can implement contract compilation and contract bytecode optimization directly by executing the script.


If the following permission error occurs during the execution:

  -bash: ./ Permission denied 

Then, you can give the file executable permission first:
  Sudo chmod +x ./ 

After the execution is successful, the output directory is generated in the current directory. The directory structure of output is as follows:

  ├── output
 │ ├── rust_wasm_contract_template.wasm
 │ └── rust_wasm_contract_template.wasm.str 

Where rust_wasm_contract_template.wasm is the Wasm bytecode file generated by our compiled contract source code. Rust_wasm_contract_template.wasm.str is a hex-encoded file of Wasm bytecode.

2.3 Deployment contract

The compiled Wasm contract needs to be deployed on the chain to run. We can deploy the above contract bytecode file to the test network, or the local test node. Let's take the example of deploying to the local test network:

First, start the local test node, we need to be a wallet file before starting:

  ./ontology account add 
The above command can be used in the process of the default configuration, and then execute the following command to start the local test node:
  ./ontology --testmode --loglevel 1 
–loglevel 1 indicates that the log level of the node is debug. If there is debug information in the test contract, it will be displayed in the node log.
Then, open another terminal window for contract deployment.
  $ ./ontology contract deploy --vmtype 3 --code ./rust_wasm_contract_template.wasm.str --name helloworld --author "author" --email "email" --desc "desc" --gaslimit 22200000
 Deploy contract:
   Contract Address: 0be3df2e320f86f55709806425dc1f0b91966634
   TxHash: bd83f796bfd79bbb2546978ebd02d5ff3a54c2a4a6550d484689f627513f5770 

Using './ontology info status bd83f796bfd79bbb2546978ebd02d5ff3a54c2a4a6550d484689f627513f5770' to query transaction status.

If an error message with insufficient gaslimit is available, set a larger gaslimit parameter.

2.4 Test Contract

Now let's call the method in the contract and execute the following command:

  $ ./ontology contract invoke --address 0be3df2e320f86f55709806425dc1f0b91966634 --vmtype 3 --params '' --version 0 --prepare
 Invoke:346696910b1fdc2564800957f5860f322edfe30b Params:null
 Contract invoke successfully
   Gas limit: 20000
   Return: 68656c6c6f (raw value) 

In order to be able to see the result of the contract execution return, we added a –prepare tag to the command to indicate that the transaction is a pre-executed transaction.

As you can see, on the command line, we get 68856c6c6f, which is the hex encoding format of the expected result hello, we only need to use hex decoding to get the expected result.

Third, the conclusion

In this issue of technical point of view, we briefly introduced how to use the Rust language for Wasm development on Ontology, how to build the environment and use contract templates for development. In addition, a new version of SmartX that supports Ontology Wasm contract deployment and invocation is under development and will be available soon. Its on-line will greatly facilitate developers to deploy Ontology Wasm contracts and call related functions.

Ontology welcomes more Wasm technology enthusiasts to join the ontology development community to create a technological ecosystem.