(## 什么是 WASM
在配置了基本的 Rust 环境后,我们可以配置 Ink! 所需的开发环境了。 我们还要安装/升级 Mac 上安装: Linux 上安装: 执行如下命令: 创建完成后进入文件夹: 合约项目目录结构: 一切顺利的话会输出如下结果: 如果顺利的话,目录下会生成 其中, 通过 打开如下网址,这个页面会自动连接本地启动的开发节点: https://paritytech.github.io/canvas-ui 上传 一路点击进行部署: 点击 选择 返回调用结果: 在本合约中,我们可以看到: 这个标识意味着下面的代码是单元测试。 Implement some functionality for a type. 为一种类型做函数实现。 标准的模板是: 套用到本合约中,首先我们定义本合约的 然后对 https://docs.soliditylang.org/en/v0.7.2/contracts.html#constructorInk! 环境配置
# 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 的编译器。# for mac brew upgrade binaryen # 如果没安装用 brew install
创建一个 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
target/ink
文件夹,里面包含如下文件:flipper.contract
是部署时要用的合约文件,可以视为solidity
合约中的bin
文件。metadata.json
是元数据,可以视为solidity
合约中的abi
文件。合约部署
canvas
启动一个本地运行的开发节点!canvas --dev --tmp
flipper.contract
这个文件:合约调用
Execute
:get():bool
函数,点击「调用」: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.
cfg
和cfg_attr
的使用cfg
是 Rust 中的特殊属性, 它允许我们编译基于标志的代码并传递给编译器。#[cfg(test)]
2. impl 关键字
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
。
#[ink(message)]
表示这行语句下面的函数是合约的普通函数,如例子中的get
函数:/// Returns the current value of the Flipper's bool. #[ink(message)] pub fn get(&self) -> bool { self.value }