ABI 编码

  • nilliol
  • 更新于 2024-05-27 12:55
  • 阅读 777

ABI(ApplicationBinaryInterface,应用二进制接口)是与以太坊智能合约交互的标准。说人话就是:给智能合约阅读的编码标准。为了应对智能合约中不同的情况,就有了不同的编码方法(合约要求的输入不一,还有省空间的问题)。关于编码方法如下:abi.encodeabi.e

ABI (Application Binary Interface,应用二进制接口)是与以太坊智能合约交互的标准。说人话就是:给智能合约阅读的编码标准。

为了应对智能合约中不同的情况,就有了不同的编码方法(合约要求的输入不一,还有省空间的问题)。关于编码方法如下:

  • abi.encode
  • abi.encodePacked
  • abi.encodeWithSignature
  • abi.encodeWithSelector

关于解码方法如下:

  • abi.decode

1 abi.encode

abi.encode会根据给定的 ABI 规则进行编码(将每个参数填充为32字节的数据,并拼接在一起)。当我们与合约进行交互时,使用的就是abi.encode。使用方法如下:

    function encode() public view returns(bytes memory result) {
        result = abi.encode(x, addr, name, array);
    }
// 其中的四个参数随用户决定

返回值为bytes类型。

2 abi.encodePacked

abi.encode的编码规则可以看出,其中很容易浪费的空间。当我们想节省空间,并不与合约进行交互时,就可以使用abi.encodePackedabi.encodePacked会使用参数所需的最低空间编码(如uint8参数就不会占用32字节那么大的空间了),使用方法同abi.encode

返回值为bytes类型。

3 abi.encodeWithSignature

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字节化结果。

4 abi.encodeWithSelector

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中一致(对于相同的函数)。

5 abi.decode

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]));
    }

6 总结

最基本的ABI编码方法就是abi.decode,但为了节省空间(在不与合约交互时)设计了abi.encodePacked

为了快捷计算所需要的合约交互编码结果,设计了abi.encodeWithSignatureabi.encodeWithSignature,其中前者填入的是函数签名字符串参数,后者使用的是函数选择器,但输出结果一致。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
nilliol
nilliol
0xbe3e...29A9
web3 的学习者,寻找实习机会中。 博客地址:https://llwh2333.github.io