Lean Engineer

リーンエンジニア〜効率的に実験しながら、技術を学ぶブログ

スマートコントラクトで独自トークンを発行し、Metamaskを使ってブラウザで送ってみる

 イーサリアムの面白いところは、スマートコントラクトを使い、簡単に自分のトークンを発行できるところだろう。これを利用してICOであったり、CryptoKittiesが作られている。

 さて、今回はICOなどにも使われている一番オーソドックスなトークンを発行してみたい。ERC 20という規格の名前のトークンだ。

Truffleを使う

 スマートコントラクトの開発環境は様々あるが、Truffleを使うのが便利そうだ。

 さて、Truffleをインストールして、プロジェクトを作ってみよう

$ npm install -g truffle
$ truffle init

 これで、必要なファイルがいろいろと作られたはずだ。次に必要なnode moduleがあるので、インストールする。

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

ERC 20準拠のコードを書く

 「 Truffle で始める Ethereum 入門 - ERC20 トークンを作ってみよう 」を参考にしながら、ERC 20準拠のトークンを作っていく(この記事では、KasajeiTokenを作成します!適当に自分の名前を付けて下さい)。まずは、contractsフォルダの中にKasajeiToken.solというファイルを作成すし、以下のように記述する。

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

// StandardTokenがERC 20に準拠しているOpenZeppleinのToeken
contract KasajeiToken is StandardToken {
  string public name = "KasajeiToken"; // トークンの名前
  string public symbol = "KSJT"; // 通貨の単位 BTC / ETHみたいな
  uint public decimals = 18; 

// 最初の供給量(initialSupply)がコンストラクタの引数になっている
  function KasajeiToken(uint initialSupply) public {
    totalSupply = initialSupply;
    balances[msg.sender] = initialSupply;
  }
}

 このコードが、スマートコントラクトの実態だ。ここで、コンパイルしてみる。

$ truffle compile

 コンパイルが終わると、build/contracts/KasajeiToken.jsonというファイルができている。Contract Artifactといい、スマートコントラクトのインターフェースが定義されている。

マイグレーションファイルを作る

 次に、このスマートコントラクトをデプロイするための、マイグレーションファイルを作る。先程のスマートコントラクトに、トークンの初期の供給量を与え、コンストラクタを呼び出し、トークンをデプロイする。migrationsフォルダ以下に、2_deploy_kasajei_token.jsを作る。

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

module.exports = (deployer) => {
  let initialSupply = 50000e18
  deployer.deploy(KasajeiToken, initialSupply)
}

 今回は、50,000 KSJT発行しちゃう!これをデプロイすると、デプロイしたアカウントが50,000 KSJT持っている状態になる。

ローカル環境にデプロイ

 ローカル環境にデプロイしてみる。

$ truffle develop
Truffle Develop started at http://localhost:9545/
....
truffle(develop)> 

 これで、ローカル環境にイーサリアムのブロックチェーン環境が実行され、truffleのコンソールに入っている状態になる。さて、デプロイだ!

truffle(develop) > migrate

 これで、migrationsのファイルに入っているJSが実行される。実行が上手く行けば、web3.eth.accounts[0]に50,000 KSJTが発行されている。こちらの記事に従ってコンソールでトークンを移動したりして遊んでみよう。どんな関数が定義されているかはbuild/contracts/KasajeiToken.jsonを見ればなんとなくわかる。

 あとで使うので、truffleコンソールのweb3.eth.accounts[0]のアドレスを調べておく。

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

Metamaskで遊ぶ

MetamaskをインストールしてETHを送ってみる

 さて、WebのUIを作るにはどうすればいいだろうか。それには、Metamaskを使うのが簡単だ。Chromeのextensionになっているので、インストールしよう。そして、ローカルで動いているネットワークに繋げるために、Custom RPCにhttp://localhost:9545を設定する。

 まずは、Metamaskのアカウントに1ETH送ってみる(僕のMetamaskのアドレスは0x97e7320814444F5f5274d78b1Ba1E2df5Ec8680fだ)。

truffle(develop)>web3.eth.sendTransaction({from:web3.eth.accounts[0], to:"0x97e7320814444F5f5274d78b1Ba1E2df5Ec8680f", value: web3.toWei(1, "ether")})

 これで、1ETHがMetamaskのアカウントに入金されているか確認しよう。

MetamaskをインストールしてKSJTを送ってみる

 次に、MetamaskのアカウントにKSJTを送ってみよう。まずは、KasajeiTokenのインスタンスを生成し、web3.eth.accounts[0]のKSJTの所持数を見てみよう。

truffle(develop)> kasajeiToken = KasajeiToken.at(KasajeiToken.address)
truffle(develop)> kasajeiToken.balanceOf(web3.eth.accounts[0])
{ [String: '5e+22'] s: 1, e: 22, c: [ 500000000 ] }

 持っていることがわかったので、Metamaskのアカウントへ送金しよう。1000KSJT送金している。

truffle(develop)> kasajeiToken.transfer("0x97e7320814444F5f5274d78b1Ba1E2df5Ec8680f", 1000e18)

 これで、metamask側で確認すると、指定したアドレスのアカウントに1000KSJTが付与されている。確認するには、MetamaskのUIからAdd Tokenして、KSJTのアドレスを入力する必要がある。

truffle(develop)> KasajeiToken.address
0x345ca3e014aaf5dca488057592ee47305d9b3e10

 やったね!

Webコンソールで遊ぶ

 次は、これをWebインターフェースで実装したい。Chromeで適当なページを開き、コンソールを立ち上げて確認していこう。Metamaskがインストールされていると、web3がインジェクションされている状態になっている。

> web3.eth.accounts[0]
<-"0x97e7320814444f5f5274d78b1ba1e2df5ec8680f"

 このような形で、Metamaskに設定されているアカウントが取得できる。

 まずは、コントラクトをコンソールで使えるようにする必要がある。必要なのは、コントラクトのアドレス0x345ca3e014aaf5dca488057592ee47305d9b3e10 と、ABIだ。コントラクトのアドレスとABIはtruffleのコンソールで以下のように取得できる。利用するときは、一番外のシングルクオートは外して使う。

truffle(develop)> JSON.stringify(kasajeiToken.abi)
'[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialSupply","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]'

 コントラクトを生成する。

> var contractAddress = "0x19dcf42be19806076a9f997708d79cae7c6d7954";
> var abiArray = [先程のArray];
> window.web3 = new Web3(web3.currentProvider);
> var contract = web3.eth.contract(abiArray).at(contractAddress);

 コントラクトが作れたら、これで送金だ。さて、先程しらべておいたtruffleのweb3.eth.accounts[0]→ 0x627306090abab3a6e1400e9345bc60c78a8bef57 に送金してみる。

>contract.transfer("0x627306090abab3a6e1400e9345bc60c78a8bef57", 1e18, {from: web3.eth.defaultAccount}, function(err, txhash){})

 これで、Submitをクリックすると送金できる。Metamaskで確認してみる。

 あとは、UIを作ったりすれば良い。Webインターフェースまで作ったコードはgithub.com/kasajei/KSJTokenに公開してある。loz84氏の「Ethereum上のトークンを送金するWebアプリを作ってDecentralizedな方法で公開してみる」を参考に、vue.jsを使って書いてある(ちょっとだけシンプルにした)。

 スマートコントラクトおもしろい!!

堅牢なスマートコントラクト開発のためのブロックチェーン[技術]入門

堅牢なスマートコントラクト開発のためのブロックチェーン[技術]入門