ABI 是什么
ABI 全称是 Application Binary Interface,翻译过来就是:应用程序二进制接口,简单来说就是以太坊的调用合约时的接口。
调用合约函数发生了什么
从外部施加给以太坊的行为都称之为向以太坊网络提交了一个交易, 调用合约函数其实是向合约地址(账户)提交了一个交易,这个交易有一个附加数据,这个附加的数据就是ABI的编码数据。
演示调用函数
以下面以个最简单的合约为例,我们看看用参数 1 调用set(uint x)
,这个交易附带的数据是什么。
pragma solidity ^0.4.0;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public constant returns (uint) {
return storedData;
}
}
然后我们打开etherscan查看交易详情数据, 可以看到其附加的ABI编码数据:
0x60fe47b10000000000000000000000000000000000000000000000000000000000000001
ABI 编码分析
我把上面交易的附加数据拷贝出来分析一下,这个数据可以分成两个子部分:
- 函数选择器(4字节)
0x60fe47b1
- 第一个参数(32字节)
函数选择器值实际是对函数签名字符串进行`sha3(keccak256)`哈希运算之后,取前4个字节,用代码表示就是:
```js
bytes4(sha3("set(uint256)")) == 0x60fe47b1
参数部分则是使用对应的16进制数。
ABI 编码函数
那么怎么获得函数对应的ABI 数据呢, 有两种方法:
Solidity ABI 编码函数
一个是 solidity 提供了ABI的相关API, 用来直接得到ABI编码信息,这些函数有:
- abi.encode(...) returns (bytes):计算参数的ABI编码。
- abi.encodePacked(...) returns (bytes):计算参数的紧密打包编码
- abi. encodeWithSelector(bytes4 selector, ...) returns (bytes): 计算函数选择器和参数的ABI编码
- abi.encodeWithSignature(string signature, ...) returns (bytes): 等价于* abi.encodeWithSelector(bytes4(keccak256(signature), ...)