ABI(ApplicationBinaryInterface,应用二进制接口)是与以太坊智能合约交互的标准。说人话就是:给智能合约阅读的编码标准。为了应对智能合约中不同的情况,就有了不同的编码方法(合约要求的输入不一,还有省空间的问题)。关于编码方法如下:abi.encodeabi.e
ABI
(Application Binary Interface,应用二进制接口)是与以太坊智能合约交互的标准。说人话就是:给智能合约阅读的编码标准。
为了应对智能合约中不同的情况,就有了不同的编码方法(合约要求的输入不一,还有省空间的问题)。关于编码方法如下:
abi.encode
abi.encodePacked
abi.encodeWithSignature
abi.encodeWithSelector
关于解码方法如下:
abi.decode
abi.encode
会根据给定的 ABI 规则进行编码(将每个参数填充为32字节的数据,并拼接在一起)。当我们与合约进行交互时,使用的就是abi.encode
。使用方法如下:
function encode() public view returns(bytes memory result) {
result = abi.encode(x, addr, name, array);
}
// 其中的四个参数随用户决定
返回值为bytes
类型。
由abi.encode
的编码规则可以看出,其中很容易浪费的空间。当我们想节省空间,并不与合约进行交互时,就可以使用abi.encodePacked
。abi.encodePacked
会使用参数所需的最低空间编码(如uint8
参数就不会占用32字节那么大的空间了),使用方法同abi.encode
。
返回值为bytes
类型。
abi.encodeWithSignature
的规则和abi.encode
类似(每个参数都时32字节),但区别在于Signature
(函数签名)这个上。abi.encodeWithSignature
的第一个参数要求是函数签名,调用其他合约时可以使用,例子如下:
function encodeWithSignature() public view returns(bytes memory result) {
result = abi.encodeWithSignature("foo(uint256,address,string,uint256[2])", x, addr, name, array);
}
返回值为bytes
类型。返回结果相当于原本abi.encode
例子中的结果加上函数选择器32字节化结果。
与abi.encodeWithSignature
功能类似,只不过第一个参数为函数选择器,为函数签名Keccak
哈希结果的前4个字节。
function encodeWithSelector() public view returns(bytes memory result) {
result = abi.encodeWithSelector(bytes4(keccak256("foo(uint256,address,string,uint256[2])")), x, addr, name, array);
}
返回值为bytes
类型。返回的结果与abi.encodeWithSignature
中一致(对于相同的函数)。
abi.decode
用于解码abi.encode
生成的二进制编码,将它还原成原本的参数。使用方法如下:
function decode(bytes memory data) public pure returns(uint dx, address daddr, string memory dname, uint[2] memory darray) {
(dx, daddr, dname, darray) = abi.decode(data, (uint, address, string, uint[2]));
}
最基本的ABI
编码方法就是abi.decode
,但为了节省空间(在不与合约交互时)设计了abi.encodePacked
。
为了快捷计算所需要的合约交互编码结果,设计了abi.encodeWithSignature
和abi.encodeWithSignature
,其中前者填入的是函数签名字符串参数,后者使用的是函数选择器,但输出结果一致。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!