Ethereumのコントラクト作成チュートリアルで、オリジナルコインを作るチュートリアルがあります。
CREATE YOUR OWN CRYPTO-CURRENCY WITH ETHEREUM
このチュートリアルでは、ウォレットアプリを利用してコントラクトをブロックチェーンに組み込んでいますが、コンソール上で行ってみたのでメモとして残しておきます。
コントラクトをsource
に格納します。
var source = "contract tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData); } contract MyToken {string public standard = 'Token 0.1';string public name;string public symbol;uint8 public decimals;uint256 public totalSupply;mapping (address => uint256) public balanceOf;mapping (address => mapping (address => uint256)) public allowance;event Transfer(address indexed from, address indexed to, uint256 value);function MyToken(uint256 initialSupply,string tokenName,uint8 decimalUnits,string tokenSymbol) {balanceOf[msg.sender] = initialSupply;totalSupply = initialSupply;name = tokenName;symbol = tokenSymbol;decimals = decimalUnits;msg.sender.send(msg.value);}function transfer(address _to, uint256 _value) {if (balanceOf[msg.sender] < _value) throw;if (balanceOf[_to] + _value < balanceOf[_to]) throw;balanceOf[msg.sender] -= _value;balanceOf[_to] += _value;Transfer(msg.sender, _to, _value);}function approveAndCall(address _spender, uint256 _value, bytes _extraData)returns (bool success) {allowance[msg.sender][_spender] = _value;tokenRecipient spender = tokenRecipient(_spender);spender.receiveApproval(msg.sender, _value, this, _extraData);return true;}function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {if (balanceOf[_from] < _value) throw;if (balanceOf[_to] + _value < balanceOf[_to]) throw;if (_value > allowance[_from][msg.sender]) throw;balanceOf[_from] -= _value;balanceOf[_to] += _value;allowance[_from][msg.sender] -= _value;Transfer(_from, _to, _value);return true;}function () {throw;}}"
solidityでコンパイルし、sourceComoiled
に格納します。
var sourceCompiled = eth.compile.solidity(source)
ABIをmyTokenAbiDefinition
にセット。
var myTokenAbiDefinition = sourceCompiled.MyToken.info.abiDefinition
ABIを使ってコントラクトオブジェクト作成
var myTokenCompiledContract = eth.contract(myTokenAbiDefinition)
コントラクトのコンストラクタ用の変数を定義
var initialSupply = 100000;
var tokenName = "MyCoin";
var decimalUnits = 2;
var tokenSymbol = "Test";
コントラクトをEthereumネットワークに送信する前に、送信者のアカウントアンロックを行います。
> personal.unlockAccount(eth.accounts[0])
Unlock account 0x3d84a1bb905e2b17980c1b9abb5bb0d8c15fa84f
Passphrase:
true
引数を与え、マイニングされるように十分なgasを設定してコントラクトをEthereumネットワークに送信します。
var myTokenContract = myTokenCompiledContract.new(initialSupply, tokenName, decimalUnits, tokenSymbol,{from:eth.accounts[0], data: sourceCompiled.MyToken.code, gas: 2000000})
マイニングを行います。
> miner.start()
しばらくすると、マイニングが行われ、コントラクトが組み込まれ、コントラクトのaddressを得ることができます。
> myTokenContract.address
"0xf1a5d1f653b61b9c23505b780403f58031cc2fd4"
現在は何もコインの送信をしていないため、各アカウントのコイン保有量は初期値のまま。
> myTokenContract.balanceOf(eth.accounts[0])
100000
> myTokenContract.balanceOf(eth.accounts[1])
0
ここで、アカウント1ユーザーがコントラクトにアクセスをし、自分にコインを10送りたいという状況を考えます。
既にブロックチェーン上に存在しているコントラクトを別のユーザーがアクセスして使いたい場合、そのコントラクトのアドレスとABIが必要です。
アカウント1のユーザーは、コントラクトのアドレスとABIを既に教えられているものだと想定してみます。
コントラクトアクセス用のオブジェクトを作成して、cntに格納します。
var cnt = eth.contract([{constant: true,inputs: [],name: "name",outputs: [{name: "",type: "string"}],type: "function"}, {constant: true,inputs: [],name: "totalSupply",outputs: [{name: "",type: "uint256"}],type: "function"}, {constant: false,inputs: [{name: "_from",type: "address"}, {name: "_to",type: "address"}, {name: "_value",type: "uint256"}],name: "transferFrom",outputs: [{name: "success",type: "bool"}],type: "function"}, {constant: true,inputs: [],name: "decimals",outputs: [{name: "",type: "uint8"}],type: "function"}, {constant: true,inputs: [],name: "standard",outputs: [{name: "",type: "string"}],type: "function"}, {constant: true,inputs: [{name: "",type: "address"}],name: "balanceOf",outputs: [{name: "",type: "uint256"}],type: "function"}, {constant: true,inputs: [],name: "symbol",outputs: [{name: "",type: "string"}],type: "function"}, {constant: false,inputs: [{name: "_to",type: "address"}, {name: "_value",type: "uint256"}],name: "transfer",outputs: [],type: "function"}, {constant: false,inputs: [{name: "_spender",type: "address"}, {name: "_value",type: "uint256"}, {name: "_extraData",type: "bytes"}],name: "approveAndCall",outputs: [{name: "success",type: "bool"}],type: "function"}, {constant: true,inputs: [{name: "",type: "address"}, {name: "",type: "address"}],name: "allowance",outputs: [{name: "",type: "uint256"}],type: "function"}, {inputs: [{name: "initialSupply",type: "uint256"}, {name: "tokenName",type: "string"}, {name: "decimalUnits",type: "uint8"}, {name: "tokenSymbol",type: "string"}],type: "constructor"}, {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"}]).at("0xf1a5d1f653b61b9c23505b780403f58031cc2fd4");
コインを10枚、アカウント0からアカウント1に送りましょう。
cnt.transfer.sendTransaction(eth.accounts[1], 10, {from:eth.accounts[0]})
マイニングを行います。
> miner.start()
暫くしますと、マイニングが完了して、下記のように、元のコントラクトでオリジナルコインの移動が行われたことが確認できました。
> myTokenContract.balanceOf(eth.accounts[1])
10
> myTokenContract.balanceOf(eth.accounts[0])
99990