Qtum のネットワーク上にERC20トークンを発行する手順、後編です。
前編(環境構築編)はこちらです。
1時間でQtum上に独自のERC20トークンを発行する(環境構築編)
本記事はこちらの非公式チュートリアル(英語)を参考にしています。
[Quantum (Qtum) Blockchain Developer Tutorial - Hello World!]
(https://steemit.com/qtum/@cryptominder/quantum-qtum-blockchain-developer-tutorial-hello-world)
前提条件
- 前編でセットアップした3ノードのQtumネットワークを前提に手順を記します。準備環境が異なる方は読み替えて下さい。1ノードでも以下の手順は実行可能です。
- 前編同様Mac環境を前提としていますが、他の環境でも概ね同様だと思われますので、ご自身の環境に合わせて読み替えて下さい。
-
qtum-cli generate
で現在ブロックを2000以降まで進めてある(Stakingが自動的に行われるようになる、かつQTUM残高が十分にある)ことが前提です。
$ ./qtum-cli-node1.sh getinfo
{
"version": 140301,
"protocolversion": 70016,
"walletversion": 130000,
"balance": 49518908.99886400,
"stake": 1041091.00113600,
"blocks": 3001,
"timeoffset": 0,
"connections": 0,
"proxy": "",
"difficulty": {
"proof-of-work": 4.656542373906925e-10,
"proof-of-stake": 4.656542373906925e-10
},
"testnet": false,
"moneysupply": 60020000,
"keypoololdest": 1520692130,
"keypoolsize": 100,
"paytxfee": 0.00000000,
"relayfee": 0.00400000,
"errors": ""
}
ツール(solc, ethabi)のセットアップ
solc
最初に述べたように、QtumにはEthereumのコントラクトをデプロイできます。そこで、Ethereumの代表的な言語であるSolidityを使ってコントラクトを作成します。
まず、SolidityのコンパイラであるsolcのDockerイメージをpullしてきます。
$ docker pull ethereum/solc:stable
参考元のチュートリアルでは$ docker pull ethereum/solc
としていましたが、これだと:lasestタグを取得しに行ってしまった(存在しない)ので、明示的にstableを指定します。
取得したイメージを実行してバージョンを確認します。
$ docker run --rm -v ${PWD}:/solidity ethereum/solc:stable --version
筆者の環境では以下のバージョンがpullされました。
Version: 0.4.21+commit.dfe3193c.Linux.g++
ethabi
同様にethabiもpullしておきます。
ethabiは、Ethereumコントラクトのfunctionや、そこに与えるパラメータ、返り値を変換してくれるツールです。コントラクトとのインタフェースは全てバイトコードですが、バイトコードは人間にとって視認性が悪いので、ethabiを使って文字列や十進数の数値をエンコード/デコードします。
$ docker pull cryptominder/ethabi
以下のコマンドでhelpが出力されれば正常です。
$ docker run --rm -v ${PWD}:/ethabi cryptominder/ethabi:latest --help
ERC20コントラクトの取得とトークン情報の設定
ERC20のサンプルコードを取得してきます。
コピペでもgit cloneでも構いません。
FixedSupplyToken
https://github.com/bokkypoobah/Tokens/blob/master/contracts/FixedSupplyToken.sol
上記をFixedSupplyToken.sol
として作業ディレクトリ直下に保存しておきます。
コンストラクタ function FixedSupplyToken()の中にある以下の各行を変更することで、独自のトークンにします。
symbol = "FIXED";
name = "Example Fixed Supply Token";
decimals = 18;
_totalSupply = 1000000 * 10**uint(decimals);
上から順に、
- トークンのシンボル名
- トークンの正式名
- 最小分割単位の少数以下の桁数 (18なら、10^-18が最小単位となる。Bitcoinなら10^-8が最小単位=1satoshi)
- トークンの総発行数 (最大100トークンで最小単位が10^-18なら、内部的にはtotalSupplyは100 * 10^18となる)
コントラクトのコンパイル
solcコンパイラを使って以下のようにコントラクトをコンパイルします。
$ docker run --rm -v ${PWD}:/solidity ethereum/solc:stable --optimize --bin --abi --hashes -o /solidity --overwrite /solidity/FixedSupplyToken.sol
サンプルコードは0.4.18で書かれているため、最新のコンパイラ(今回は0.4.21)だと文法的に非推奨(deprecated)という旨の警告がいくつか出ますが、ここでは無視して大丈夫です。
作業ディレクトリに、.abi, .bin, .signaturesという拡張子のファイルがいくつかできます。
ApproveAndCallFallBack.abi
ApproveAndCallFallBack.bin
ApproveAndCallFallBack.signatures
ERC20Interface.abi
ERC20Interface.bin
ERC20Interface.signatures
FixedSupplyToken.abi
FixedSupplyToken.bin
FixedSupplyToken.signatures
Owned.abi
Owned.bin
Owned.signatures
SafeMath.abi
SafeMath.bin
SafeMath.signatures
残高の確認とコントラクトオーナーアドレスの生成
コントラクトをデプロイする前に、トランザクションのfeeを払えるQTUM残高があるか確認します。
$ ./qtum-cli-node1.sh getbalance
4000000.00000000
ひとまず1,000,000以上のの残高があればOKです。(足りない場合はgenerateコマンドでブロックを進めて下さい)
次に、コントラクトオーナーとなるアドレスを生成します。
$ ./qtum-cli-node1.sh getaccountaddress contract_owner
qdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5w
上記のコマンドで、"contract_owner"というアカウントがウォレット上に作成され、アドレスqdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5wがそのアカウントに紐づけられています。
(アドレスはもちろんランダムなので、個々に変わります)
このコマンドは指定したアカウントが未作成であれば新たに生成してアドレスを発行し、既存であれば生成したアドレスを返します。
また、小文字のqで始まるアドレスはテストネット用のアドレスであることを示します。メインネットでは大文字のQから始まります。
作成したアドレスにQTUMを送ります。(同じウォレット内で別のアドレスに振り替えた形です)
これがないとコントラクトデプロイに必要なgasを支払えません。
$ ./qtum-cli-node1.sh qdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5w 1000000
contract_ownerアカウントの残高を調べます。(アカウント名を指定しない場合はウォレット内の全残高になります)
$ ./qtum-cli-node1.sh getbalance contract_owner
1000000.00000000
これでコントラクトデプロイの準備が整いました。
コントラクトのデプロイ
まず、コントラクトのバイトコードを確認します。コンパイル時に生成されたFixedSupplyToken.bin
を開くと、デプロイするべきコードが出力されています。
$ cat FixedSupplyToken.bin
6060604052341561000f57600080fd5b60008054600160a060020a03191633600160a060020a031617905560408051908101604052600581527f464958454400000000000000000000000000000000000000000000000000000060208201526002908051610071929160200190610135565b5060408051908101604052601a81527f4578616d706c6520466978656420537570706c7920546f6b656e000000000000602082015260039080516100b9929160200190610135565b5060048054601260ff19909116179081905560ff16600a0a620f424002600581905560008054600160a060020a039081168252600660205260408083208490558254909116927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915190815260200160405180910390a36101d0565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017657805160ff19168380011785556101a3565b828001600101855582156101a3579182015b828111156101a3578251825591602001919060010190610188565b506101af9291506101b3565b5090565b6101cd91905b808211156101af57600081556001016101b9565b90565b610a9c806101df6000396000f3006060604052600436106100cc5763ffffffff60e060020a60003504166306fdde0381146100d1578063095ea7b31461015b57806318160ddd1461019157806323b872dd146101b6578063313ce567146101de5780633eaaf86b1461020757806370a082311461021a57806379ba5097146102395780638da5cb5b1461024e57806395d89b411461027d578063a9059cbb14610290578063cae9ca51146102b2578063d4ee1d9014610317578063dc39d06d1461032a578063dd62ed3e1461034c578063f2fde38b14610371575b600080fd5b34156100dc57600080fd5b6100e4610390565b60405160208082528190810183818151815260200191508051906020019080838360005b83811015610120578082015183820152602001610108565b50505050905090810190601f16801561014d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561016657600080fd5b61017d600160a060020a036004351660243561042e565b604051901515815260200160405180910390f35b341561019c57600080fd5b6101a461049b565b60405190815260200160405180910390f35b34156101c157600080fd5b61017d600160a060020a03600435811690602435166044356104cd565b34156101e957600080fd5b6101f16105e0565b60405160ff909116815260200160405180910390f35b341561021257600080fd5b6101a46105e9565b341561022557600080fd5b6101a4600160a060020a03600435166105ef565b341561024457600080fd5b61024c61060a565b005b341561025957600080fd5b610261610698565b604051600160a060020a03909116815260200160405180910390f35b341561028857600080fd5b6100e46106a7565b341561029b57600080fd5b61017d600160a060020a0360043516602435610712565b34156102bd57600080fd5b61017d60048035600160a060020a03169060248035919060649060443590810190830135806020601f820181900481020160405190810160405281815292919060208401838380828437509496506107d195505050505050565b341561032257600080fd5b610261610934565b341561033557600080fd5b61017d600160a060020a0360043516602435610943565b341561035757600080fd5b6101a4600160a060020a03600435811690602435166109d6565b341561037c57600080fd5b61024c600160a060020a0360043516610a01565b60038054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104265780601f106103fb57610100808354040283529160200191610426565b820191906000526020600020905b81548152906001019060200180831161040957829003601f168201915b505050505081565b600160a060020a03338116600081815260076020908152604080832094871680845294909152808220859055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a35060015b92915050565b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8546005540390565b600160a060020a0383166000908152600660205260408120546104f6908363ffffffff610a4b16565b600160a060020a0380861660009081526006602090815260408083209490945560078152838220339093168252919091522054610539908363ffffffff610a4b16565b600160a060020a038086166000908152600760209081526040808320338516845282528083209490945591861681526006909152205461057f908363ffffffff610a6016565b600160a060020a03808516600081815260066020526040908190209390935591908616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060019392505050565b60045460ff1681565b60055481565b600160a060020a031660009081526006602052604090205490565b60015433600160a060020a0390811691161461062557600080fd5b600154600054600160a060020a0391821691167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b600054600160a060020a031681565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104265780601f106103fb57610100808354040283529160200191610426565b600160a060020a03331660009081526006602052604081205461073b908363ffffffff610a4b16565b600160a060020a033381166000908152600660205260408082209390935590851681522054610770908363ffffffff610a6016565b600160a060020a0380851660008181526006602052604090819020939093559133909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600192915050565b600160a060020a03338116600081815260076020908152604080832094881680845294909152808220869055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259086905190815260200160405180910390a383600160a060020a0316638f4ffcb1338530866040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108cc5780820151838201526020016108b4565b50505050905090810190601f1680156108f95780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b151561091a57600080fd5b5af1151561092757600080fd5b5060019695505050505050565b600154600160a060020a031681565b6000805433600160a060020a0390811691161461095f57600080fd5b600054600160a060020a038085169163a9059cbb91168460405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b15156109b957600080fd5b5af115156109c657600080fd5b5050506040518051949350505050565b600160a060020a03918216600090815260076020908152604080832093909416825291909152205490565b60005433600160a060020a03908116911614610a1c57600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600082821115610a5a57600080fd5b50900390565b8181018281101561049557600080fd00a165627a7a7230582093cb3ba185eeb26a1a3c00097de4d5c5f2a8bd98cc39245cc71e1c411f5709f30029
このコードをコピーして、以下のコマンドを実行します。少々長くなりますが、2番目の引数に上記のコードを挿入します。そしてその後にgasLimit, gasPrice, コントラクトオーナーアドレスのパラメータを渡します。gasLimit, gasPriceはここではデフォルトの値を使っています。
./qtum-cli-node1.sh createcontract 60606040523415...(略) 2500000 0.0000004 qdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5w
成功すると以下のように結果が返ってきます。
{
"txid": "10f2acc10102b3367568baa560276b9f577a2d46c75fbafc25686fd1e0c2bf87",
"sender": "qdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5w",
"hash160": "dffc6638526876e0fb35a2d802780260449bcae1",
"address": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43"
}
"address":3d3ff25a14fcb4d88593b50cb195e12d8034ac43がコントラクトのアドレスです。(これももちろん実行毎に変わります)
デプロイしたコントラクトを確認する
コントラクトinfo確認
getaccoutinfoコマンドでコントラクトの情報を確認できます。
$ ./qtum-cli-node1.sh getaccountinfo 3d3ff25a14fcb4d88593b50cb195e12d8034ac43
{
"address": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"balance": 0,
"storage": {
"036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0": {
"0000000000000000000000000000000000000000000000000000000000000005": "00000000000000000000000000000000000000000000d3c21bcecceda1000000"
},
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563": {
"0000000000000000000000000000000000000000000000000000000000000000": "000000000000000000000000dffc6638526876e0fb35a2d802780260449bcae1"
},
"405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": {
"0000000000000000000000000000000000000000000000000000000000000002": "464958454400000000000000000000000000000000000000000000000000000a"
},
"8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b": {
"0000000000000000000000000000000000000000000000000000000000000004": "0000000000000000000000000000000000000000000000000000000000000012"
},
"c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": {
"0000000000000000000000000000000000000000000000000000000000000003": "4578616d706c6520466978656420537570706c7920546f6b656e000000000034"
},
"e46e3281cf7ba285da87585af2ebac4355f9771bbca415954ff68fbab2892f0b": {
"3b44a00c1b1e2ea1eb0d57bc2cfecefb96c357301ba0d73e6aa252e5d673f41d": "00000000000000000000000000000000000000000000d3c21bcecceda1000000"
}
},
"code": "6060604052...(略)
storageの部分に、作成したFixedSupplyTokenの基本情報や残高情報が入っています。
バイトコードのため見辛いですが、例えば
"036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0": {
"0000000000000000000000000000000000000000000000000000000000000005": "00000000000000000000000000000000000000000000d3c21bcecceda1000000"
},
これはTotal Supplyの値を示しています。3c21bcecceda1000000は10進数に変換すると1000000000000000000000000です。
また、以下はトークンシンボルを示しています、
"405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": {
"0000000000000000000000000000000000000000000000000000000000000002": "464958454400000000000000000000000000000000000000000000000000000a"
},
464958454400000000000000000000000000000000000000000000000000000aを
デコーダーでデコードすると、"FIXED"の文字列が得られます。(デフォルトのままのシンボル名)
また、以下は残高情報です。
"e46e3281cf7ba285da87585af2ebac4355f9771bbca415954ff68fbab2892f0b": {
"3b44a00c1b1e2ea1eb0d57bc2cfecefb96c357301ba0d73e6aa252e5d673f41d": "00000000000000000000000000000000000000000000d3c21bcecceda1000000"
}
コントラクトオーナーのアドレスに、先ほどのTotal Supplyの全てが付与されています。
コントラクトのfunctionの呼び出し方
コンパイル時に生成されたFixedSupplyToken.signatures
というファイルを開くと以下のようになっていると思います。これは、コントラクトの各functionを呼び出すためのバイトコードのマッピングです。
3eaaf86b: _totalSupply()
79ba5097: acceptOwnership()
dd62ed3e: allowance(address,address)
095ea7b3: approve(address,uint256)
cae9ca51: approveAndCall(address,uint256,bytes)
70a08231: balanceOf(address)
313ce567: decimals()
06fdde03: name()
d4ee1d90: newOwner()
8da5cb5b: owner()
95d89b41: symbol()
18160ddd: totalSupply()
a9059cbb: transfer(address,uint256)
dc39d06d: transferAnyERC20Token(address,uint256)
23b872dd: transferFrom(address,address,uint256)
f2fde38b: transferOwnership(address)
callcontractコマンドを使って以下のようにfunctionを呼び出します。第2引数がコントラクトのアドレス、第3引数がfunctionのバイトコードです。今回はname()のコードを渡してみます。
$ ./qtum-cli-node1.sh callcontract 3d3ff25a14fcb4d88593b50cb195e12d8034ac43 06fdde03
{
"address": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"executionResult": {
"gasUsed": 22731,
"excepted": "None",
"newAddress": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"output": "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4578616d706c6520466978656420537570706c7920546f6b656e000000000000",
"codeDeposit": 0,
"gasRefunded": 0,
"depositSize": 0,
"gasForDeposit": 0
},
"transactionReceipt": {
"stateRoot": "eea0d31c047bda4f2af212fd1d323135116598c225f76bd0c82fdb5a8071b660",
"gasUsed": 22731,
"bloom": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"log": [
]
}
}
以上のように結果が返ってきます。"output"にname()の出力結果が記されています。出力結果もバイトコードなのでそのままでは読めません。そこで、ethabiの出番です。
以下のようにethabiでdecodeコマンドを実行し、上記のoutputの値を渡します。
$ docker run --rm -v ${PWD}:/ethabi cryptominder/ethabi:latest decode params -t string 0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4578616d706c6520466978656420537570706c7920546f6b656e000000000000
以下のように結果が返ります。
string Example Fixed Supply Token
ethabiはこのように結果をデコードしたり、コントラクトに与えるパラメータをエンコードしたりするのに使います。
残高確認
先ほどのfunctionのバイトコードマッピングの中に
70a08231: balanceOf(address)
とありました。
これはトークン残高を確認するfunctionです。
そこで先ほどの例のように70a08231を引数としてcallcontractを実行したいところですが、balanceOfには引数が必要なため、そのままではうまく機能しません。(呼び出し自体はできますが)
そこで、ethabiを使ってfunctionと引数をまとめてエンコードします。
$ docker run --rm -v ${PWD}:/ethabi cryptominder/ethabi:latest encode function /ethabi/FixedSupplyToken.abi balanceOf -p qdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5w -l
上記はbalanceOfのfunctionに、コントラクトオーナーのアドレスを引数に与えてエンコードさせようとしています。しかし、これはエラーを返します。
Cannot parse address
Caused by:
Invalid character 'q' at position 0
アドレスのパースに失敗しているからです。その理由は、ここで指定するアドレスは、コントラクトアドレスのhash160表現である必要があるからです。(ちょっと頭の中がこんがらがりますが)
そこで、qtum-cliのgethexaddressコマンドを使ってコントラクトオーナーアドレスをhash160に変換します。
(実は、遡るとコントラクトのデプロイ時の返り値に、 "hash160":"dffc6638526876e0fb35a2d802780260449bcae1",
というようにhash160値が出力されていました。)
$ ./qtum-cli-node1.sh gethexaddress qdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5w
dffc6638526876e0fb35a2d802780260449bcae1
ここで得られたアドレスを使って再度ethabiでエンコードを実行します。
$ docker run --rm -v ${PWD}:/ethabi cryptominder/ethabi:latest encode function /ethabi/FixedSupplyToken.abi balanceOf -p dffc6638526876e0fb35a2d802780260449bcae1 -l
以下のように結果が得られます。
70a08231000000000000000000000000dffc6638526876e0fb35a2d802780260449bcae1
よく見ると、これはbalanceOfのバイトコードにzero paddingしたhash160が結合されているだけです。
このコードを使ってcallcontractします。
$ ./qtum-cli-node1.sh callcontract 3d3ff25a14fcb4d88593b50cb195e12d8034ac43 70a08231000000000000000000000000dffc6638526876e0fb35a2d802780260449bcae1
{
"address": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"executionResult": {
"gasUsed": 23470,
"excepted": "None",
"newAddress": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"output": "00000000000000000000000000000000000000000000d3c21bcecceda1000000",
"codeDeposit": 0,
"gasRefunded": 0,
"depositSize": 0,
"gasForDeposit": 0
},
"transactionReceipt": {
"stateRoot": "eea0d31c047bda4f2af212fd1d323135116598c225f76bd0c82fdb5a8071b660",
"gasUsed": 23470,
"bloom": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"log": [
]
}
}
またoutputをエンコードしなければなりませんが、これはただの16進数の数値です。
特に送金を実行していなければ、totalSupplyと同じ値が出ているはずです。
トークンを送金する
いよいよトークンを送金します。
送金する前に、送金先アドレスが必要なので作成しておきます。
これはnode1内に作ってもいいですが、せっかくなのでnode2に作成します。
(node2用のqtum-cliスクリプトを作っていなければ、node1からコピーして作って下さい。中身の1を2に変えるだけで良いです)
$ ./qtum-cli-node2.sh getaccountaddress receiver
qPWs97onkHq5mw8UtXBjve9nGevyRaKQrK
hash160に変換しておきます。
$ ./qtum-cli-node2.sh gethexaddress qPWs97onkHq5mw8UtXBjve9nGevyRaKQrK
4156dded07f14fc835996603db354ec80fff09cd
送金にはtranfer functionを使います。バイトコードは
a9059cbb: transfer(address,uint256)
です。(送金先、送る数)
これらを使って、データをエンコードします。30000トークン送ることにしてみます。
$ docker run --rm -v ${PWD}:/ethabi cryptominder/ethabi:latest encode function /ethabi/FixedSupplyToken.abi transfer -p 4156dded07f14fc835996603db354ec80fff09cd -p uint256 30000 -l
本来これで正しいはずなのですが、筆者の環境ではuint256のパースに失敗してしまいました。
そこで、同じethabiでも、functionエンコードではなくparamエンコードでは正しく処理できたので、少し遠回りですが以下のようにしました。
$ docker run --rm -v ${PWD}:/ethabi cryptominder/ethabi:latest encode params -v address 4156dded07f14fc835996603db354ec80fff09cd -v uint256 30000 -l
0000000000000000000000004156dded07f14fc835996603db354ec80fff09cd0000000000000000000000000000000000000000000000000000000000007530
上記のコードが得られるので、transferのバイトコードと単純に結合します。
a9059cbb0000000000000000000000004156dded07f14fc835996603db354ec80fff09cd0000000000000000000000000000000000000000000000000000000000007530
これでコントラクトに送るデータが出来上がりました。
このデータを、今度はsendtocontractコマンドを使ってコントラクトに送ります。
callcontractは、functionの静的な呼び出しです。constantな(状態変化を伴わない)functionはこちらで呼び出します。実行にstakingを必要とせず、すぐに結果が返ります。
sendtocontractは状態変化を伴うfunctionの呼び出しに使います。こちらはstakingされて初めて結果が反映されます。
$ ./qtum-cli-node1.sh sendtocontract 3d3ff25a14fcb4d88593b50cb195e12d8034ac43 a9059cbb0000000000000000000000004156dded07f14fc835996603db354ec80fff09cd0000000000000000000000000000000000000000000000000000000000007530 0 2500000 0.0000004 qdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5w
バイトコードの後ろに、一緒にコントラクトに送るQTUMの量、gasLimit, gasPrice, 送信元アドレスを与えます。
送信元アドレスを明示的にコントラクトオーナーアドレスにする必要があります。(トークン残高を保有しているのがこのアドレスのため)
{
"txid": "9445f126964ad046f8f66945599337cef94f40dd574f27b17b357d3e9a74441b",
"sender": "qdyiCpX23YQrR9nnPnUHuZVYB2XUATHU5w",
"hash160": "dffc6638526876e0fb35a2d802780260449bcae1"
}
getinfoでstakingされた(ブロックが進んでいる)のを確認したら、再度残高を確認してみます。
$ ./qtum-cli-node1.sh callcontract 3d3ff25a14fcb4d88593b50cb195e12d8034ac43 70a08231000000000000000000000000dffc6638526876e0fb35a2d802780260449bcae1
{
"address": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"executionResult": {
"gasUsed": 23470,
"excepted": "None",
"newAddress": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"output": "00000000000000000000000000000000000000000000d3c21bcecceda0ff8ad0",
"codeDeposit": 0,
"gasRefunded": 0,
"depositSize": 0,
"gasForDeposit": 0
},
"transactionReceipt": {
"stateRoot": "5d8680faa690b938aad8de237ecba67d51e7efc38fdfd4ba2898f21a8e4933bf",
"gasUsed": 23470,
"bloom": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"log": [
]
}
}
00000000000000000000000000000000000000000000d3c21bcecceda0ff8ad0
は
999999999999999999970000
なので、送った30000トークンの分減っています。
送られた側の残高も確認します。
(先ほどのコマンドのhash160の部分を差し替えれば良いです)
$ ./qtum-cli-node1.sh callcontract 3d3ff25a14fcb4d88593b50cb195e12d8034ac43 70a082310000000000000000000000004156dded07f14fc835996603db354ec80fff09cd
{
"address": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"executionResult": {
"gasUsed": 23470,
"excepted": "None",
"newAddress": "3d3ff25a14fcb4d88593b50cb195e12d8034ac43",
"output": "0000000000000000000000000000000000000000000000000000000000007530",
"codeDeposit": 0,
"gasRefunded": 0,
"depositSize": 0,
"gasForDeposit": 0
},
"transactionReceipt": {
"stateRoot": "5d8680faa690b938aad8de237ecba67d51e7efc38fdfd4ba2898f21a8e4933bf",
"gasUsed": 23470,
"bloom": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"log": [
]
}
}
0000000000000000000000000000000000000000000000000000000000007530
=30000 トークンとなっています。
これでトークンの送金完了が確認できました。
終わりに
以上の手順を振り返ると、ほぼ全ての手順がEthereumと同じだったかと思います。
実際、Ethereumで使われているツールもそのまま使っています。
同じ知識で扱えますので、ぜひQtumも使ってみて下さい。
本番ネットワークへのデプロイ方法についても後日記述予定です。