ABI エンコーディングとは
ABI エンコーディングは、関数呼び出しをバイト列に変換するための Solidity コントラクト ABI 仕様の規則です。4 バイトのセレクタの後に、引数を 32 バイトワードに詰めて並べます。静的な値はインラインに置かれ、動的な値(bytes、string、動的配列)はそのバイトオフセットを保持するヘッドの後ろに配置されます。ABI エンコーダーはシグネチャと値からこの calldata を組み立て、デコーダーはその逆を行います。
レイアウトの仕組み
f(uint256,uint32[],bytes10,bytes) を (0x123, [0x456, 0x789], "1234567890", "Hello, world!") で呼び出した場合のエンコードは次のとおりです: セレクタ 0x8be65246、続いて 4 ワードのヘッド(uint256、配列へのオフセット 0x80、右パディングされた bytes10、bytes へのオフセット 0xe0)、その後にテール(配列長 2 とその 2 要素、次に bytes 長 13 とパディングされたデータ)。上の「Solidity ドキュメントの f()」をクリックするとワード単位で確認できます。
規則の要点
- すべての値は 32 バイトの倍数を占めます。整数とアドレスは左パディング、
bytesNは右パディングされます。 - 負の整数は 256 ビットの 2 の補数を使います。
- 動的な値は、それを含むタプルまたは配列本体の先頭から測ったバイトオフセットで参照されます。
- 静的な
Tの静的配列T[k]はインラインに置かれ、動的配列T[]は長さから始まります。 - タプルは同じヘッド/テール規則を再帰的に適用します。構造体やネストした配列はこの方法でエンコードされます。
具体例: ERC-20 の transfer
受取先 0x1111111111111111111111111111111111111111 に 25 USDT(生の単位で 25,000,000)を送る transfer(address,uint256) は 68 バイトにエンコードされます: セレクタ a9059cbb、次に 12 バイトのゼロによる左パディングに続く 20 バイトのアドレス、次に 25,000,000 = 0x17d7840 を 32 バイトワードに左パディングしたもの。あらゆるエクスプローラー上のあらゆる ERC-20 transfer がまさにこの形をしているため、デコーダーはセレクタだけで関数名を特定し引数を復元できるのです。
関連ツール
セレクタだけを計算するには関数セレクタツール、トークン量を生の整数に変換するにはトークン小数桁コンバーター、個々のワードを調べるにはhex→10進コンバーターを使ってください。