Help us understand the problem. What is going on with this article?

Truffle で始める Ethereum 入門 - ERC20 トークンを作ってみよう

More than 1 year has passed since last update.

この記事は Ethereum Advent Calendar 2017 の2日目の記事です。

今日は、Ethereum 入門者の方向けに「ERC20トークン」の作成方法をご紹介しようと思います。意外と簡単で驚かれるかもしれません。

ERC20 トークンとは

ERC20 は、Ethereum ブロックチェーン上でトークンを発行する際の標準規格です。ERC20 に準拠したトークンであれば、無数に存在する種類のトークンを同じ枠組みで価値移転することができます。

ちなみに ERC とは「Ethereum RFC (Request for Comment)」の意味で、その20番目だったために「ERC20」と呼ばれます。仕様の詳細は以下にまとまっています。
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md

具体的には、以下の 6つの function と 2つの event を実装すれば、ERC20 トークンとなります。

contract ERC20 {
  function totalSupply() constant returns (uint totalSupply);
  function balanceOf(address _owner) constant returns (uint balance);
  function transfer(address _to, uint _value) returns (bool success);
  function transferFrom(address _from, address _to, uint _value) returns (bool success);
  function approve(address _spender, uint _value) returns (bool success);
  function allowance(address _owner, address _spender) constant returns (uint remaining);
  event Transfer(address indexed _from, address indexed _to, uint _value);
  event Approval(address indexed _owner, address indexed _spender, uint _value);
}

トークン作成の流れ

では実際に ERC20 トークンを作ってみましょう。今回は、ライブラリを活用してサクッと ERC20 トークンのコントラクトを作成し、それをローカルマシン上の仮想的なプライベートチェーンにデプロイするまでを行います。

全体の流れは以下のとおりです。

  1. Truffle フレームワークのインストール
  2. OpenZeppelin ライブラリの導入
  3. Solidity コードの作成
  4. Solidity コードのコンパイル
  5. マイグレーションファイルの作成
  6. コントラクトのデプロイ
  7. デプロイされたコントラクトの確認

Truffle フレームワークのインストール

Truffle は、Ethereum の開発フレームワークです。コントラクトコードのコンパイルやデプロイ、アドレス管理などの面倒を見てくれます。

以下のコマンドで、Truffle をインストールしてください1。本記事執筆時点での Truffle の最新バージョンは 4.0.1 でした。

$ npm install -g truffle

新しくプロジェクトフォルダを作成して、truffle init を実行します。

$ mkdir ~/my_erc20_token
$ cd ~/my_erc20_token
$ truffle init

以下のようなフォルダ構成でファイル一式がダウンロードされたかと思います。

OpenZeppelin ライブラリの導入

OpenZeppelin は、Ethereum のスマートコントラクト開発を補助するライブラリです。ERC20 トークンの実装も含まれているので、今回はそれを使用します。

Truffle のプロジェクトフォルダの中で、以下のコマンドを実行してください。

$ npm init -f
$ npm install zeppelin-solidity --save

これで、OpenZeppelin のコードを、自分のコントラクトコードの中から使えるようになりました。

Solidity コードの作成

Solidity は、Ethereum のスマートコントラクトを記述するためのプログラミング言語の1つです。他にも使用できる言語はありますが、現時点では Solidity がデファクトスタンダードになっています。

では、ERC20 トークンの Solidity コードを書きましょう。MyToken.sol というファイルを contracts フォルダの中に用意し、以下のコードを記述してください。

pragma solidity ^0.4.18;
import "zeppelin-solidity/contracts/token/ERC20/StandardToken.sol";

contract MyToken is StandardToken {
  string public name = "MyToken";
  string public symbol = "MTKN";
  uint public decimals = 18;

  function MyToken(uint initialSupply) public {
    totalSupply_ = initialSupply;
    balances[msg.sender] = initialSupply;
  }
}

短いコードなので、順番に解説していきます。

pragma solidity ^0.4.18;

↑ コンパイル時に使用する Solidity コンパイラのバージョンを指定しています。

import "zeppelin-solidity/contracts/token/ERC20/StandardToken.sol";

↑ OpenZeppelin ライブラリから、ERC20 の実装クラスである StandardToken.sol をインポートしています2

contract MyToken is StandardToken {
  ...
}

↑ コントラクトの宣言です。is StandardToken の部分で、MyTokenStandardToken を継承していることを表しています。

  string public name = "MyToken"; 
  string public symbol = "MTKN";
  uint public decimals = 18;

↑ コントラクトの状態変数 name, symbol, decimals に値を代入しています。ここでは、名前が "MyToken"、シンボルが "MTKN"、小数点の桁数が 18 のトークンとしています。

  function MyToken(uint initialSupply) public {
    ...
  }

↑ コントラクト作成時に呼ばれるコンストラクタです。contract 名と同じ名称の function がコンストラクタとなります。

    totalSupply_ = initialSupply;

↑ トークンの総発行量を表す totalSupply_ という変数に、コンストラクタで受け取った initialSupply を代入しています。totalSupply_ は、MyToken コントラクトが継承している OpenZeppelin の StandardToken が持つ状態変数です。

    balances[msg.sender] = initialSupply;

発行したトークンを、全て msg.sender のアドレス(口座)に入れています。msg.sender は、コントラクト実行者の Ethereum アドレスを表し、balances は、アドレスをキーとした key/value 型の変数です。

Solidity コードのコンパイル

では、記述した Solidity コードをコンパイルしましょう。

$ truffle compile

を実行すると、継承先のコントラクトも含めてコンパイルされます。ビルド結果は、build/contracts に、Truffle の Contract Artifact という形式の JSON ファイルで保存されます。

マイグレーションファイルの作成

次に、MyToken コントラクトをデプロイするためのマイグレーションファイルを作成します。migrations フォルダの中に、2_deploy_my_token.js というファイルを作成し、以下のコードを記述します。

const MyToken = artifacts.require('./MyToken.sol')

module.exports = (deployer) => {
  const initialSupply = 50000e18
  deployer.deploy(MyToken, initialSupply)
}

ここでは、トークン発行量が 50,000 MTKN になるように、MyToken のコンストラクタへ initialSupply の値を渡しています。

ちなみにマイグレーションの仕組みは、デプロイの順番や状態を管理するため、マイグレーションファイル名は [数字]_[名称].js という形式にする必要があります。

コントラクトのデプロイ

$ truffle develop

というコマンドを実行すると、ローカルマシンの 9545 ポート (localhost:9545) で Ethereum ブロックチェーンのエミュレータが起動し、利用可能な Ethereum アドレスのリストが表示されます。

Truffle Develop started at http://localhost:9545/

Accounts:
(0) 0x...
(1) 0x...
...

同時に、インタラクティブにやり取りできるコンソールも立ち上がります。そこで migrate というコマンドを打つと、作成したマイグレーションファイルに従って、コントラクトのデプロイが実行されます。

truffle(develop)> migrate
Using network 'develop'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... 0x54f6d0cef097d4fb43e0eae48f889a59af725f92a701f5f4ba7adac693118159
  Migrations: 0x8f0483125fcb9aaaefa9209d8e9d7b9c8b9fb90f
Saving successful migration to network...
  ... 0x2e369ab2d57c20d6f0be342da05a0e340a8e85de0aef12b3199e44de9005d26c
Saving artifacts...
Running migration: 2_deploy_my_token.js
  Replacing MyToken...
  ... 0x1228137c93414046875fa0ca1e85a6c65db529d13010579ecd1b4ec689688448
  MyToken: 0x2c2b9c9a4a25e24b174f26114e8926a9f2128fe4
Saving successful migration to network...
  ... 0xf222e7a6a6255bd91b1dd223d30f4d2c18056ceb7b496cc47db3a6da4bbb7417
Saving artifacts...

↑のように表示されれば成功です。上の例であれば、0x2c2b9c9a4a25e24b174f26114e8926a9f2128fe4 というアドレスに MyToken コントラクトがデプロイされました。

デプロイされたコントラクトの確認

続けて、Truffle のコンソール上で MyToken コントラクトとやり取りしてみましょう。

truffle(develop)> myToken = MyToken.at(MyToken.address)
...

とすると、myToken という変数に、デプロイされた MyToken コントラクトオブジェクトが代入されます。

例えば、

truffle(develop)> myToken.name()
'MyToken'

truffle(develop)> myToken.totalSupply()
BigNumber { s: 1, e: 22, c: [ 500000000 ] }

とすると、トークンの名称、総発行量が確認できます3

トークンの口座残高を見てみましょう。次のコマンドを打つと、Truffle が用意してくれたアドレスのリストが表示されます。

truffle(develop)> web3.eth.accounts
[ '0x0...', ... ]

先程のデプロイは、一番目のアドレス (web3.eth.accounts[0]) で行ったことになるので、このアドレスに発行した全てのトークンが入っており、他のアドレスの残高はゼロになっています。

truffle(develop)> myToken.balanceOf(web3.eth.accounts[0])
BigNumber { s: 1, e: 22, c: [ 500000000 ] }

truffle(develop)> myToken.balanceOf(web3.eth.accounts[1])
BigNumber { s: 1, e: 0, c: [ 0 ] }

最後に、accounts[0] から accounts[1] に、1,000 MTKN だけ移してみましょう。

truffle(develop)> myToken.transfer(web3.eth.accounts[1], 1000e18)
...

truffle(develop)> myToken.balanceOf(web3.eth.accounts[0])
BigNumber { s: 1, e: 22, c: [ 490000000 ] }

truffle(develop)> myToken.balanceOf(web3.eth.accounts[1])
BigNumber { s: 1, e: 21, c: [ 10000000 ] }

おわりに

今回は、Truffle フレームワークと OpenZepplein ライブラリを活用して ERC20 トークンを作成してみました。ご覧になった通り、ERC20 トークンを作成するだけであれば、10行程のコードを書くだけで実現できます。

独自トークンの発行はスタートに過ぎず、重要なのは、そのトークンを使って何を実現するかです。ぜひ皆さんも、Ethereum ブロックチェーンを活用して素晴らしいアイデアを実現してみてください。

See Also


  1. Node.js 環境がない方はインストールしておいてください  

  2. 使用する OpenZeppelin のバージョンによって、パスや変数名が異なることがあります 

  3. 数値は BigNumber オブジェクトをで返されます 

amachino
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした