ABI エンコーダーは Solidity の関数シグネチャとパラメータ値の列を受け取り, 取引に貼り付けられる 0x 始まりの calldata 文字列に変換します. 全部ブラウザ内で完結します. バックエンドはありません: ページに js-sha3 が同梱され keccak256 を計算し, 32 バイトのワードにはネイティブ BigInt を使い, 文字列の長さはブラウザ組み込みの UTF-8 エンコーダーが数えます. タブは 2 つ: エンコードはシグネチャと値を受け, セレクタに値ごとに 1 つの 32 バイトワードを続けて出力し, デコードは生の calldata を受け, 復元できる範囲を表示します. シグネチャ入力欄の下にリアルタイムのセレクタプレビューがあり, 結果の下には hex 文字数のカウンターがあるので, コピーする前にサイズを確認できます. まず ABI エンコーダーツールで, 正規形 transfer(address,uint256) を入力してみてください.
4 バイトセレクタの計算方法
セレクタは, シグネチャ文字列をそのまま keccak256 に通したハッシュの先頭 4 バイトです. keccak256 は 256 ビットのハッシュなので, ツールは 64 桁 hex の完全なダイジェストを計算し, 先頭 8 桁の hex 文字, つまり EIP-196 がコントラクトメソッドディスパッチに定義した 4 バイトのプレフィックスを残します. 表記が効いてくるのはここです: transfer(address,uint256) は誰もが知る 0xa9059cbb を出す一方, カンマの後にスペースを入れた同じシグネチャは全く別のダイジェストになり, プレフィックスも変わります. 呼び出しは誤った関数に向かい, あるいは revert します. 入力欄下のプレビューはキーを打つたびにセレクタを再計算するので, タイポは即座に目に見えます. 完全なダイジェストを見たい場合は, Keccak ハッシュツール が同じ入力で 64 桁 hex の完全な出力と, 関数セレクタとしての先頭 4 バイト, アドレス形式の先頭 20 バイトを表示します.
静的値が 32 バイトワードになるまで
静的パラメータはどれも 32 バイトの 1 ワードに書き込まれ, 右寄せで先頭にゼロが埋められます. アドレスは 0x プレフィックスの有無を問わずちょうど 40 桁の hex 文字でなければならず, 64 桁に埋めます. ブール値は true, false, 1, 0 を受け付けます. bytes32 は 1 桁から 64 桁の hex を受け付けます. 整数は 8 ビットの型から uint256 までの非符号系すべてと, それに対応する符号付き 128 ビットと 256 ビットの型を扱い, 各値はエンコード前に範囲チェックされます: int128 は負の 2^127 から 2^127 減 1 の範囲に収まり, int256 は負の 2^255 から 2^255 減 1 の範囲です. 範囲外の入力は拒否され, 黙ってラップされることはありません. 負の整数は補数形式で格納され, つまり値に 2^bits を足した形になります: stake(int256) に -1 を渡すと, セレクタ 0x77b71df0 に f が 64 個続いたワードが続きます. これが 32 バイトの中の -1 の姿です.
動的値のオフセットについて
string, bytes, 配列のパラメータは動的なので, ヘッドスロットにはデータではなくオフセットが入ります. オフセットは最初のヘッドワード, つまり 4 バイトのセレクタに続く 32 バイトのワードから, バイト単位で測ります. セレクタ自体から測るのではありません. 動的引数が 1 つだけのとき, データは最初のテールワードから始まります. ヘッドの起点より 32 バイト遅い位置なので, オフセットワードは単に 32 です. テールには先に長さワード, 次に 32 バイトの倍数にパッドした実際のデータが続きます. 長さは UTF-8 のバイト数で数え, 文字数ではありません. エモジ 1 個は 4 バイトを数えます. greet(string) に hi を渡すと, セレクタ 0xead710c4, オフセットワード 32, 長さワード 2, 先頭が 0x6869 のデータワードになります. 0x6869 は h と i の hex で, 以降はゼロで埋められます.
完全なエンコードをワードごとに追う
transfer(address,uint256) で一通り組み立ててみましょう. 受取人を 0x1234567890123456789012345678901234567890, 金額を 100 にします. 結果は 0xa9059cbb00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000000064 になり, カウンターは 136 桁の hex 文字と表示します. これはちょうどセレクタの 8 桁とアドレスワードの 64 桁と金額ワードの 64 桁の合計です. 金額の 100 は最後のワードに右寄せされ, 100 の hex 表現は 64 です. アドレスの 48 桁の hex は自分のワードの末尾に座り, 前面は 24 桁のゼロです.
デコードタブができることとできないこと
デコードタブは 0x プレフィックスを剥がし, 先頭 8 桁の hex をセレクタとして取り, 以降の 64 桁 hex ずつのチャンクを無符号 256 ビット整数として読み, 十進数で表示します. stake(uint256,uint256) の calldata を与えると, セレクタ 0x7b0472f0 と 2 つのパラメータ, 100 と 2026 を報告します. きれいに往復します. デコーダーは型を見ません. ABI も型リストもないため, transfer の calldata では受取人がアドレスではなく 48 桁の十進数 103929005307130220006098923584552504982110632080 として出てきます. string パラメータもテキストではなく, 生のオフセット, 長さ, データのワードとして戻ります. ワードの裏のバイトを確認したいときは, hex 部分を Hex コンバーターに貼り付ければ, UTF-8 テキストとして読めます.
このツールが何ではないか
ABI エンコーダーは型付きコントラクトエクスプローラーではありません. 生のワードをエンコード・デコードするだけなので, 取引, アドレス, トークンをオンチェーンで調べるなら, ブロックエクスプローラーツールが Etherscan, BscScan, PolygonScan と主要な L2 エクスプローラーへのディープリンクを出します. アドレスチェッカーでもない: 受取人のワードは 32 バイトで, アドレスはそのワード末尾の 40 桁の hex です. ETH アドレスチェックツールはアドレスを EIP-55 の混在大文字小文字に並べ替え, チェックサム不一致をフラグで示します. 手数料計算機でもない: calldata の長さは gas 使用量に影響し, Gas 料金推定ツールは gas 上限とベース・プライオリティ手数料を ETH と USD のコストに換算します. 値の基数コンバーターでもない: 小さい数なら 基数コンバーターで 100 が 64 になるような十進から hex の変換を確認できますが, 32 ビット範囲しか扱いません. バイト単位のテキストツールでもない: 長さワードは UTF-8 のバイト数を数えます. テキストが文字ごとにどのように展開されるかを見たいときは, テキストをバイナリに変換するガイドが ASCII 入力の 8 ビット展開を順に説明します.