【原创】合约编码方式解析

例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

动态类型的使用

函数签名的来源:

%E5%90%88%E7%BA%A6%E7%BC%96%E7%A0%81%E6%96%B9%E5%BC%8F%E8%A7%A3%E6%9E%90%2033e329f6f21f46dca68c62117d9b5d32/Untitled.png

例1:f(uint256,uint32[],bytes10,bytes)

分析:f(定长类型,动态类型,定长类型,动态类型)

调用:f(0x123, [0x456, 0x789], "1234567890", "Hello, world!")

→方法签名:sha3(f(uint256,uint32[],bytes10,bytes))=0x8be65246

→ 参数1,定长类型0x123:

  • 0x00000000000000000000000000000000000000000000000000000000000001230x123填充到 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

posted on 2022-10-26 15:02  fRe_Bourne  阅读(117)  评论(0)    收藏  举报

导航