はじめに
solidityで別コントラクトの関数を呼び出すとき、call()やdelegatecall()が使われると思います。
call()やdelegatecall()は、引数にcalldataが必要です。
calldataの作り方が分からなかったので整理しました。
calldataついて
EVM(Ethereum Virtual Machine)でコードを実行する際にstack、memory、storage、calldata、returndataの5つのデータ領域がある。
calldataはcallまたはdelegatecallで別のコントラクトを呼び出す時に使用するデータ領域で、calldataはbytes型で表される。
calldataは2つのサブパートに分けることができる。
- メソッドID(4バイト)
- 引数(32バイト)※引数が複数ある場合もある
メソッドIDの求め方
メソッドIDは、メソッドシグネチャのkecccak256ハッシュの先頭8文字で表される。
メソッドシグネチャは、メソッドの名前とその引数の型のこと。
例
メソッドの名前 --> transferFrom
引数の型 --> (address, address, uint256)
メソッドシグネチャ --> transferFrom(address, address, uint256)
kecccak256ハッシュの先頭8文字 --> web3.abi.encodeFunctionSignature('transferFrom(address,address,uint256)') --> 0x4a6e9f4e
0x4a6e9f4eがメソッドIDとなる
calldataの引数部分の求め方
引数部分は、各引数を32バイトで表し、連結する。
例
transferFrom(0x0123456789abcdef01223456789abcdef0123456, 0xabcdef0123456789abcdef0123456789abcdef01, 30)
0x0123456789abcdef01223456789abcdef0123456を32バイトにする --> 0x0000000000000000000000000123456789abcdef01223456789abcdef0123456
0xabcdef0123456789abcdef0123456789abcdef01を32バイトにする --> 0x000000000000000000000000abcdef0123456789abcdef0123456789abcdef01
30を32バイトにする --> 0x000000000000000000000000000000000000000000000000000000000000001d
連結する --> 0x0000000000000000000000000123456789abcdef01223456789abcdef0123456000000000000000000000000abcdef0123456789abcdef0123456789abcdef01000000000000000000000000000000000000000000000000000000000000001d
calldataの求め方
メソッドIDと、calldataの引数部分を連結する
例
メソッドID --> 0x4a6e9f4e
calldataの引数部分 --> 0x0000000000000000000000000123456789abcdef01223456789abcdef0123456000000000000000000000000abcdef0123456789abcdef0123456789abcdef01000000000000000000000000000000000000000000000000000000000000001d
calldata --> 0x4a6e9f4e0000000000000000000000000123456789abcdef01223456789abcdef0123456000000000000000000000000abcdef0123456789abcdef0123456789abcdef01000000000000000000000000000000000000000000000000000000000000001d
まとめ
calldataについて理解できました。
Etherscanにも、メソッドIDなどは記載されているので、Transactionの理解も深まりました。