理解以太坊ABI:应用程序二进制接口
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;
}
}
首先,您需要将合约部署到以太坊网络,这实际上也是一个操作步骤。然后,您会调用 "set" 函数,并将参数设置为 "1"。如下图:

然后我们打开etherscan查看交易详情数据, 可以看到其附加数据如下图:

这个数据就是ABI的编码数据:
0x60fe47b10000000000000000000000000000000000000000000000000000000000000001
ABI 编码分析
我们上面交易的附加数据拷贝出来分析一下,这个数据可以分成两个子部分:
- 函数选择器(4字节)
0x60fe47b1 - 第一个参数(32字节)
00000000000000000000000000000000000000000000000000000000000000001
函数选择器值 实际是对函数签名字符串进行sha3(keccak256)哈希运算之后,取前4个字节,用代码表示就是:
bytes4(sha3(“set(uint256)”)) == 0x60fe47b1
参数部分则是使用对应的16进制数。
现在就容易理解附加数据怎么转化为对应的函数调用。
ABI 编码函数
有两种方法可以获得函数对应的ABI 数据
Solidity ABI 编码函数
Solidity提供了一些与ABI相关的API,用于直接获取ABI编码信息。这些函数包括:
abi.encode(...)
返回(bytes)
:用于计算参数的ABI编码。abi.encodePacked(...)
返回(bytes)
:用于计算参数的紧密打包编码。abi.encodeWithSelector(bytes4 selector, ...)
返回(bytes)
:用于计算函数选择器和参数的ABI编码。abi.encodeWithSignature(string signature, ...)
返回(bytes)
:相当于abi.encodeWithSelector(bytes4(keccak256(signature)), ...)
。
通过使用这些ABI编码函数,您可以获取ABI编码值,而无需实际调用函数。
我们通过一段代码来看看这些方法的使用:
pragma solidity ^0.4.24;
contract testABI {
uint storedData;function set(uint x) public {
storedData = x;
}function abiEncode() public constant returns (bytes) {
abi.encode(1); // 计算1的ABI编码
return abi.encodeWithSignature("set(uint256)", 1); //计算函数set(uint256) 及参数1 的ABI 编码
}
}
大家可以运行运行下abiEncode
函数,它的输出其实就是前面调用的附加数据。
Web3 ABI 编码函数
另一个web3提供相应的API,例如使用web3计算函数选择器的方式如下:
web3.eth.abi.encodeFunctionSignature('myMethod(uint256,string)');