MintableTokenを理解して作成してみた

トークンを管理者で追加発行したい、、、

最初はStandardTokenにonlyOwnerをつけてトークン量を加算しよう、そんな感じで実装しようとしていましたが、いろいろ調べるうちに、OpenZeppelinにMintableというトークンがあることがわかりました。

それならば、せっかくフレームワークにあるのに、使わないわけにはいかない、ということで、作成してみたいと思います。

ミンタブルトークンは

openzeppelin-solidity->contracts->token->ERC20->MintableToken.sol

にあります。

※アカウント間で送金のみできる、基本的なトークンは以下の記事で作成しました。

MintableTokenのコード

MintableTokenの全貌は↓

pragma solidity ^0.4.21;

import "./StandardToken.sol";
import "../../ownership/Ownable.sol";

/**
* @title Mintable token
* @dev Simple ERC20 Token example, with mintable token creation
* @dev Issue: * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/120
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
*/
contract MintableToken is StandardToken, Ownable {
  event Mint(address indexed to, uint256 amount);
  event MintFinished();

  bool public mintingFinished = false;

  modifier canMint() {
    require(!mintingFinished);
    _;
  }

  /**
  * @dev Function to mint tokens
  * @param _to The address that will receive the minted tokens.
  * @param _amount The amount of tokens to mint.
  * @return A boolean that indicates if the operation was successful.
  */
  function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
    totalSupply_ = totalSupply_.add(_amount);
    balances[_to] = balances[_to].add(_amount);
    emit Mint(_to, _amount);
    emit Transfer(address(0), _to, _amount);
    return true;
  }

  /**
  * @dev Function to stop minting new tokens.
  * @return True if the operation was successful.
  */
  function finishMinting() onlyOwner canMint public returns (bool) {
    mintingFinished = true;
    emit MintFinished();
    return true;
  }
}

importをみるとわかる通り、MintableTokenはOwnable.sol(管理者のみ実行できる機能)と、StandardTokenの機能を組み合わせてできています。

contractは、StandardTokenとOwnableを継承していますね。

このMintableToken.solで新たに追加されているメソッドとしては、

・mint(“トークン追加先アドレス”, 追加トークン量)

・finishMinting()

があります。

finishMintingメソッドはmintingFinishedフラグを変更するだけのものですね。一回実行してフラグをtrueにすると、mintもmintingFinishedも実行できなくなります。トークン発行の必要が無くなったら実行して追加発行を凍結するみたいなイメージでしょうか。

このMintableTokenを継承して自分のトークンをつくれば、簡単に管理者のみトークン追加が可能なトークンを作れそうです。

実装してみる

以下のコードを書くだけです 笑

以前の記事のトークンのほぼ使いまわしです^^;

pragma solidity ^0.4.18;

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

contract mymint is MintableToken{
  string public name = "mymint";
  string public symbol = "MYMNT";
  uint public decimals = 18;

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

StandardTokenと違うところは、

・importでMintableToken.solをインポートしているところ

・contractの継承がMitableTokenになるところ

だけでしょうか・・・

完成です 笑

動かしてみる

もちろん、migrationフォルダ内には「2_deploy_mymint.js」を配置してください。

StandardTokenの時に使用したものと同じです。(requireの.solの参照先はファイル名に合わせて変更)

var mytoken = artifacts.require("./mymint.sol");

module.exports = function(deployer){
  var initialSupply = 21000000e18
  deployer.deploy(mytoken, initialSupply, {
    gas: 2000000
  })
}

2_deploy_mymint.js

それでは、truffleの開発用ブロックチェーンを起動してみます。

truffle develop

次に、例のごとくマイグレーションします。

migrate

コンパイル→ブロックチェーンにデプロイされると、

mymint: 0x……..

とコントラクトのアドレスが表示されますので、そのアドレスはひかえておきます。

a = mymint.at("0x...↑でコピーしたアドレスです。")

として、aですぐにメソッドを呼び出せるようにします。

まずはトークン総量の確認から

a.totalSupply()

次に、mintメソッドを実行してみます。

a.mint("developのアカウント0のアドレス", 1000e18)

developのアカウント0のアドレスはtruffle develop起動時にでるアカウント0のアドレスです。ここでは、アカウント0のアドレスに1000MYMNT追加しています。

a.totalSupply()

でトークン量の確認、ふえてますね。

最後に、

a.finishMinting()

発動しました。これで、このトークンがメインネットやテストネットにあった場合、永久に追加発行できなくなりました。もう一度、

a.mint("developのアカウント0のアドレス", 1000e18)

をしてもエラーで実行されません。

ということで、何とか管理者のみトークンを増やすことができるトークンが作成できました。

◆オススメの書籍

ブロックチェーンの概要、スマートコントラクトの概要から、ビットコイン、イーサリアムの違い、イーサリアムのコントラクトを実装するための開発環境構築など、ブロックチェーンアプリケーションの入門にはもってこいの書籍です。