在此之前你可以先看。
ABI 编码函数
abi.encode(...) returns (bytes)
:计算参数的ABI
编码。abi.encodePacked(...) returns (bytes)
:计算参数的紧密打包编码- 会把多余的
0
都省掉
- 会把多余的
abi. encodeWithSelector(bytes4 selector, ...) returns (bytes)
: 计算函数选择器和参数的ABI编码abi.encodeWithSignature(string signature, ...) returns (bytes)
: 等价于* abi.encodeWithSelector(bytes4(keccak256(signature), ...)
通过 ABI
编码函数可以在不用调用函数的情况下,获得 ABI
编码值,下面通过一段代码来看看这些方式的使用:
我们将用编码 4
个变量,他们的类型分别是 uint256
, address
, string
, uint256[2]
:
1 | uint x = 10; |
- abi.encode
将给定参数利用 ABI
规则编码。ABI
被设计出来跟智能合约交互,他将每个参数填充为32
字节的数据,并拼接在一起。如果你要和合约交互,你要用的就是abi.encode
。
1 | function encode() public view returns(bytes memory result) { |
编码的结果为 0x000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000007a58c0be72be218b41c608b7fe7c5bb630736c7100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000043078414100000000000000000000000000000000000000000000000000000000
,由于 abi.encode
将每个数据都填充为 32
字节,中间有很多0
。
- abi.encodePacked
将给定参数根据其所需最低空间编码。它类似 abi.encode
,但是会把其中填充的很多 0
省略。比如,只用 1
字节来编码 uint
类型。当你想省空间,并且不与合约交互的时候,可以使用 abi.encodePacked
,例如算一些数据的 hash
时。
1 | function encodePacked() public view returns(bytes memory result) { |
编码的结果为 0x000000000000000000000000000000000000000000000000000000000000000a7a58c0be72be218b41c608b7fe7c5bb630736c713078414100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006
,由于 abi.encodePacked
对编码进行了压缩,长度比 abi.encode
短很多。
- abi.encodeWithSignature
与 abi.encode
功能类似,只不过第一个参数为函数签名,比如 "foo(uint256,address)"
。当调用其他合约的时候可以使用。
1 | function encodeWithSignature() public view returns(bytes memory result) { |
编码的结果为 0xe87082f1000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000007a58c0be72be218b41c608b7fe7c5bb630736c7100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000043078414100000000000000000000000000000000000000000000000000000000
,等同于在 abi.encode
编码结果前加上了 4
字节的函数选择器说明。 说明: 函数选择器就是通过函数名和参数进行签名处理(Keccak–Sha3
)来标识函数,可以用于不同合约之间的函数调用
- abi.encodeWithSelector
与 abi.encodeWithSignature
功能类似,只不过第一个参数为函数选择器,为函数签名 Keccak
哈希的前 4
个字节。
1 | function encodeWithSelector() public view returns(bytes memory result) { |
编码的结果为 0xe87082f1000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000007a58c0be72be218b41c608b7fe7c5bb630736c7100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000043078414100000000000000000000000000000000000000000000000000000000
,与 abi.encodeWithSignature
结果一样。
ABI解码
abi.decode
abi.decode
用于解码 abi.encode
生成的二进制编码,将它还原成原本的参数。
1 | function decode(bytes memory data) public pure returns(uint dx, address daddr, string memory dname, uint[2] memory darray) { |