以太坊智能合约函数参数ABI编码,动态类型string编码,函数参数的ABI编码,
含c++代码
官⽅⽂档讲得不全也不是很清楚,特别是动态类型string。这⾥补充。
⽐如下图使⽤
solidity
这⾥侧重于solidity智能合约的构造⽅法的ABI编码构造。
普通⽅法的编码官⽹说得很清楚了。
构造函数的ABI编码由两部分构成,⼀是编译后的智能合约代码,⽽是构造函数的参数。
1. 使⽤remix编译智能合约,复制编译后的⼗六进制码。
2. 我们智能合约的构造⽅法是:
constructor (uint256 _deadline, uint32 _reward, string memory _code) public{
现在的问题是,如果我们使⽤后台提交⼀个智能合约,需要提交该智能合约的构造函数的参数的值,但是,上⾯第⼀步的所复制的编码中不包含参数的值,因此,需要我们⾃⼰构造构造函数的值的ABI编码。
换⼀种说法描述上⾯的问题,如果使⽤remix部署我们上⾯的智能合约的话,因为只有⼀个构造函数,且是带参数的,因此deploy前需要填写这些参数的值,如下图。现在remix⾃动帮我们对参数进⾏ABI编码了,并将它追加在第⼀步所复制的数据的后⾯。如果我们⾃⼰在后台构造和部署智能合约,如何进⾏ABI编码构造⽅法的参数?
3. 根据constructor (uint256 _deadline, uint32 _reward, string memory _code) ,假如取值(3, 2, “helloworld”),第⼀个参数是
uint256,0x0000000000000000000000000000000000000000000000000000000000000003,使⽤0填充,uint32同理,追加到前⾯的数中。第三个是string,动态类型,因此先填下⾯这个固定的数,以60为结尾,长度为
64。0000000000000000000000000000000000000000000000000000000000000060,变成:
为什么要追加这个"0000000…0060"呢?看下⽂。
4. 接下来追加string的长度(使⽤16进制表⽰)⽤0填充前⾯部分;再追加字符串的16进制表⽰,⽤0填充后⾯部分。
5. 因为0填充是以64长度为单位的,因此,当字符串的16进制编码长度操作了64长度,后⾯统⼀使⽤0填充。因此有
官⽹没有说清楚的是,为什么要追加上⾯的值0000000000000000000000000000000000000000000000000000000000000060。原因是,string 类型是动态类型,长度不是固定的,因此,需要将string数据从哪⾥开始的这个信息编码进去,这个信息我们称为offset。现在的
offset=60(16进制)=96(10进制),我们的字符串的长度表⽰是使⽤⼗进制的,⼜因为我们需要编码的参数为(uint256 _deadline, uint32 _reward, string memory _code),前⾯两个参数+offset,相当于3个数,每⼀个数的长度是⼀样的,因此 ** 每⼀个数的长度为96/3 = 32。** 这就是我们的结论。
根据上⾯这个结论,如果所编码的参数变为四个(uint256 _deadline, uint32 _reward, uint32 other, string
memory _code),那么string前⾯的offset变为32*4 = 128(10进制) = 80 (16进制)。使⽤线上⼯具验证结果⼀致:
在solidity中的bytes类型也是动态类型,编码⽅式跟string类似。
谢谢
c++代码