Skip to content

Latest commit

 

History

History
82 lines (54 loc) · 2.79 KB

File metadata and controls

82 lines (54 loc) · 2.79 KB
title tags
08. calldata/returndata的ABI编码
solidity
abi

WTF Solidity内部标准: 08. calldata/returndata的ABI编码

《WTF Solidity内部标准》教程将介绍Solidity智能合约中的存储布局,内存布局,以及ABI编码规则,帮助大家理解Solidity的内部规则。

推特:@0xAA_Science

社区:Discord微信群官网 wtf.academy

所有代码和教程开源在github: github.com/AmazingAng/WTF-Solidity-Internals


这一讲,我们将介绍Solidity的函数调用calldata和返回值returndata的ABI编码规则。

calldata

当我们调用函数时,我们需要为要调用的函数名以及参数进行ABI编码。对于参数a_1, ..., a_n的函数f的调用会被编码为:

function_selector(f) e((a_1, ..., a_n))

其中function_selector(f)为函数的选择器(函数签名的Keccak-256哈希值的前4字节),(a_1, ..., a_n)为参数组成的元组,e(x)为变量x的ABI编码。

举个简单的例子:

function testCalldata(uint256 x, bool y) public pure{
}

当我们调用上面的testCalldata()函数,参数为99(也就是0x63)和true时,会如何编码呢?

首先,我们需要计算这个函数的函数选择器,为0xb3b1391c。如果你不了解函数选择器,可以阅读WTF Solidity教程第29讲

接下来我们需要编码(x, y)。由于xy都是静态类型,这个元组也是静态类型,直接编码就可以。

因此,calldata的编码为:

0xb3b1391c
0000000000000000000000000000000000000000000000000000000000000063
0000000000000000000000000000000000000000000000000000000000000001

returndata

当函数返回时,我们需要对返回值进行编码。返回值a_1, ..., a_n会被被编码为:

e((a_1, ..., a_n))

举个简单的例子:

function testReturndata() public pure returns(uint x, bool y){
    x = 99;
    y = true;
}

当我们调用上面的testReturndata()函数,返回值是如何编码的?

其实很简单,返回值的编码就是e((x, y)),也就是上一节calldata编码去掉函数选择器的部分:

0x
0000000000000000000000000000000000000000000000000000000000000063
0000000000000000000000000000000000000000000000000000000000000001

总结

这一讲,我们介绍了Solidity合约的ABI编码公式,有了它,再复杂的编码也不怕。它的核心思想是使用递归的方法把复杂类型的编码转换成简单类型的编码。