EOSIO Developer Portal 解説 独自トークンの発行 第1回

  • 2020.02.04
  • 2020.02.26
  • EOS
EOSIO Developer Portal 解説 独自トークンの発行 第1回

はじめに


本記事ではEOS Developer Portalで紹介されているeosio.tokenコントラクトを用いて、コントラクトのデプロイや実行をおこない、より実用的なコントラクトの構造や実行方法を学びます。

本記事は、前回の最短でHello World!で開発環境を構築済みであることを前提としています。

本記事は、過去にコンセンサス・ベイスが主宰していたオンラインサロンの記事です。記事は2017年~2018年にかけて執筆されたため、一部は、既に古くなっている可能性があります。あらかじめご了承ください。


関連する記事

EOSIO Developer Portal 解説 最短でHello World!
EOSIO Developer Portal 解説 独自トークンの発行 第1回
EOSIO Developer Portal 解説 独自トークンの発行 第2回
EOSIO Developer Portal 解説 独自トークンの発行 第3回
EOSIO Developer Portal 解説 データの永続化とインラインアクション 第1回
EOSIO Developer Portal 解説 データの永続化とインラインアクション 第2回
EOSIO Developer Portal 解説 データの永続化とインラインアクション 第3回

eosio.tokenコントラクト


eosio.tokenコントラクトは、EOSIO公式のサンプルコードとして提供されている、EOS上でさまざまな種類のトークンの作成や管理をおこなうためのコントラクトです。

さっそく、EOSIO公式サンプルコードをダウンロードし、eosio.tokenの中身を確認してみましょう。

コードのダウンロード


下記コマンドを実行して、EOSIOのサンプルコードをダウンロードし、eosio.tokenのファイル構成を確認します。

CONTRACTS_DIRは、環境構築の際にDockerのボリュームに指定したcontractsフォルダのフルパスを指定します。

コマンド1. eosio.tokenコントラクトのダウンロード

$ cd CONTRACTS_DIR
 
$ git clone https://github.com/EOSIO/eosio.contracts --branch v1.4.0 --single-branch
 
$ cd eosio.contracts/eosio.token
 
# treeコマンドがない場合は sudo apt install tree でインストール
# macOSなら brew install tree でもインストール可
$ tree
.
├── CMakeLists.txt
├── README.md
├── include
│   └── eosio.token
│       └── eosio.token.hpp
└── src
    └── eosio.token.cpp


※EOSのリポジトリをcloneする際、”You are in ‘detached HEAD’ state~”というメッセージが出ることがありますが、本記事ではソースの確認と実行だけなのでそのまま続行して大丈夫です。
eosio.tokenコントラクトは、主にeosio.token.hppとeosio.token.cppで構成されています。eosio.token.hppには、クラスやアクション、テーブルの定義などが記載されており、eosio.token.cppには、具体的なロジックの実装が記載されています。

コントラクトの構造


eosio.tokenコントラクトの構造を理解するために、まずはeosio.token.hppの中身を確認してみましょう。コード1に、eosio.token.hppのアクション定義を抜粋したコードを示します。

なお、アクションとは、EOSブロックチェーンの状態を変更するための機能であり、Ethereumコントラクトにおけるファンクションに相当します。

コード1. eosio.token.hppのアクション定義抜粋

class [[eosio::contract("eosio.token")]] token : public contract {
   public:
      using contract::contract;
 
      [[eosio::action]]
      void create( name   issuer,
                   asset  maximum_supply);
 
      [[eosio::action]]
      void issue( name to, asset quantity, string memo );
 
      [[eosio::action]]
      void retire( asset quantity, string memo );
 
      [[eosio::action]]
      void transfer( name    from,
                     name    to,
                     asset   quantity,
                     string  memo );
 
      [[eosio::action]]
      void open( name owner, const symbol& symbol, name ram_payer );
 
      [[eosio::action]]
      void close( name owner, const symbol& symbol );
};


eosio.token.hppの記述をみると、コントラクトには、create, issue, retire, transfer, open, closeという6つのアクションが定義されていることが分かります。
これらのアクションの概要をテーブル1にまとめます。

テーブル1. eosio.tokenコントラクトのアクション一覧

アクション概要
createissuer(発行者)と最大供給量を指定して、新しいトークンの種類を作成します。
issue新しいトークンを発行し、トークンの供給量を増加させます。
retire流通しているトークンの一部を回収(還収)し、トークンの供給量を減少させます。
transfer指定した量のトークンの所有者を変更します。
open指定したトークンの種類に対応する残高口座を開設します。
close指定したトークンの種類に対応する残高口座を閉鎖します。


第1回の記事では、createアクションを用いて新しいトークンの種類を作成し、第2回で他のアクションを試します。

eosio.tokenコントラクトは、ひとつのコントラクトで複数の種類のトークンを作成、管理します。そのためのデータ構造として、トークンごとの定義や供給量を管理するstatテーブルと、アカウントごとのトークン残高を管理するaccountsテーブルをもちます。

eosio.token.hppファイルにおけるstatテーブルとaccountsテーブルの定義の抜粋をコード2に示します。

コード2. eosio.token.hppのテーブル定義抜粋

private:
   struct [[eosio::table]] account {
      asset    balance;
 
      uint64_t primary_key()const { return balance.symbol.code().raw(); }
   };
 
   struct [[eosio::table]] currency_stats {
      asset    supply;
      asset    max_supply;
      name     issuer;
 
      uint64_t primary_key()const { return supply.symbol.code().raw(); }
   };
 
   typedef eosio::multi_index< "accounts"_n, account > accounts;
   typedef eosio::multi_index< "stat"_n, currency_stats > stats;


それでは、実際にコントラクトを実行して、動作を確認していきましょう。

コントラクトのデプロイ


コントラクトをデプロイする前に、開発環境が正しく構築されているかを確認します。

まず、コントラクトのコンパイルをおこなうために、eosio.cdt (EOSIO Contract Development Toolkit) が必要です。下記コマンドを実行し、CDTのバージョン1.3.2がインストールされていることを確認します。

コマンド2. CDTのバージョン確認

$ eosio-cpp --version
eosio-cpp version 1.3.2

また、eosioのDockerコンテナが正しく起動しているかを確認します。

コマンド3. eosioコンテナの起動と確認例

$ docker start eosio
eosio
 
$ docker ps
CONTAINER ID        IMAGE               COMMAND                ...
50f1aabd7a1c        eosio/eos:v1.4.2    "/bin/bash -c 'keosd…" ...


最後に、必要なウォレットとアカウントが作成されているかを確認します。ウォレットを作成した際に控えたパスワードを用いて、ウォレットをアンロックし、ウォレットに登録されている公開鍵と秘密鍵のペアを確認してみましょう。

なお、前回の記事で起動したコンテナをすでに停止・削除している場合、dockerコンテナを起動した後、改めてwalletのオープンからアンロック、鍵の設定、テストアカウントの作成までの手順を行ってください。

コマンド4. ウォレットのアンロック

# defaultウォレットを開く
$ cleos wallet open
Opened: default
 
# ウォレットの一覧を確認
$ cleos wallet list
Wallets:
[
  "default"
]
 
# パスワードを用いてウォレットをアンロック
$ cleos wallet unlock
password:
 
# もう一度ウォレットの一覧を確認
$ cleos wallet list
Wallets:
[
  "default *"  # * がついていることで、ウォレットがアンロックされている
]
 
# ウォレットの公開鍵と秘密鍵を確認
$ cleos wallet private_keys
password:
[[
    "YOUR_PUBLIC_KEY",
    "YOUR_PRIVATE_KEY"
  ],[
    "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
    "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"
  ]
]


YOUR_PUBLIC/PRIVATE_KEYの部分は、環境構築の手順で各々が作成した公開鍵・秘密鍵が表示されているはずですので、各々異なった結果となります。EOS6MRyA…から始まる公開鍵は、eosioのDockerにあらかじめセットされた鍵をインポートしましたので、同じ鍵が表示されるはずです。

YOUR_PUBLIC_KEYに対応するアカウントも確認しておきましょう。eosio.tokenコントラクトの実行でも、aliceとbobのアカウントを用いるため、両者のアカウントが作成されていることを確認してください。

コマンド5. 公開鍵に対応するアカウントの確認

$ cleos get accounts YOUR_PUBLIC_KEY
{
  "account_names": [
    "alice",
    "bob",
    "hello"
  ]
}


上記の結果をみて分かるとおり、EOSではアカウントと公開鍵/秘密鍵が1:1には紐付かず、一つの鍵ペアに複数のアカウントが対応することが多くあります。また、今回はまだ意識していませんが、基本的に一つのアカウントに複数の鍵ペアが紐付き、鍵ペアごとに異なる権限を付与することができます。

また、EOSでは一つのコントラクトに対して一つのアカウントが紐付きます。通常は、コントラクトと同じ名前のアカウントを作成します。
今回も、eosio.tokenコントラクトに紐付く、eosio.tokenアカウントを作成しておきましょう。公開鍵は、Dockerであらかじめ用意されている開発用の鍵を用います。

公開鍵は$ docker exec -it eosio bashでコンテナに入って、直下のconfig.iniをcatコマンドなどで表示すれば見つけることができます。

また、EOS Developer Portalにも掲載されているので、こちらからも確認できます。(下記のstep2)

https://developers.eos.io/eosio-home/docs/token-contract

コマンド6. eosio.tokenアカウントの作成

$ cleos create account eosio eosio.token \
EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV


下記のコマンドで、eosio.tokenアカウントが作成されているのが確認できます。

$ cleos get accounts EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
{
  "account_names": [
    "eosio.token"
  ]
}


アカウントの作成や次のコントラクトのデプロイには、ウォレットがアンロックされている必要があります。ウォレットは一定時間でロックされますので、ロックがかかってしまった場合は適宜アンロックをしてください。

コントラクトのデプロイ


環境構築の確認が終わったところで、コントラクトのデプロイを始めます。まず、CDTのeosio-cppを用いてコードをコンパイルします。

成功すると、eosio.token.abiと、eosio.token.wasmファイルが作成されます。

コマンド7. eosio.tokenコントラクトのコンパイル

$ eosio-cpp -I include -o eosio.token.wasm src/eosio.token.cpp --abigen
$ ls -l
CMakeLists.txt
README.md
eosio.token.abi
eosio.token.wasm
include
src


コンパイルが完了したら、コントラクトをブロックチェーンにデプロイします。

下記コマンド8におけるCONTRACTS_DIRは、コントラクトフォルダのフルパスを指定します。

eosio.tokenコントラクトのデプロイは、さきほど作成したeosio.tokenアカウントを用いて実行していることに注意してください(-p eosio.token@activeの部分)。

コマンド8. eosio.tokenコントラクトのデプロイ

$ cleos set contract eosio.token CONTRACTS_DIR/eosio.contracts/eosio.token --abi eosio.token.abi -p eosio.token@active
 
Reading WASM from ...
Publishing contract...
executed transaction: 69c68b1bd5d61a0cc146b11e89e11f02527f24e4b240731c4003ad1dc0c87c2c  9696 bytes  6290 us
#         eosio <= eosio::setcode               {"account":"eosio.token","vmtype":0,"vmversion":0,"code":"0061736d0100000001aa011c60037f7e7f0060047f...
#         eosio <= eosio::setabi                {"account":"eosio.token","abi":"0e656f73696f3a3a6162692f312e30000605636c6f73650002056f776e6572046e61...
warning: transaction executed locally, but may not be confirmed by the network yet         ]

新規トークンの作成


それでは、デプロイしたeosio.tokenコントラクトを用いて、新規トークンを作成してみましょう。

新規トークンの作成には、createアクションを用います。

コード3に、eosio.token.cppから、createアクションの実装を抜粋します。

コード3.  eosio.token.cppのcreateアクションの抜粋

void token::create( name   issuer,
                    asset  maximum_supply )
{
    require_auth( _self );
 
    auto sym = maximum_supply.symbol;
    eosio_assert( sym.is_valid(), "invalid symbol name" );
    eosio_assert( maximum_supply.is_valid(), "invalid supply");
    eosio_assert( maximum_supply.amount > 0, "max-supply must be positive");
 
    stats statstable( _self, sym.code().raw() );
    auto existing = statstable.find( sym.code().raw() );
    eosio_assert( existing == statstable.end(), "token with symbol already exists" );
 
    statstable.emplace( _self, [&]( auto& s ) {
       s.supply.symbol = maximum_supply.symbol;
       s.max_supply    = maximum_supply;
       s.issuer        = issuer;
    });
}


createアクションは、引数にissuerとmaximum_supplyを取ります。issuerには、新規トークンの発行権限を持つアカウントを指定し、maximum_supplyには、トークンの最大供給量をトークンのシンボルとともに指定します。

シンボルは、1~7文字の大文字で表現された文字列です。

例えば、eosioユーザーをissuerにして、最大供給量1000000000.0000の「SYS」トークンを作成するコマンドは、コマンド9のとおりです。

コマンド9. 新規SYSトークンの作成例

$ cleos push action eosio.token create '[ "eosio", "1000000000.0000 SYS"]' -p eosio.token@active
 
executed transaction: 0e49a421f6e75f4c5e09dd738a02d3f51bd18a0cf31894f68d335cd70d9c0e12  120 bytes  1000 cycles
#   eosio.token <= eosio.token::create          {"issuer":"eosio","maximum_supply":"1000000000.0000 SYS"}


トークンの最大供給量には、小数点以下いくつまでを許容するかも定義可能です。小数点による分割を許容しない YEN トークンを作成するには、下記コマンド10のようにします。

コマンド10. 新規YENトークンの作成例

$ cleos push action eosio.token create '[ "eosio", "1000000000 YEN"]' -p eosio.token@active
 
executed transaction: 487d3838a96f7389029929fa41a8249c37f35216de0110a07a4c6cb129fc31d4  120 bytes  1407 us
#   eosio.token <= eosio.token::create          {"issuer":"eosio","maximum_supply":"1000000000 YEN"}

作成されたトークンの定義は、eosio.tokenコントラクトのstatテーブルに格納されています。下記のコマンド11に示した手順で、作成したトークンの定義を確認してみましょう。

コマンド11. 作成したトークンの確認

$ cleos get table eosio.token SYS stat
{
  "rows": [{
      "supply": "0 SYS",
      "max_supply": "1000000000.0000 SYS",
      "issuer": "eosio"
    }
  ],
  "more": false
}
 
$ cleos get table eosio.token YEN stat
{
  "rows": [{
      "supply": "0 YEN",
      "max_supply": "1000000000 YEN",
      "issuer": "eosio"
    }
  ],
  "more": false
}


指定したmax_supplyとissuerにより、正しくSYS、YENトークンが作成されていることがわかります。

ただし、両者ともsupplyは0のままです。これは、新規トークンの定義は作成されたものの、実体としてのトークンはまだ発行されていない状態だからです。第2回の記事にて、トークンの新規発行や送金、回収などのアクションを実行してみましょう。

参考文献:


     

免責事項

本記事に掲載されている記事の内容につきましては、正しい情報を提供することに務めてはおりますが、提供している記事の内容及び参考資料からいかなる損失や損害などの被害が発生したとしても、弊社では責任を負いかねます。実施される際には、法律事務所にご相談ください。

技術・サービス・実装方法等のレビュー、その他解説・分析・意見につきましてはblock-chani.jp運営者の個人的見解です。正確性・正当性を保証するものではありません。本記事掲載の記事内容のご利用は読者様個人の判断により自己責任でお願いいたします。

     

コンセンサス・ベイス(株)とブロックチェーン事業を行なってみませんか?

当サイトを運営するコンセンサス・ベイス株式会社は、2015年設立の国内で最も古いブロックチェーン専門企業です。これまでに、大手企業の顧客を中心に、日本トップクラスのブロックチェーンの開発・コンサルティング実績があります。

ブロックチェーンに関わるビジネスコンサル・システム開発・教育・講演などご希望でしたら、お気軽にお問い合わせください。

     
     

ブロックチェーン学習に最適の書籍の紹介

図解即戦力 ブロックチェーンのしくみと開発がこれ1冊でしっかりわかる教科書

ブロックチェーン イーサリアムへの入り口 第二版 (ブロックチェーン技術書籍)

本書は、ブロックチェーン技術に興味を持ったエンジニアや、その仕組みを学び、自分の仕事に活かしたいビジネスパーソンを対象にして、ブロックチェーンのコア技術とネットワーク維持の仕組みを平易な言葉で解説しています。この本を読んだうえで、実際にコードを書くような専門書、ブロックチェーンビジネスの解説書を読むことで、理解度が飛躍的に高まるでしょう。(はじめにより)

EOSカテゴリの最新記事