Open7
ink!に入門する
事前準備
$ brew install binaryen
$ cargo install cargo-contract --vers ^0.16 --force --locked
コントラクト用のプロジェクトを新規作成する
$ cargo contract new flipper
$ cd flipper
で、ビルド
$ cargo +nightly test
$ cargo +nightly contract build
:
Original wasm size: 43.0K, Optimized: 19.2K
The contract was built in DEBUG mode.
Your contract artifacts are ready. You can find them in:
/path/to/flipper/target/ink
- flipper.contract (code + metadata)
- flipper.wasm (the contract's code)
- metadata.json (the contract's metadata)
target/ink
の下に関連ファイルが生成される、と。
$ tree -L 2 target
target
├── CACHEDIR.TAG
├── debug
│ ├── build
│ ├── deps
│ ├── examples
│ └── incremental
├── ink
│ ├── CACHEDIR.TAG
│ ├── flipper.contract
│ ├── flipper.wasm
│ ├── metadata.json
│ ├── release
│ └── wasm32-unknown-unknown
└── release
├── build
├── deps
├── examples
├── incremental
├── libflipper.d
└── libflipper.dylib
13 directories, 7 files
Substrateノード起動
$ substrate-contracts-node --dev --tmp
2021-12-25 17:13:21 Running in --dev mode, RPC CORS has been disabled.
2021-12-25 17:13:21 Substrate Contracts Node
2021-12-25 17:13:21 ✌️ version 0.1.0-7d81166-aarch64-macos
2021-12-25 17:13:21 ❤️ by Parity Technologies <admin@parity.io>, 2021-2021
2021-12-25 17:13:21 📋 Chain specification: Development
2021-12-25 17:13:21 🏷 Node name: freezing-pot-1451
2021-12-25 17:13:21 👤 Role: AUTHORITY
2021-12-25 17:13:21 💾 Database: RocksDb at /var/folders/b_/lxz21x891450bdx5s921z9_40000gn/T/substrateRcFhg8/chains/dev/db/full
2021-12-25 17:13:21 ⛓ Native runtime: substrate-contracts-node-100 (substrate-contracts-node-1.tx1.au1)
2021-12-25 17:13:21 🔨 Initializing Genesis block/state (state: 0x0f3a…bf76, header-hash: 0xcdbe…ebc3)
2021-12-25 17:13:21 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.
2021-12-25 17:13:22 ⏱ Loaded block-time = 6s from block 0xcdbe4e854bd2a3f2b41c7d23ae5024f9e1bf0f1223a99a710c8aebb41cb1ebc3
2021-12-25 17:13:22 🏷 Local node identity is: 12D3KooWJrTxtnkMwuj9spd4daF916eAvPd1FdVduUgqtBusFZFd
2021-12-25 17:13:22 📦 Highest known block at #0
2021-12-25 17:13:22 〽️ Prometheus exporter started at 127.0.0.1:9615
2021-12-25 17:13:22 Listening for new connections on 127.0.0.1:9944.
2021-12-25 17:13:23 Accepted a new tcp connection from 127.0.0.1:61035.
:
コントラクトをデプロイするためにWeb UIにアクセスする
選択ノードをLocal Node
にする。
そしてビルドしたコントラクト target/ink/flipper.contract
をアップロードして登録する。
このコントラクトは値をfalse/trueどちらかをストアするだけみたい。
コントラクト実行して、false/trueを切り替える。
実行した時はこんな感じになる。
storageの値をインクリメントするコントラクト作ってみる
$ cargo contract new incrementer
$ cd incrementer
$ cargo +nightly test
$ cargo +nightly contract build
コントラクトはテンプレートでflipperが実装されてるので、以下のような変更を入れる。
--- ../flipper/lib.rs 2021-12-25 16:46:36.000000000 +0900
+++ lib.rs 2021-12-25 17:34:17.000000000 +0900
@@ -3,25 +3,24 @@
use ink_lang as ink;
#[ink::contract]
-mod flipper {
+mod incrementer {
/// 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,
+ pub struct Incrementer {
+ my_number: u32,
}
- impl Flipper {
+ impl Incrementer {
/// Constructor that initializes the `bool` value to the given `init_value`.
#[ink(constructor)]
- pub fn new(init_value: bool) -> Self {
- Self { value: init_value }
+ pub fn new(init_value: u32) -> Self {
+ Self { my_number: init_value }
}
- /// Constructor that initializes the `bool` value to `false`.
+ /// Constructor that initializes the `u32` value to `0`.
///
/// Constructors can delegate to other constructors.
#[ink(constructor)]
@@ -33,14 +32,14 @@
/// 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;
+ pub fn increment(&mut self) {
+ self.my_number += 1;
}
/// Simply returns the current value of our `bool`.
#[ink(message)]
- pub fn get(&self) -> bool {
- self.value
+ pub fn get(&self) -> u32 {
+ self.my_number
}
}
@@ -58,17 +57,19 @@
/// We test if the default constructor does its job.
#[ink::test]
fn default_works() {
- let flipper = Flipper::default();
- assert_eq!(flipper.get(), false);
+ let incrementer = Incrementer::default();
+ assert_eq!(incrementer.get(), 0);
}
/// 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);
+ let mut incrementer = Incrementer::new(0);
+ assert_eq!(incrementer.get(), 0);
+ incrementer.increment();
+ assert_eq!(incrementer.get(), 1);
+ incrementer.increment();
+ assert_eq!(incrementer.get(), 2);
}
}
}
テストで確認
$ cargo +nightly test
Finished test [unoptimized + debuginfo] target(s) in 0.06s
Running unittests (target/debug/deps/incrementer-d60c12a0e8f0b2ec)
running 2 tests
test incrementer::tests::default_works ... ok
test incrementer::tests::it_works ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
コントラクをビルドし直して、コントラクト(target/ink/incrementer.contract
)登録して動き見てみる。
$ cargo +nightly contract build
うまく動いてそう。
Rustでコントラクト実装できるのいいですね。