什么是 Solidity ABI(应用二进制接口)?
作者 Mohammad
Ethereum 开发者使用 Solidity 编程语言为 Ethereum 网络编写智能合约代码。但 Solidity 是如何与 Ethereum 虚拟机(EVM)协同工作的?这一切都始于智能合约的编译。
本文将说明:
- 通过介绍智能合约编译的必要性,解释Solidity ABI是什么
- ABI 作为 Solidity 编译器的工作方式
- 什么是字节码,以及它在编译过程中的作用
- Solidity ABI 是什么,以及它与 API 的区别
- ABI 的工作原理(附示例)
什么是智能合约编译?
智能合约编译是将 Solidity 智能合约代码转换为与 Ethereum 虚拟机语言兼容的语言的过程。
开发者使用 Solidity 编写智能合约,这是一种高级编程语言,只有人类才能读懂和理解。EVM 无法理解 Solidity。由于虚拟机无法理解 Solidity,编译会将人类可理解的 Solidity 代码转换为机器可读的语言。Ethereum 生态系统使用 Solidity 编译器来编译其智能合约。
什么是 Solidity 编译器?
Solidity 编译器,也称为 solc,将基于 Solidity 的智能合约编译为 EVM 可理解的字节码和应用二进制接口(ABI)。字节码和 Solidity 合约 ABI 是与 Ethereum 智能合约交互的两个主要组成部分。
什么是字节码?
字节码是 Ethereum 虚拟机上以二进制格式存储的智能合约信息。字节码不是人类可读的,只能由机器(EVM)读取。换句话说,Solidity 会被编译并转换为机器可读的字节码,以便 EVM 执行必要的功能。
字节码包含一系列机器可理解的指令,称为操作码(opcode),每个操作码长一字节(8 位)。因此,字节码是由一字节操作码组合而成的。
字节码分为两种类型:
- 创建字节码(creation bytecode)
- 运行时字节码(runtime bytecode)
什么是创建字节码?
智能合约编译会生成创建字节码,其中包含智能合约的构造函数逻辑和构造函数参数。 创建字节码负责生成运行时字节码。
在任何集成开发环境(IDE)平台上点击某个智能合约的"编译详情"时,你看到的就是创建字节码。创建字节码只在部署时执行一次。
要检索链上的创建字节码,请使用:
要通过 JSON RPC 调用在链下检索创建字节码,请使用以下方法:getTransactionByHash。
什么是运行时字节码?
运行时字节码是已编译的智能合约数据,作为永久可执行代码存储在链上。与创建字节码不同,运行时字节码不包含构造函数逻辑和构造函数参数。
要检索链上的运行时字节码,请使用:
要通过 JSON RPC 调用在链下检索运行时字节码,请使用以下方法:getCode
如何与字节码交互
智能合约数据在 EVM 上以机器可读的字节码形式存储,而在外部应用中则以 Javascript 存储,其他智能合约则以人类可读的 Solidity 语言存储,因为它们无法与字节码通信。这正是智能合约编译的第二个组成部分——应用二进制接口(ABI)——发挥作用的地方,它使这种交互成为可能。
Solidity 中的应用二进制接口(ABI)是什么?
应用二进制接口(ABI)是一种解释器,用于促进与 EVM 字节码的通信。Solidity ABI 是智能合约上用于执行特定功能的方法的人类可读列表。你可以将 ABI 与 ethers.js 这样的库结合使用,以与智能合约交互。
Solidity 中的 ABI 与 API(应用程序接口)有相似之处,但也有区别。
Solidity ABI 与 API 有什么区别?
在 web2 中,API 促进 Web 应用程序与中心化服务器之间的交互,而 Solidity ABI 则向应用程序和其他合约提供智能合约数据。当应用程序使用 API 向服务器请求数据时,API 会提供数据;而 ABI 则以称为 Solidity 二进制文件的二进制字节码格式访问智能合约数据。
在下一节中,我们将解释什么是 Solidity 二进制文件。
什么是 Solidity 二进制文件?
Solidity 二进制文件是 Ethereum 生态系统中智能合约的一种独特数据存储基础设施。
开发者无法将人类可读的 Solidity 代码部署到 Ethereum 区块链上。相反,Solidity 智能合约数据以二进制格式(即一长串十六进制字符)作为原始字节码存储。这被称为 Solidity 二进制文件,这样存储数据在区块链上更具成本效益。
那么 ABI 是如何访问 Solidity 二进制文件的呢?它通过一个称为 ABI 编码的过程来实现。
什么是 Solidity ABI 编码?
ABI 使用 EVM 字节码可以理解的函数签名和变量声明来调用智能合约。 这称为 ABI 编码,即 ABI 将机器可读字节码需要处理的信息进行编码。在大多数情况下,ABI 编码是自动完成的,由智能合约编译器完成。
什么是 ABI 解码?
当 EVM 字节码执行一条指令并返回结果时,结果是原始的十六进制格式,而 ABI 会将这种非人类可读的十六进制格式解码为人类可读的语言。 这称为 ABI 解码。
你从 ABI 获取 Solidity 代码,本质上 ABI 充当了在机器码与外部之间进行数据编码/解码的接口。
Solidity 代码如何映射到 EVM 操作码?
EVM 字节码由若干操作码组成。当 ABI 编码调用一个函数时,它会指向某个特定的操作码。 处理完交易后,该操作码返回一个结果,ABI 会为用户解码这个结果。
Solidity 中的 ABI 是如何工作的?
ABI 指定要调用哪个函数(编码),并执行该函数以向用户返回数据(解码)。 一个智能合约包含若干个作为字节码部署在 EVM 上的函数,每个智能合约都有自己的 ABI,需要用它来获取执行结果。
由于智能合约以二进制格式存储,ABI 定义了与该二进制合约交互所需的结构和方法。编译后,智能合约会生成一个以 Solidity JSON ABI 格式表示的 ABI。
某些 IDE(如 Remix)会自动生成合约 ABI。不过,你也可以使用 Solidity Compiler NPM package 手动创建 ABI。
Solidity JSON ABI 会生成以下组成部分:
- Type - 定义函数的性质(receive、fallback、constructor)
- Name - 定义函数的名称
- Inputs - 由 name、type、components 组成的对象数组
- Outputs - 与 inputs 类似的对象数组
- stateMutability - 定义函数的可变性(pure、view、non-payable 或 payable)
交易是如何与 ABI 配合工作的?
一笔交易与 Solidity ABI 文件配合工作分为 3 个步骤:
- 智能合约的 ABI 被提供给前端库,如 EtherJS。
- 前端库将方法调用和参数转换为 calldata,作为交易的一部分提供给 Ethereum 节点。
- 交易验证通过后,会生成一个包含详细日志和所用 gas(交易费用)的收据树(receipts trie)。
什么是收据树?
一笔 Ethereum 交易会生成一个称为"收据树"的收据,记录成功交易的结果。 收据树由四类信息组成:
- 交易状态
- 累计使用的 gas
- 执行过程中创建的日志集合
- 由日志组成的布隆过滤器(Bloom filter)
为了更好地理解交易的工作原理,请看下面的例子。
ERC-20 代币转账示例
例如,你想将一个 ERC-20 代币从一个钱包转移到另一个钱包。以下代码指示 ABI 向基于 EVM 的字节码发送一条消息。
ABI 编码确保字节码识别该函数并执行该交易。生成结果后,ABI 解码将结果转换为人类可读的格式。用户会收到一张收据,表明 ERC-20 代币已从一个地址转移到另一个地址。
进一步了解 Solidity 的 ABI
在学习 Solidity 的过程中,你会明白 ABI 是 Ethereum 智能合约的基石。ABI 促进了区块链生态系统中的交易。尽管 ABI 在智能合约技术中非常重要,但在开发者教程中却常常被忽视。虽然超出了本文的范围,但了解什么是 Solidity interface 将有助于你进一步理解合约之间是如何交互的。
深入理解 ABI 是开发出健壮的智能合约和应用、并成为 Solidity 开发者的重要基础。
相关概览

构建区块链应用
Alchemy 将最强大的 Web3 开发者产品和工具与资源、社区及专业支持结合在一起。


