---
title: "什么是 Solidity ABI（应用二进制接口）？"
description: "关于 Solidity 应用二进制接口（ABI）你需要了解的一切"
---

# 什么是 Solidity ABI（应用二进制接口）？

Ethereum 开发者使用 Solidity 编程语言为 Ethereum 网络[编写智能合约代码](https://www.alchemy.com/overviews/solidity-smart-contract)。但 Solidity 是如何与 [Ethereum 虚拟机](https://www.alchemy.com/overviews/what-is-the-ethereum-virtual-machine-evm)（EVM）协同工作的？这一切都始于智能合约的编译。

本文将说明：

- 通过介绍智能合约编译的必要性，解释[Solidity ABI](https://www.alchemy.com/overviews/what-is-an-abi-of-a-smart-contract-examples-and-usage)是什么
- ABI 作为 Solidity 编译器的工作方式
- 什么是字节码，以及它在编译过程中的作用
- Solidity ABI 是什么，以及它与 API 的区别
- ABI 的工作原理（附示例）

## **什么是智能合约编译？**

智能合约编译是将 Solidity 智能合约代码转换为与 Ethereum 虚拟机语言兼容的语言的过程。

开发者使用 Solidity 编写智能合约，这是[一种高级编程语言](https://www.alchemy.com/overviews/solidity)，只有人类才能读懂和理解。EVM 无法理解 Solidity。由于虚拟机无法理解 Solidity，编译会将人类可理解的 Solidity 代码转换为机器可读的语言。[Ethereum 生态系统](https://www.alchemy.com/dapps/ecosystem/ethereum)使用 Solidity 编译器来编译其智能合约。

### **什么是 Solidity 编译器？**

[**Solidity 编译器**](https://www.alchemy.com/overviews/solidity-compiler)，也称为 solc，将基于 Solidity 的智能合约编译为 EVM 可理解的字节码和[**应用二进制接口（ABI）**](https://docs.soliditylang.org/en/v0.8.13/abi-spec.html)。字节码和 Solidity 合约 ABI 是与 Ethereum 智能合约交互的两个主要组成部分。

## **什么是字节码？**

字节码是 Ethereum 虚拟机上以二进制格式存储的智能合约信息。字节码不是人类可读的，只能由机器（EVM）读取。换句话说，Solidity 会被编译并转换为机器可读的字节码，以便 EVM 执行必要的功能。

字节码包含一系列机器可理解的指令，称为操作码（opcode），每个操作码长一字节（8 位）。因此，字节码是由一字节操作码组合而成的。

字节码分为两种类型：

1. 创建字节码（creation bytecode）
1. 运行时字节码（runtime bytecode）

### **什么是创建字节码？**

**智能合约编译会生成创建字节码，其中包含智能合约的构造函数逻辑和构造函数参数。** 创建字节码负责生成运行时字节码。

在任何[集成开发环境（IDE）平台](https://www.alchemy.com/overviews/solidity-ide)上点击某个智能合约的"编译详情"时，你看到的就是创建字节码。创建字节码只在部署时执行一次。

要检索链上的创建字节码，请使用：

要通过 JSON RPC 调用在链下检索创建字节码，请使用以下方法：[`getTransactionByHash`](https://www.alchemy.com/docs/chains/ethereum/ethereum-api-endpoints/eth-get-transaction-by-hash)。

### **什么是运行时字节码？**

运行时字节码是已编译的智能合约数据，作为永久可执行代码存储在链上。与创建字节码不同，运行时字节码不包含构造函数逻辑和构造函数参数。

要检索链上的运行时字节码，请使用：

要通过 JSON RPC 调用在链下检索运行时字节码，请使用以下方法：[`getCode`](https://www.alchemy.com/docs/chains/ethereum/ethereum-api-endpoints/eth-get-code)

### **如何与字节码交互**

智能合约数据在 EVM 上以机器可读的字节码形式存储，而在外部应用中则以 Javascript 存储，其他智能合约则以人类可读的 Solidity 语言存储，因为它们无法与字节码通信。这正是智能合约编译的第二个组成部分——应用二进制接口（ABI）——发挥作用的地方，它使这种交互成为可能。

## **Solidity 中的应用二进制接口（ABI）是什么？**

[**应用二进制接口（ABI）**](https://www.alchemy.com/overviews/what-is-an-abi-of-a-smart-contract-examples-and-usage)是一种解释器，用于促进与 EVM 字节码的通信。Solidity ABI 是智能合约上用于执行特定功能的方法的人类可读列表。你可以将 ABI 与 [ethers.js](https://www.alchemy.com/dapps/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 二进制文件](https://www.alchemy.com/overviews/solidity-binaries)，这样存储数据在区块链上更具成本效益。

那么 ABI 是如何访问 Solidity 二进制文件的呢？它通过一个称为 ABI 编码的过程来实现。

### **什么是 Solidity ABI 编码？**

**ABI 使用 EVM 字节码可以理解的函数签名和变量声明来调用智能合约。** 这称为 ABI 编码，即 ABI 将机器可读字节码需要处理的信息进行编码。在大多数情况下，ABI 编码是自动完成的，由智能合约编译器完成。

### **什么是 ABI 解码？**

**当 EVM 字节码执行一条指令并返回结果时，结果是原始的十六进制格式，而 ABI 会将这种非人类可读的十六进制格式解码为人类可读的语言。** 这称为 ABI 解码。

你从 ABI 获取 Solidity 代码，本质上 ABI 充当了在机器码与外部之间进行数据编码/解码的接口。

### **Solidity 代码如何映射到 EVM 操作码？**

EVM 字节码由若干[操作码](https://ethereum.org/en/developers/docs/evm/opcodes/)组成。**当 ABI 编码调用一个函数时，它会指向某个特定的操作码。** 处理完交易后，该操作码返回一个结果，ABI 会为用户解码这个结果。

## **Solidity 中的 ABI 是如何工作的？**

**ABI 指定要调用哪个函数（编码），并执行该函数以向用户返回数据（解码）。** 一个智能合约包含若干个作为字节码部署在 EVM 上的函数，每个智能合约都有自己的 ABI，需要用它来获取执行结果。

由于智能合约以二进制格式存储，ABI 定义了与该二进制合约交互所需的结构和方法。编译后，智能合约会生成一个以 Solidity JSON ABI 格式表示的 ABI。

某些 IDE（如 Remix）会自动生成合约 ABI。不过，你也可以使用 [Solidity Compiler NPM package](https://www.npmjs.com/package/solc) 手动创建 ABI。

Solidity JSON ABI 会生成以下组成部分：

- **Type** - 定义[函数](https://www.alchemy.com/overviews/solidity-functions)的性质（receive、fallback、constructor）
- **Name** - 定义函数的名称
- **Inputs** - 由 name、type、components 组成的对象数组
- **Outputs** - 与 inputs 类似的对象数组
- **stateMutability** - 定义函数的可变性（pure、view、[non-payable 或 payable](https://www.alchemy.com/docs/solidity-payable-functions)）

## **交易是如何与 ABI 配合工作的？**

一笔交易与 Solidity ABI 文件配合工作分为 3 个步骤：

1. 智能合约的 ABI 被提供给前端库，如 EtherJS。
1. 前端库将方法调用和参数转换为 _calldata_，作为交易的一部分提供给 Ethereum 节点。
1. 交易验证通过后，会生成一个包含详细日志和所用 gas（交易费用）的收据树（receipts trie）。

### 什么是收据树？

**一笔 Ethereum 交易会生成一个称为"收据树"的收据，记录成功交易的结果。** 收据树由四类信息组成：

1. 交易状态
1. 累计使用的 gas
1. 执行过程中创建的日志集合
1. 由日志组成的布隆过滤器（Bloom filter）

为了更好地理解交易的工作原理，请看下面的例子。

## ERC-20 代币转账示例

例如，你想将一个 [ERC-20 代币](https://www.alchemy.com/overviews/erc20-solidity)从一个钱包转移到另一个钱包。以下代码指示 ABI 向基于 EVM 的字节码发送一条消息。

ABI 编码确保字节码识别该函数并执行该交易。生成结果后，ABI 解码将结果转换为人类可读的格式。用户会收到一张收据，表明 ERC-20 代币已从一个地址转移到另一个地址。

## **进一步了解 Solidity 的 ABI**

在[学习 Solidity](https://www.alchemy.com/overviews/learn-solidity) 的过程中，你会明白 ABI 是 Ethereum 智能合约的基石。ABI 促进了区块链生态系统中的交易。尽管 ABI 在智能合约技术中非常重要，但在开发者教程中却常常被忽视。虽然超出了本文的范围，但了解什么是 [Solidity interface](https://www.alchemy.com/overviews/solidity-interface) 将有助于你进一步理解合约之间是如何交互的。

深入理解 ABI 是开发出健壮的智能合约和[应用](https://www.alchemy.com/dapps/top/defi-dapps)、并[成为 Solidity 开发者](https://www.alchemy.com/overviews/how-to-become-a-solidity-developer)的重要基础。
