ERC20準拠のトークン
ERC20とは、イーサリアム上のトークンを標準化する仕様のことです。
ERC20に準拠するトークンをERC20準拠のトークンと呼びます。
ERC20に準拠することで、異なるトークン同士でのやり取りが簡単になり、ERC20対応のウォレットでの取り扱いが可能となります。
詳しくはこちらを参照してください。
ERC20 Token Standard - The Ethereum Wiki
プロジェクト作成
$ mkdir dapps-token $ cd dapps-token $ truffle init
OpenZeppelinのインストール
OpenZeppelinは、Solidity言語でセキュアにスマートコントラクトを開発できるオープンソースフレームワークです。
$ npm init -f $ npm install zeppelin-solidity
トークンコントラクトの作成
contracts/にDappsToken.solファイルを作成し、トークンコントラクトの実装を行います。
pragma solidity ^0.4.18;
import "zeppelin-solidity/contracts/token/ERC20/StandardToken.sol";
contract DappsToken is StandardToken {
string public name = "DappsToken";
string public symbol = "DTKN";
uint public decimals = 18;
function DappsToken(uint initialSupply) public {
totalSupply_ = initialSupply;
balances[msg.sender] = initialSupply;
}
}
dapps-token/DappsToken.sol at master · akifumi/dapps-token · GitHub
デプロイ時に動作するスクリプトを記述します。
migrations/に2_deploy_dapps_token.jsファイルを作成します。
var DappsToken = artifacts.require("./DappsToken.sol"); module.exports = function(deployer) { var initialSupply = 1000; deployer.deploy(DappsToken, initialSupply); };
dapps-token/2_deploy_dapps_token.js at master · akifumi/dapps-token · GitHub
テストコードの作成
tests/にDappsToken.jsファイルを作成します。
var DappsToken = artifacts.require("./DappsToken.sol"); contract('DappsToken', function(accounts) { it("should put 1000 DappsToken in the first account", function() { return DappsToken.deployed().then(function(instance) { return instance.balanceOf.call(accounts[0]); }).then(function(balance) { assert.equal(balance.valueOf(), 1000, "1000 wasn't in the first account"); }); }); });
dapps-token/DappsToken.js at master · akifumi/dapps-token · GitHub
テストを実行します。
$ truffle develop truffle(develop)> test
migrateコマンドでdevelopネットワークにデプロイし、設定した名前などを確認しましょう。
truffle(develop)> migrate
truffle(develop)> dappsToken = DappsToken.at(DappsToken.address)
truffle(develop)> dappsToken.name()
'DappsToken'
truffle(develop)> dappsToken.symbol()
'DTKN'
truffle(develop)> dappsToken.totalSupply()
{ [String: '1000'] s: 1, e: 3, c: [ 1000 ] }
アカウント別の発行量を確認します。
アカウントの1番目は発行者なので、トークンを全額保持しています。
アカウントの2番目は保持量が0です。
truffle(develop)> dappsToken.balanceOf(web3.eth.accounts[0])
{ [String: '1000'] s: 1, e: 3, c: [ 1000 ] }
truffle(develop)> dappsToken.balanceOf(web3.eth.accounts[1])
{ [String: '0'] s: 1, e: 0, c: [ 0 ] }
送金してみましょう。
送金完了後に各アカウントが所持するトークン数を確認すると、トークンが正常に動作していることがわかります。
truffle(develop)> dappsToken.transfer(web3.eth.accounts[1], 100)
{ tx: '0xf001aa4460728b5b75b96e7afdc72e739d5a53cf71dffc4cb6323b83d1d5b2d0',
receipt:
{ transactionHash: '0xf001aa4460728b5b75b96e7afdc72e739d5a53cf71dffc4cb6323b83d1d5b2d0',
transactionIndex: 0,
blockHash: '0x933600dadc8888729d6d538a27944088e37859b2d931af5f5e1a19a9f15e780f',
blockNumber: 13,
gasUsed: 51519,
cumulativeGasUsed: 51519,
contractAddress: null,
logs: [ [Object] ],
status: '0x01',
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000008000000000000000000010000000080000000000000000000000000000000000000000000000000000000000000000010000000000000000000010000000000000000000000000000000000000000010000000002000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000010000000000000' },
logs:
[ { logIndex: 0,
transactionIndex: 0,
transactionHash: '0xf001aa4460728b5b75b96e7afdc72e739d5a53cf71dffc4cb6323b83d1d5b2d0',
blockHash: '0x933600dadc8888729d6d538a27944088e37859b2d931af5f5e1a19a9f15e780f',
blockNumber: 13,
address: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
type: 'mined',
event: 'Transfer',
args: [Object] } ] }
truffle(develop)> dappsToken.balanceOf(web3.eth.accounts[0])
{ [String: '900'] s: 1, e: 2, c: [ 900 ] }
truffle(develop)> dappsToken.balanceOf(web3.eth.accounts[1])
{ [String: '100'] s: 1, e: 2, c: [ 100 ] }