Skip to content

基本的なトークンの作り方

dogecrypto edited this page Jun 25, 2018 · 70 revisions

基本的なトークンの作り方の流れ

OpenZeppelin使うのが定番

  • OpenZeppelinはバージョンの違いでかなりの変更が起きるケースがあるっぽいので--saveではなく-Eを利用するのがポイント
    • -E (--save-exact)
    • バージョンを確認するのも重要
npm install -g truffle
mkdir myproject && cd myproject
truffle init


npm init -y
npm install -E openzeppelin-solidity

touch contracts/ExampleToken.sol
touch migrations/2_deploy_contracts.js

ganache-cli

Version確認

truffle version
Truffle v4.1.12 (core: 4.1.12)
Solidity v0.4.24 (solc-js)

node version
v8.8.1

cat contracts/Migrations.sol
pragma solidity ^0.4.23;

"openzeppelin-solidity": "1.10.0"

基本的なERC20トークン

StandardTokenを使うとよい、MintableTokenとかでもOK。

ExampleToken.sol

decimalsが18のトークンを100000作成

pragma solidity ^0.4.23;
import "openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol";

contract ExampleToken is StandardToken {
  string public name = "ExampleToken";
  string public symbol = "EGT";
  uint public decimals = 18;
  uint public INITIAL_SUPPLY = 10000 * (10 ** decimals);

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

Migrationファイル設定

2_deploy_contracts.js

var coin = artifacts.require("./ExampleCoin.sol");

module.exports = function(deployer) {
  deployer.deploy(coin);
};

truffle.js設定

module.exports = {
    networks: {
        development: {
            host: "localhost",
            port: 8545,
            network_id: "*" // Match any network id
        }
    }
};

コンパイルとマイグレーション

truffle compile
truffle migrate

ちなみにマイグレーションリセットはよく使う

truffle migrate --reset

Consoleからのdeployと各種基本処理

[~]$ truffle console

// デプロイ
ExampleToken.deployed().then(inst => { token = inst })

token.totalSupply()
BigNumber { s: 1, e: 22, c: [ 100000000 ] }

owner = web3.eth.accounts[0]

token.balanceOf(owner)
BigNumber { s: 1, e: 22, c: [ 100000000 ] }

receiver = web3.eth.accounts[1]

// トークンの送信
token.transfer(receiver, web3.toWei(1, "ether"))

token.balanceOf(owner)
BigNumber { s: 1, e: 21, c: [ 99990000 ] }

token.balanceOf(receiver)
BigNumber { s: 1, e: 18, c: [ 10000 ] }

token.balanceOf(owner).then(balance => ownerBalance = balance.toString(10))
'9999000000000000000000'
web3.fromWei(ownerBalance, "ether")
'9999'

MintableToken

MintableToken利用すると、オーナー変更したり新しくコイン作れたりして便利 クラウドセールとかをする時はオーナーを変更して実行する

ExampleTokenをStandardTokenからMintableTokenに変更

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

contract ExampleToken is MintableToken {
  string public name = "ExampleToken";
  string public symbol = "EGT";
  uint public decimals = 18;
  uint public INITIAL_SUPPLY = 10000 * (10 ** decimals);

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

コンパイルとマイグレーション

truffle compile 
truffle migration --reset

コンソールからの各種処理

[~]$ truffle console

ExampleToken.deployed().then(inst => { token = inst })

owner = web3.eth.accounts[0]
token.balanceOf(owner)
BigNumber { s: 1, e: 22, c: [ 100000000 ] }

// コイン作成
token.mint(owner, 1 * 10 ** 18)

token.balanceOf(owner)
BigNumber { s: 1, e: 22, c: [ 100010000 ] }

// オーナー変更
newOwner = web3.eth.accounts[1]
token.transferOwnership(newOwner)

// オーナーでなくなったので、コインの作成ができなくなる
token.mint(owner, 1 * 10 ** 18)
Error: VM Exception while processing transaction: revert

BurnableToken

BurnableToken利用すると、コインを減らすことができる burnはpublic関数なので、だれでも自分のコインを減らせることに注意

ExampleTokenにBurnableTokenを追加

pragma solidity ^0.4.23;
import "openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol";
import "openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol";

contract ExampleToken is MintableToken, BurnableToken {
  string public name = "ExampleToken";
  string public symbol = "EGT";
  uint public decimals = 18;
  uint public INITIAL_SUPPLY = 10000 * (10 ** decimals);

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

コンパイルとマイグレーション

truffle compile 
truffle migration --reset

コンソールからの各種処理

[~]$ truffle console

ExampleToken.deployed().then(inst => { token = inst })

owner = web3.eth.accounts[0]
token.balanceOf(owner)
BigNumber { s: 1, e: 22, c: [ 100000000 ] }

// コインを減少させる
token.burn(1 * 10 ** 18)

token.balanceOf(owner)
BigNumber { s: 1, e: 21, c: [ 99990000 ] }

// コインの増加も可能

token.mint(owner, 1 * 10 ** 18)

token.balanceOf(owner)
BigNumber { s: 1, e: 22, c: [ 100000000 ] }

truffleの各種コマンド

基本コマンド

truffle init
truffle create contract ExampleCoin
truffle compile
truffle migrate
truffle migrate --reset

truffle console
truffle develop
truffle test

コンソール

migrate --reset

デプロイ

ネットワークにデプロイするためにライブラリ追加

npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet

設定ファイル

  • .envファイルをルートディレクトリに作成し、以下のようにWalletのプライベートキーを指定する
    • mainnetを使わない場合は、ropstenのキー設定しておくとよい
    • なんも設定してないとWallet作成エラーになる

.env

ROPSTEN_PRIVATE_KEY="key"
MAINNET_PRIVATE_KEY="key"

truffle.jsを編集して各種ネットワークの情報を設定する

truffle.js

const WalletProvider = require("truffle-wallet-provider");
const Wallet = require('ethereumjs-wallet');

require('dotenv').config();

var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
var mainnetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")

var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");

var mainnetWallet = Wallet.fromPrivateKey(mainnetPrivateKey);
var mainnetProvider = new WalletProvider(mainnetWallet, "https://mainnet.infura.io/");

module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!

  networks: {
    development: {
      host: "127.0.0.1",
      port: 9545,
      network_id: "*"
    },
    ropsten: {
      provider: ropstenProvider,
      // You can get the current gasLimit by running
      // truffle deploy --network ropsten
      // truffle(rinkeby)> web3.eth.getBlock("pending", (error, result) =>
      //   console.log(result.gasLimit))
      network_id: "3",
    },
    mainnet: {
      provider: mainnetProvider,
      network_id: "1",
    }
  }
};

デプロイコマンド

デプロイにはイーサリアムが必要になるので、ある程度ウォレットにいれておく必要あり

  • テスト環境(ropsten)のfaucet(ethereumもらえるところ)
  • http://faucet.ropsten.be:3001/
  • 1etheあればデプロイできる感じ
  • 合計大体0.3ether程度必要?

デプロイには数十秒~数分程度時間がかかる

ropstenへのデプロイ

truffle deploy --network ropsten

リセットもできる

truffle deploy --network ropsten --reset

出力結果

Using network 'ropsten'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... 0x8c9031e696ae2d2b19a1ce3f57c14c7226adec8ddcf77772a2615b7b8935acfe
  Migrations: 0xbe1aece5bb028e55f6c96484892eface79a2852e
Saving successful migration to network...
  ... 0xea11b368c94006c69c06e6c60f2c96282d745a10f6d08c663957c7fecc9b0b27
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Replacing ExampleToken...
  ... 0x83de8926b343f55ea88c936df4d60f23408b0b2b98f15b65f020795df7798c0f
  ExampleToken: 0xe6897689c73ea878beb5ff9f698ee4e493c13ba9
Saving successful migration to network...
  ... 0xe1387484779544dd630ad74525bca82ee4030883f73e013798c212c548a01e97
Saving artifacts...

mainnetへのデプロイ

truffle deploy --network mainnet

コンソール

デプロイしたトークンはコンソールから制御することもできる

  • mintやburnは結構時間がかかる
truffle console  --network ropsten

truffle(ropsten)>

token.totalSupply()
BigNumber { s: 1, e: 22, c: [ 100000000 ] }

owner = "0x3dfCEDa23dB363e651e3c3845f4ec54cB5D904eA"
token.balanceOf(owner)
BigNumber { s: 1, e: 22, c: [ 100000000 ] }

token.mint(owner , 1 * 10 ** 18)

token.balanceOf(owner)
BigNumber { s: 1, e: 22, c: [ 100010000 ] }

token.burn(1 * 10 ** 18)

token.balanceOf(owner)
BigNumber { s: 1, e: 22, c: [ 100000000 ] }

EtherScanでの動作確認

EtherScanの各種情報更新方法

  • EtherScanで変更できる情報
    • Code(Verify and Publish your Solidity Source Code )
    • Link(Project Link)

Code

Are you The Contract Creator? Verify And Publish*New your Contract Source Code Today!

solcのバージョンは、出力されたbuild/contracts/ExampleToken.jsonに記載されている

Contract Name

ExampleToken

solc version

0.4.24+commit.e67f0147.Emscripten.clang

Optimization

NO

FlattenされたSolidityのCodeを確認するために、truffle-flattenerをインストールする

npm install truffle-flattener -g

Flattenされたコードを出力してコピーする

/usr/local/bin/truffle-flattener ./contracts/ExampleToken.sol | pbcopy

Code

Constructor Arguments ABI-encoded

今回はコンストラクタにパラメーターがないのでこれは利用しないでよい

無事コード公開できた模様

参考リンク

Link

プロジェクト情報のリンクの付け方

  • 残念ながらメインネット以外は使えないっぽい
  • Contractの作成者かオーナーのウォレットで認証すればできるようになる感じ

クラウドセール

link