Blockchain
Ethereum
solidity
geth
イーサリアム

【Ethereum】Geth APIにおけるContract functionへの引数の渡し方

More than 1 year has passed since last update.

はじめに

一年前ぐらいに投稿するつもりだったものを供養する。
gethのバージョンは古いが、現在でもここの仕様はおそらく変わっていない。

GethにはJSON-RPC APIがあり、基本的にほとんどの機能がAPI経由で実行することができる。そこでコントラクトをBlockchainにデプロイしようと思った時、コントラクトに値を渡す方法がわからなかったので、忘備録として記録しておく。

以下に詳しくは書いてある。
Ethereum Contract ABI - Github Ethereum wiki

基本的なEthereum APIの使い方は以下
JSON RPC - Github Ethereum wiki

環境

  • geth 1.6.5-stable

やり方

基本的には

0x(Keccak(関数名)の先頭4byte)(渡す 引数パラメータ群)

をdataとしてContract Account宛に送ることでコントラクトの関数実行が可能である。
デプロイ時にはコントラクトをコンパイルしたソースコードの末尾に渡すパラメータ群を記述する。コンストラクタの関数名は入れる必要はないので、パラメーター群をそのまま以下のような形式で書けば良い。

引数パラメータの記述方法

基本的に32byte毎に引数一つとして記述する。例えば以下のような関数を考える。

foo.solidity
function fuga(uint256 hoge,address user,string fuga) {
    _hoge = hoge;
    _user = user;
    _fuga = fuga;
}

この場合、uint256型とaddress型、string型のパラメータを渡したい。

Uint256の場合

先頭はuint256型なので、渡したい値を16進数にし、パラメータ一つの全体が32byteの長さになるように左を0埋めする。

1234
-> 00000000000000000000000000000000000000000000000000000000000004d2

addressの場合

次にaddress型だが、これも左0埋めして32byteにする。

0xb8bac7b269f97350e1df5b57a45302ded9b177d3
-> 000000000000000000000000b8bac7b269f97350e1df5b57a45302ded9b177d3

Stringの場合

stringの場合は、パラメータ全体の末尾にその長さとともに記述し、正規の記述するべき順序の場所の32byteには、先頭から何byte後の部分からその順序にあるべきStringのデータが記述されているかを記述する。つまり、この場合はパラメータが3つあり、その末尾になるので、正規の記述するべき順序の場所の32byteには先頭から96byte後あることを示す。その後、末尾には、先頭32byteにそのString長の数値を左0埋め、その後ASCIIでStringを記述する。

つまり、3番目のパラメータとして、

先頭から96byte後にStringの記述開始
-> 0000000000000000000000000000000000000000000000000000000000000060

そして末尾に

hogehoge
-> 0000000000000000000000000000000000000000000000000000000000000008
686f6765686f6765000000000000000000000000000000000000000000000000

を記述する。

関数名

関数名は引数を含んだものをKeccakするので、

keccak("fuga(uint256 hoge,address user,string fuga)")
-> 5e03f4b96ab58326c1381d7b3218d9318f3b013f7d044e6d039e67f8cae2ed4d

これの先頭4byteを持つ。

送信データ

上の3つをパラメータとして、実際に送信するdataは以下である。わかりやすく32byte毎に改行している。

0x5e03f4b9
00000000000000000000000000000000000000000000000000000000000004d2
000000000000000000000000b8bac7b269f97350e1df5b57a45302ded9b177d3
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000008
686f6765686f6765000000000000000000000000000000000000000000000000

eth_sendTransactionのメソッドを使ってContract Account向けにトランザクションを発行することで実行できる。

 おわりに

他にも配列や、渡す型によって記述方法がそれぞれ違うのだが、全てを網羅するのは諦めた。ドキュメント読め。正直この辺の話は上に挙げたABIのページに書いてあるのだが、非常にわかりづらく英語もわからないのでMistでコンパイルし、トランザクションデータを作らせて、というのを繰り返して諸行無常をした。ちゃんとドキュメントには書いてあるので読もう。