例1:
函数定义:
function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; }
实际调用:
baz(69, true)
编码为:
方法ID——0xcdcd77c0,方法 baz(uint32 x, bool y)
的签名的ASCII格式的Kecak hash 的前4个字节:
0xcdcd77c0
第一个参数——69的hex形式uint32值,用0补位成32字节
0x0000000000000000000000000000000000000000000000000000000000000045
第二个参数——bool类型,0补位成32字节:
0x0000000000000000000000000000000000000000000000000000000000000001
合在一起则为:
0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001
例2:function bar(bytes3[2] memory) public pure {}
实际调用:bar(["abc", "def"])
编码:
方法ID——0xfce353f6,方法 bar(bytes3[2])的签名的ASCII格式的Kecak hash 的前4个字节:
0xfce353f6
参数1的第一部分——”abc”,长度为3的字符串,左对齐【bytes3
值"abc"
(左对齐)】:
0x6162630000000000000000000000000000000000000000000000000000000000
参数1的第二部分——”def”,长度为3的字符串,左对齐【bytes3
值"def"
(左对齐)】
0x6465660000000000000000000000000000000000000000000000000000000000
合在一起则为:
0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000
例3: function sam(bytes memory, bool, uint[] memory) public pure {}
实际调用:sam("dave",true,[1,2,3])
编码:
方法ID——0xa5643bf2,方法sam(bytes,bool,uint256[])的签名的ASCII格式的Kecak hash 的前4个字节:
0xa5643bf2
参数1(动态类型)的数据部分的位置——以字节为单位,从参数块的起始位置算起,本例则为0x60:
0x0000000000000000000000000000000000000000000000000000000000000060
参数2——true,bool类型
0x0000000000000000000000000000000000000000000000000000000000000001
参数3(动态类型)的数据部分的位置——以字节为单位,本例则为0xa0:
0x00000000000000000000000000000000000000000000000000000000000000a0
参数1(动态类型)的数据部分——以字节为单位,从参数块的起始位置算起,本例则为0x60:
合在一起则为:
0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000
动态类型的使用
函数签名的来源:
例1:f(uint256,uint32[],bytes10,bytes)
分析:f(定长类型,动态类型,定长类型,动态类型)
调用:f(0x123, [0x456, 0x789], "1234567890", "Hello, world!")
→方法签名:sha3(f(uint256,uint32[],bytes10,bytes))=0x8be65246
→ 参数1,定长类型0x123:
0x0000000000000000000000000000000000000000000000000000000000000123
(0x123
填充到 32 个字节)
→ 参数2,动态类型,偏移量:
0x0000000000000000000000000000000000000000000000000000000000000080
(到第二个参数数据部分开始的偏移量,4*32(tohex(128)→80) 字节,正好是头部的大小
→参数3,定长类型 “1234567890”:(ASCII)
0x3132333435363738393000000000000000000000000000000000000000000000
→ 参数4,动态类型,
动态参数n的偏移量=
(动态参数1的数据起始位置的偏移量+动态参数1的数据大小)
+(动态参数2的数据起始位置的偏移量+动态参数2的数据大小)
+…
+(动态参数n-1的数据起始位置的偏移量+动态参数n-1的数据大小)
0x00000000000000000000000000000000000000000000000000000000000000e0
=432 + 332
→ 参数2(动态)的数据部分[0x456,0x789]:
数组元素的数量,2:
0x0000000000000000000000000000000000000000000000000000000000000002
第一个元素:
0x0000000000000000000000000000000000000000000000000000000000000456
第二个元素:
0x0000000000000000000000000000000000000000000000000000000000000789
→ 参数4(动态)的数据部分"Hello, world!”:
字符串的元素(byte-s)数,13:
0x000000000000000000000000000000000000000000000000000000000000000d
参数内容本身(补足32位):(ASCII码)
0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000
合一起为
0x8be65246 0000000000000000000000000000000000000000000000000000000000000123 0000000000000000000000000000000000000000000000000000000000000080 3132333435363738393000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000e0 0000000000000000000000000000000000000000000000000000000000000002 0000000000000000000000000000000000000000000000000000000000000456 0000000000000000000000000000000000000000000000000000000000000789 000000000000000000000000000000000000000000000000000000000000000d 48656c6c6f2c20776f726c642100000000000000000000000000000000000000