【Truffle5.0対応】シンプルなERC20トークンを作成しよう!

【Truffle5.0対応】シンプルなERC20トークンを作成しよう!

どうもこじりょー(@kojiryoinvestor)です。

この記事はEthereum開発入門として、初心者の方に向けたシンプルなERC20トークンの作成を行うチュートリアルです。

シンプルなERC20トークンの作成を通じて、以下のこと学んでいきます。

・Ethereumの開発環境の構築(Truffle, Ganache)

OpenZepplinを利用したERC20トークンの作成

それでは始めていきましょう!

ERC20トークンとは?

EIP20

トークンの送受信はすべてスマートコントラクト上で行われています。

スマートコントラクトは誰でも自由に作ることができるため、好きなようにトークンの仕組みを作ることができます。

しかし誰もが好きなように作ると、異なるトークン同士のやりとりが難しくなります。

そこで異なるトークン同士が簡単に相互運用できるようトークンを標準化する仕様の1つが「EIP20」です。

Ethereumベースのトークンのインターフェースの標準「ERC20」を提案したEIP20はFabian Vogelsteller氏とVitalik Buterin氏によって2015年11月に提出され、2017年9月に採用が決定しました。

Ethereumベースのトークンの標準ERC20 | Blockchain Biz

「EIP20」はイーサリアムコミュニティで公式に確立された仕様です。

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md

その「EIP20」の仕様に沿って作成されたトークンを「ERC(Ethereum Request for Comments)20」と言います。

Ethereum開発環境の構築

node.jsとnpmのインストール

Ethereum開発で利用するツール等はJavaScript用のパッケージマネージャ「npm」を使って各プロジェクトにインストールしていきます。

まずは、公式サイトからnodejsとnpmをインストールしましょう。

Truffleのインストール

「Truffle」はEthereum上でスマートコントラクトの開発に必要なツールがまとまったフレームワークです。

TRUFFLE SUITE

npmのインストールが終わったらtruffleをインストールします。

$ npm install -g truffle

truffleのインストールが正常にできていれば、以下のコマンドを入力してバージョンを表示させることができます。

$ truffle version
Truffle v5.0.0 (core: 5.0.0)
Solidity v0.5.0 (solc-js)
Node v10.14.1

Ganacheのインストール

「Ganache」「自分のPC内だけで動くイーサリアムネットワーク」またの名を「プライベート・ネットワーク」を簡単に構築してくれるツールです。

もちろん「Geth」などの「イーサリアムクライアント」でもプライベートネットを構築することはできます。

ただGanacheの方が、Gethで手間がかかる点(アカウントロックの解除、アカウントの作成..etc)を省力してくれるので開発に集中できます。

Ganacheは公式サイトからインストールすることができます。

VScodeのインストール

スマートコントラクトの開発はテキストエディタとターミナルの両方を利用する機会が多いです。

画面を切り替えて両者を交互に利用するのは地味に面倒です。

そこでテキストエディタ内でターミナルも表示することができる「VSCode」がおすすめです。

VSCode

Visual Studio Code | Microsoft

ERC20トークンの作成

プロジェクトディレクトリ

まずはじめにトークンを作成するためのプロジェクトを作成しましょう。

お好きな名前でディレクトリを作成してください。

ここでは「simple」という名前でディレクトリを作成しました。

$ mkdir simple

ディレクトリを作成したらターミナルからディレクトリに移動して、Truffleで初期化を行います。

$ cd simple
$ truffle init

「truffle init」を実行すると開発に必要なディレクトリとファイルが自動で作成されます。

「truffle init」の実行結果
「truffle init」で自動作成されたディレクトリやプログラム

コントラクト

ERC20トークンの仕様

EIP20の仕様に沿ったトークンの作成が「ERC20トークン」と言いました。

つまりERC20トークンの作成とは、EIP20の仕様に沿ったコントラクトを作成するということです。

ERC20トークンの作成には以下のメソッドを実装します。

//供給されたトークンの合計を返す
function totalSupply() public view returns (uint256)

//トークンの残高を返す
function balanceOf(address _owner) public view returns (uint256 balance)

//指定したアドレスにトークンを送信する
function transfer(address _to, uint256 _value) public returns (bool success)

//イーサリアムアカウント同士でトークンを送受信する
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)

//_spenderの残高から_valueの量までトークンを引き落とすことを許可する
//簡単に言うとERC20トークンで小切手を実現する関数
function approve(address _spender, uint256 _value) public returns (bool success)

//_spenderから引き出せるトークンの量を返す
function allowance(address _owner, address _spender) public view returns (uint256 remaining)

//トークンが送信された情報をログに表示する
event Transfer(address indexed _from, address indexed _to, uint256 _value)

//approve()が実行された内容をログに表示する
event Approval(address indexed _owner, address indexed _spender, uint256 _value)

ERC20トークンの作成は以上のメソッドと、それらを利用したロジックを実装する必要があります。

これらを全て一から実装することもできますが、ここでは「OpenZeppelin」というライブラリを利用していきます。

OpenZepplinのインストール

「OpenZepplin」は、ERC20などの再利用可能なコントラクトを提供しているフレームワークです。

OpenZeppelin

一からセキュアなプログラムを開発しなくても、「OpenZepplin」上のコードを再利用することで効率的にトークンの作成を行うことができます。

「OpenZepplin」はnpmを利用してプロジェクトにインストールします。

ターミナルからプロジェクトディレクトリに移動して、下記のコマンドを実行します。

//パッケージJSONを作成 
$ npm init -f

//OpenZeppelinのインストール 
$ npm install openzeppelin-solidity

上記のコマンドを実行すると、プロジェクトディレクトリ内に「node_modules」というディレクトリが自動で作成され、その中に「openzeppelin-solidity」がインストールされています。

node_modules/openzeppelin-solidity

コントラクトファイルの作成

まずは「contracts」ディレクトリ内にファイルを新規作成します。

お好きな名前で作りましょう。

ここではファイル名を「SimpleToken.sol」として作成しています。

contracts/SimpleToken.sol

続いてコントラクトの中身を以下のように作成します。

pragma solidity ^0.5.0;

import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol";

contract SimpleToken is ERC20, ERC20Detailed {
    
}

まずはじめに、コントラクトが動作するSolidityのバージョンを指定します。

その次の「import」では、「OpenZepplin」の「ERC20.sol」と「ERC20Detailed.sol」というプログラムを利用できるように読み込みます。

クラスを継承するには「コントラクト名 is 継承の参照」という形で定義します。

ERC20.sol

「ERC20.sol」はEIP20で定義されたメソッドおよび、それらを利用したトークン処理のロジックが作成されています。

ERC20.sol | openzeppelin-solidity

ERC20Detailed.sol

「ERC20Detailed.sol」はトークンの詳細を定義することができるコントラクトです。

定義できる内容は以下の3つです。

・name (トークンの名前)

・symbol (トークンの単位)

・decimals (トークンの最小単位)

ERC20Detailed.sol | openzeppelin-solidity

コントラクトのロジック作成

まずはコントラクトの「constructor」を以下のように定義します。

「constructor」はコントラクトがデプロイされたときに一度だけ呼び出される関数です。

ここでの「constructor」は、トークンの名前(name)、シンボル(simbol)、最小単位(decimals)、初回に発行するトークンの量(initSupply)を引数で受け取ります。

受け取ったname・simbol・decimalsを「ERC20Detailed」のconstructorに渡して、トークンの詳細をブロックチェーンに記録します。

最後に「ERC20.sol」の「_mint()」を実行します。

「_mint()」はトークンを発行して、指定したイーサリアムアカウントにトークンを送ります。

マイグレーション

マイグレーションはコントラクトのデプロイや、デプロイ時に行いたい処理などを作成できます。

マイグレーションは「migrations」ディレクトリに内に作成していきます。

マイグレーションのファイル名は「番号_作業内容_コントラクト名称」という形でつけることが一般的と言われています。

スクリプトのファイル名は番号から開始し、アンダースコアで作業内容、さらにアンダースコアでコントラクト名称を入れることが一般的です。

加嵜 長門(著)・篠原 航(著)・丸山 弘詩(編)(2018)『ブロックチェーン・アプリケーション開発の教科書』(マイナビ出版)P.231

マイグレーションファイルは以下のようになります。

最小単位(decimals)の設定はトークンの用途によって決めるといいです。

・1トークンが現実世界の何か1つを表すとき、 decimals を 0 に

・小数以下の桁が決まってるとき、decimals をその桁数に

・どちらでもないとき、細かくトークンを使えるように decimalsを18に

ERC-20トークンコントラクトはどのように動いているのか | The Coffee Times

ここでは特に用途は決まっていないのでETHと同じ「1ST = 1×10の18乗」としています。

またトークンの初回発行量は「100ST」としています。

Web3.jsでは巨大な数字を扱う際は「bn.js」ライブラリを利用していますので、以下のように「bn.js」のインスタンスに変換しています。

const initSupply = web3.utils.toBN(100*(10**decimals));

https://web3js.readthedocs.io/en/1.0/web3-utils.html#tobn

テスト

テストコードの作成

作成したコントラクトの動作を検証する「テストコード」を作成していきます。

テストコードは「test」ディレクトリ内に作成します。

テストコードのファイル名は分かりやすいようにコントラクトの名前にしておきましょう。

コントラクトのテストコードは以下のようになります。

上記のテストコードでは、コントラクトがデプロイされた際に、デプロイしたアカウントアドレスに100STトークン発行されているかどうかを検証しています。

プライベートネットへの接続設定

テストを実行する前に「Ganache」への接続設定をしていきます。

「truffle-config.js」を開き、49~53行あたりを以下のように修正します。

development: {
    host: "127.0.0.1",
    port: 7545,
    network_id: "*",
},

【2019/1/6 追記】openzeppelin@v2.1.1からSolidity@v0.5.0に対応したため、以下の修正は不要です。

続いて92行目付近にある、コンパイルのバージョンを以下のように修正します。

// Configure your compilers
  compilers: {
    solc: {
      version: "0.4.24",
      以下省略...

Truffleのv5.0.0からは、solidityのv0.5.0を利用してコンパイルされるようになりました。

しかしこの記事執筆時点(2018年12月時点)では、solidity-v0.5.0でopenzeppelinのコードをコンパイルするとエラーになります。

そのためコンパイルバージョンは「0.4.24」に指定しています。

テストの実行

それでは「Ganache」を起動して、コントラクトのテストを実行していきます。

アプリケーションを開くと自動でプライベートネットが構成される

続いてターミナルからプロジェクトディレクトリに移動し、下記のコマンドでテストを実行します。

$ truffle test

以下のようになればテスト成功です。

テストの実行結果

作成したERC20トークンの確認

デプロイ

それでは作成したコントラクトをプライベートネット内にデプロイしていきます。

完成したコードはGitHubで公開してありますので、よければご利用ください!

https://github.com/kojimaro/ERC20Tutorial

以下のコマンドを実行することでコントラクトをデプロイすることができます。

$ truffle migrate

成功すると以下のようにターミナル上に表示されます。

コントラクトのデプロイを実行した結果

コントラクトを動かす

デプロイしたコントラクトを動かしていきましょう。

まずは以下のコマンドを実行してプライベートネットのノードにアクセスします。

$ truffle console

以下のような表示になればノードにアクセスしています。

「truffle console」の実行結果

続いてコントラクトのインスタンスを生成して、instance変数に格納します。

SimpleToken.deployed().then(i=>instance=i)

以下の内容を実行して、トークン名を表示できればインスタンスの生成に成功しています。

instance.name()

instance.name()の実行結果

次にイーサリアムアカウントを取得して、accounts変数に格納します。

web3.eth.getAccounts().then(a=>accounts=a)

以下の内容を実行して出力されたアドレスが、Ganacheで一番上に表示されているアドレスと同じかどうか確認しておきましょう。

accounts[0]

accounts[0]の実行結果

Ganacheで自動生成されたインデック番号[0]のアドレス

次にaccounts[0]のトークンの残高を取得して、balance変数に格納します。

instance.balanceOf(accounts[0]).then(b=>balance=b)

続いて単位を変換します。initSupplyで指定したトークンの量が表示されていれば成功です。

web3.utils.fromWei(balance, "ether")

単位変換の結果

コントラクトのデプロイは、インデックス番号[0]のアカウント(コインベースアカウント)で行われます。

そのため、初回発行のトークンはaccounts[0]のアドレスに付与されています。

終了するには以下のコマンドを実行しましょう。

.eixt

おわりに

以上、シンプルなERC20トークンを作成するチュートリアルでした。

OpenZeppelinを利用すればさらに、トークンの追加発行や処分などが行えるように機能を拡張することができます。

ぜひ次のチュートリアルに進んで、トークンの追加発行の機能を実装してみてください!

ERC20トークンの追加発行機能を実装しよう!【OpenZeppelin2.0】

Dapps開発のチュートリアル動画

Dapps開発のチュートリアル動画をYoutubeで公開しています!

よろしかったらチャンネル登録をよろしくお願いします!

ERC20トークンカテゴリの最新記事