開発環境の構築とかはこちら参照:
https://qiita.com/YukiSekiguchi/items/623359857269aff74586
https://qiita.com/YukiSekiguchi/items/f84afbf35f4fa039859c
今回やること
https://developers.eos.io/eosio-home/docs/token-contract に沿ってEOSIOのプライベートネットワーク上で仮想通貨トークンを発行、送金してみる
準備
nodeosのコンテナが動いてないようなら動かす
$docker start 1574a37de3c6
まずはウォレットをopenする+unlockする。
$cleos wallet open -n default
$cleos wallet unlock -n default
トークン発行するスマートコントラクト用にアカウントを作成。開発用の鍵を使う。
$cleos create account eosio eosio.token EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
トークン発行用のスマートコントラクトの実装は公式が提供してくれているので、これを持ってくる
$git clone https://github.com/EOSIO/eosio.contracts
そのままコンパイルするだけ。簡単。
$cd eosio.contracts
$eosio-cpp -o eosio.token.wasm src/eosio.token.cpp -I include/
トークンの作成
コンテナの中にeosio.token.wasmとabiを持っていったら
$ cleos set contract eosio.token <eosio.token.wasmがおいてあるコンテナ内のパス> --abi <eosio.token.abiのおいてあるコンテナ内のパス> -p eosio.token@active
とすると
Reading WASM from /home/eosio.contracts/eosio.token/eosio.token.wasm...
Publishing contract...
executed transaction: c12511f41efb3ec72e64a9ab8ce040f2c65c54a7d7d21ef847bb758b0b49e79c 9320 bytes 1490 us
# eosio <= eosio::setcode {"account":"eosio.token","vmtype":0,"vmversion":0,"code":"0061736d0100000001b0011d60037f7e7f0060047f...
# eosio <= eosio::setabi {"account":"eosio.token","abi":"0e656f73696f3a3a6162692f312e30010c6163636f756e745f6e616d65046e616d65...
2018-10-08T12:07:31.800 thread-0 main.cpp:481 print_result warning: transaction executed locally, but may not be confirmed by the network yet
と出てスマートコントラクトがネットワーク上にデプロイされる。
この状態で次のコマンドを打つとトークンが作成できる。
cleos push action eosio.token create '[ "eosio", "1000000000.0000 HOGE"]' -p eosio.token@active
1000000000.0000
は発行上限が1000000000
で、最小単位が0.0001
になること表す。
またHOGE
の部分は任意の大文字アルファベットを入れる。これがトークンの単位になる。普通は3文字にする(と思う)。
今回はこのままHOGE
コインということで進める。
トークンの発行
発行(issue)と作成(create)は違う概念で、createはトークンの上限と最小単位と単位を規定し、実際のトークンはeosio.token自身が持つ。
トークンを通常のアカウント向けに渡すのが発行である(この辺の理解は怪しい)。
前回作ったalice
とbob
にトークンを発行し、やりとりさせてみる。
まずalice
に100.0000 HOGE
発行する。
$ cleos push action eosio.token issue '[ "alice", "100.0000 HOGE", "memo" ]' -p eosio@active
executed transaction: deafe9a28bbd20697c28f1e2a2b7c2997d589115c661d5010cbe25a909074460 128 bytes 6136 us
# eosio.token <= eosio.token::issue {"to":"alice","quantity":"100.0000 HOGE","memo":"memo"}
# eosio.token <= eosio.token::transfer {"from":"eosio","to":"alice","quantity":"100.0000 HOGE","memo":"memo"}
# eosio <= eosio.token::transfer {"from":"eosio","to":"alice","quantity":"100.0000 HOGE","memo":"memo"}
# alice <= eosio.token::transfer {"from":"eosio","to":"alice","quantity":"100.0000 HOGE","memo":"memo"}
memo
の部分は文字通りメモで、取引について好きなメモを残せる。
なおHOGE
コインの最小単位は0.0001にしたので、きっちり.0000まで書かないと以下のようにエラーになる。
$ cleos push action eosio.token issue '[ "alice", "100.0 HOGE", "memo" ]' -p eosio@active
Error 3050003: eosio_assert_message assertion failure
また、-d
をつけるとdry runができる(見てもよくわからない)。
$ cleos_d push action eosio.token issue '[ "alice", "100.0000 HOGE", "memo" ]' -p eosio@active -d
{
"expiration": "2018-10-08T12:41:28",
"ref_block_num": 52702,
"ref_block_prefix": 2512073667,
"max_net_usage_words": 0,
"max_cpu_usage_ms": 0,
"delay_sec": 0,
"context_free_actions": [],
"actions": [{
"account": "eosio.token",
"name": "issue",
"authorization": [{
"actor": "eosio",
"permission": "active"
}
],
"data": "0000000000855c3440420f000000000004484f4745000000046d656d6f"
}
],
"transaction_extensions": [],
"signatures": [
"SIG_K1_KexcdCmckuWp9bVBKeiLNDuLQA1L4Jenicy44TBTFxajF9dFrpAutrjRd4gvZdWrA8VA8ftrZ5qvEAF9FtDAYPHLpJPv2U"
],
"context_free_data": []
}
アカウントが持つトークンは次のように確認できる
$ cleos get currency balance eosio.token alice HOGE
100.0000 HOGE
トークンの送金
これでalice
は100.0000HOGE
持っているので、bob
に送金してみる。
試しにmemoに日本語を入れたけど大丈夫だった(途中で切れてしまったが)。
$ cleos push action eosio.token transfer '[ "alice", "bob", "25.0000 HOGE", "アリスからボブに25.0000HOGE送金する" ]' -p alice@active
executed transaction: 8378a1d8577444796660e9ae5f417f71ad05bcfb54fa4f1e82ed4f65dacd1d5e 176 bytes 2931 us
# eosio.token <= eosio.token::transfer {"from":"alice","to":"bob","quantity":"25.0000 HOGE","memo":"アリスからボブに25.0000HOGE送�...
# alice <= eosio.token::transfer {"from":"alice","to":"bob","quantity":"25.0000 HOGE","memo":"アリスからボブに25.0000HOGE送�...
# bob <= eosio.token::transfer {"from":"alice","to":"bob","quantity":"25.0000 HOGE","memo":"アリスからボブに25.0000HOGE送�...
2018-10-08T12:45:34.574 thread-0 main.cpp:481 print_result warning: transaction executed locally, but may not be confirmed by the network yet
bob
のトークン所有量を見てみると、
$cleos get currency balance eosio.token bob HOGE
25.0000 HOGE
となり、alice
のトークン所有量を見てみると、
$cleos get currency balance eosio.token alice HOGE
75.0000 HOGE
となっていて、alice
からbob
に25.0000 HOGE
送金できたことがわかる。
ちなみに試しにbob
が勝手にalice
からbob
に送金しようとする(最後をbob@active
に変える)と何が起きるかというと
$ cleos push action eosio.token transfer '[ "alice", "bob", "25.0000 HOGE", "アリスからボブに勝手に25.0000HOGE送金する" ]' -p bob@active
Error 3090004: Missing required authority
となり、勝手なことはできないようになっている。
これはsrc/eosio.token.cpp
の中身を見てみると
void token::transfer( account_name from,
account_name to,
asset quantity,
string memo )
{
eosio_assert( from != to, "cannot transfer to self" );
require_auth( from );
eosio_assert( is_account( to ), "to account does not exist");
auto sym = quantity.symbol.name();
stats statstable( _self, sym );
const auto& st = statstable.get( sym );
︙
︙
となっており、前回もやったrequire_auth( from )
が効いているからであることがわかる。