Posted at

【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でコンパイルし、トランザクションデータを作らせて、というのを繰り返して諸行無常をした。ちゃんとドキュメントには書いてあるので読もう。