理解以太坊ABI:应用程序二进制接口

理解以太坊ABI:应用程序二进制接口

电报联系方式

ABI 是什么

ABI是Application Binary Interface的缩写,意为应用程序二进制接口。这是以太坊合约调用的界面说明,它定义了如何与以太坊智能合约进行通信。

理解以太坊ABI:应用程序二进制接口

调用合约函数发生了什么

任何对以太坊网络的外部操作都被称为提交了一个Trading。当调用合约函数时,实际上是向合约地址(账户)发送了一笔交易,这笔交易包含额外的数据,这个额外的数据就是ABI编码数据。

理解以太坊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”。如下图:

理解以太坊ABI:应用程序二进制接口

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

理解以太坊ABI:应用程序二进制接口

这个数据就是ABI的编码数据:

0x60fe47b10000000000000000000000000000000000000000000000000000000000000001

ABI 编码分析

我们上面交易的附加数据拷贝出来分析一下,这个数据可以分成两个子部分:

  • 函数选择器(4字节)
    0x60fe47b1
  • 第一个参数(32字节)
    00000000000000000000000000000000000000000000000000000000000000001

函数选择器值 实际是对函数签名字符串进行sha3(keccak256)哈希运算之后,取前4个字节,用代码表示就是:

bytes4(sha3(“set(uint256)”)) == 0x60fe47b1

参数部分则是使用对应的16进制数。

现在就容易理解附加数据怎么转化为对应的函数调用。

ABI 编码函数

有两种方法可以获得函数对应的ABI 数据

Solidity ABI 编码函数

Solidity提供了一些与ABI相关的API,用于直接获取ABI编码信息。这些函数包括:

  1. abi.encode(...) 返回 (bytes):用于计算参数的ABI编码。
  2. abi.encodePacked(...) 返回 (bytes):用于计算参数的紧密打包编码。
  3. abi.encodeWithSelector(bytes4 selector, ...) 返回 (bytes):用于计算函数选择器和参数的ABI编码。
  4. 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)’);

开发联系:DEXDAO

 

© 版权声明

Related posts

No comments

No comments...