(## 什么是 WASM

Ink! 环境配置

在配置了基本的 Rust 环境后,我们可以配置 Ink! 所需的开发环境了。

# for substrate rustup component add rust-src --toolchain nightly rustup target add wasm32-unknown-unknown --toolchain stable # for canvas node  cargo install canvas-node --git https://github.com/paritytech/canvas-node.git --tag v0.1.4 --force --locked # for ink!CLI cargo install cargo-contract --vers 0.10.0 --force --locked

我们还要安装/升级binaryen,Binaryen 是 WebAssembly 的编译器。

Mac 上安装:

# for mac brew upgrade binaryen # 如果没安装用 brew install

Linux 上安装:

创建一个 ink! 项目

执行如下命令:

cargo contract new flipper

创建完成后进入文件夹:

cd flipper/

合约项目目录结构:

flipper | +-- lib.rs                <-- Contract Source Code | +-- Cargo.toml            <-- Rust Dependencies and ink! Configuration | +-- .gitignore

合约测试

cargo +nightly test

一切顺利的话会输出如下结果:

$ cargo +nightly test     running 2 tests     test flipper::tests::it_works ... ok     test flipper::tests::default_works ... ok      test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

合约编译

cargo +nightly contract build

Hello, Ink! | 用 Rust 写智能合约(一)

如果顺利的话,目录下会生成target/ink文件夹,里面包含如下文件:

Hello, Ink! | 用 Rust 写智能合约(一)

其中,flipper.contract 是部署时要用的合约文件,可以视为solidity合约中的bin文件。

metadata.json是元数据,可以视为solidity合约中的abi文件。

合约部署

通过canvas启动一个本地运行的开发节点!

canvas --dev --tmp

Hello, Ink! | 用 Rust 写智能合约(一)

打开如下网址,这个页面会自动连接本地启动的开发节点:

https://paritytech.github.io/canvas-ui

Hello, Ink! | 用 Rust 写智能合约(一)

上传flipper.contract这个文件:

Hello, Ink! | 用 Rust 写智能合约(一)

一路点击进行部署:

Hello, Ink! | 用 Rust 写智能合约(一)

Hello, Ink! | 用 Rust 写智能合约(一)

Hello, Ink! | 用 Rust 写智能合约(一)

合约调用

点击Execute

Hello, Ink! | 用 Rust 写智能合约(一)

选择get():bool函数,点击「调用」:

Hello, Ink! | 用 Rust 写智能合约(一)

返回调用结果:

Hello, Ink! | 用 Rust 写智能合约(一)

Flipper 源码解读

// Copyright 2018-2020 Parity Technologies (UK) Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // //     http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License.  #![cfg_attr(not(feature = "std"), no_std)]  use ink_lang as ink;  #[ink::contract] pub mod flipper {     #[ink(storage)]     pub struct Flipper {         value: bool,     }      impl Flipper {         /// Creates a new flipper smart contract initialized with the given value.         #[ink(constructor)]         pub fn new(init_value: bool) -> Self {             Self { value: init_value }         }          /// Creates a new flipper smart contract initialized to `false`.         #[ink(constructor)]         pub fn default() -> Self {             Self::new(Default::default())         }          /// Flips the current value of the Flipper's bool.         #[ink(message)]         pub fn flip(&mut self) {             self.value = !self.value;         }          /// Returns the current value of the Flipper's bool.         #[ink(message)]         pub fn get(&self) -> bool {             self.value         }     }      #[cfg(test)]     mod tests {         use super::*;          #[test]         fn default_works() {             let flipper = Flipper::default();             assert_eq!(flipper.get(), false);         }          #[test]         fn it_works() {             let mut flipper = Flipper::new(false);             assert_eq!(flipper.get(), false);             flipper.flip();             assert_eq!(flipper.get(), true);         }     } }

1. cfgcfg_attr的使用

cfg是 Rust 中的特殊属性, 它允许我们编译基于标志的代码并传递给编译器。

在本合约中,我们可以看到:

#[cfg(test)]

这个标识意味着下面的代码是单元测试。

2. impl 关键字

Implement some functionality for a type.

为一种类型做函数实现。

标准的模板是:

struct Example {     number: i32,     # 许多变量…… }  impl Example {     fn boo() {         println!("boo! Example::boo() was called!");     }      fn answer(&mut self) {         self.number += 42;     }         # 许多函数…… }

套用到本合约中,首先我们定义本合约的struct

pub struct Flipper {     value: bool, # 其中包含一个变量 value }

然后对struct进行补充实现:

impl Flipper {     …… }

3. #[ink(constructor)]#[ink(message)]

#[ink(constructor)]表示这行语句函数是合约的构造函数,相当于solidity合约中的constructor

https://docs.soliditylang.org/en/v0.7.2/contracts.html#constructor

#[ink(message)]表示这行语句下面的函数是合约的普通函数,如例子中的get函数:

/// Returns the current value of the Flipper's bool. #[ink(message)] pub fn get(&self) -> bool {     self.value }

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注