---
title: "什麼是智能合約的 ABI？"
description: "開發者範例與使用方式"
---

# 什麼是智能合約的 ABI？

智能合約的 Application Binary Interface（ABI）讓合約具備與外部應用程式及其他智能合約溝通、互動的能力。從外部來源接收資料，對於完成應用程式與使用者的目標來說相當重要。

在傳統的網頁開發中，資料的溝通是透過 API（Application Program Interface）在應用程式與伺服器之間進行。伺服器扮演集中式的資訊來源，依據請求將資料提供給應用程式。

在區塊鏈上，並不存在這種資料集中化的架構。節點基本上扮演伺服器的角色，而智能合約則是鏈上「託管」的函式。區塊鏈外部的應用程式（以及其他智能合約）需要一種方式來與鏈上的智能合約溝通，這正是 ABI 發揮作用的地方。

## **為什麼需要 ABI？**

在深入探討 ABI 是什麼之前，先了解我們為何需要它會有幫助。

智能合約是 [EVM（Ethereum Virtual Machine）](https://www.alchemy.com/overviews/what-is-the-ethereum-virtual-machine-evm)的核心應用。智能合約的目的是在合約中定義的特定條件被滿足時執行交易。這些條件可以是鏈上或鏈下的事件。智能合約以高階語言撰寫，例如 [Solidity](https://www.alchemy.com/overviews/solidity)，但它們儲存在 EVM 上時是以可執行的位元組碼（bytecode）形式存在，屬於二進位格式。

<ImageBlock
  src="https://media.alchemy.com/1703767018-evm-executable-bytecode.jpeg"
  alt="以可執行位元組碼形式儲存在 EVM 上的智能合約程式碼示意圖"
  width={1600}
  height={916}
  caption="EVM 上的可執行位元組碼"
/>

由於這種位元組碼並非人類可讀，因此需要經過解讀才能被理解。ABI 讓任何撰寫智能合約的人，都能在以 Javascript 等高階語言寫成的網頁應用程式，與 EVM 所理解的位元組碼之間進行溝通。

## **什麼是 ABI？**

如同它在 Web2 世界的表親 API，ABI 扮演函式選擇器的角色，定義可以呼叫來執行智能合約的特定方法。這些特定方法及其相關的資料型別，會列在一個產生出來的 JSON RPC 檔案中。

<ImageBlock
  src="https://media.alchemy.com/1703767166-abi-function-selector.png"
  alt="ABI 作為智能合約方法函式選擇器的示意圖"
  width={760}
  height={484}
  caption="ABI 函式選擇器"
/>

與 API 不同的是，我們無法直接以 JSON 格式向智能合約發送請求並期待收到回應，因為合約只能以位元組碼溝通。為了將其轉換成 EVM 能理解的內容，這些資訊會透過 ABI encoding 進行編碼。這些編碼包含函式簽章與變數宣告，讓 EVM 能確切知道要在智能合約中執行哪個函式。

<ImageBlock
  src="https://media.alchemy.com/1703767249-abi-encoding.png"
  alt="ABI 編碼將函式呼叫轉換為 EVM 位元組碼的範例"
  width={1362}
  height={280}
  caption="ABI 編碼"
/>

回應也是以位元組碼呈現，因此在被網頁應用程式處理之前，同樣需要經過解讀。使用位元組碼作為回應格式的好處是，我們可以預期呼叫合約函式後會得到某種固定的結構。

## **如何使用 ABI？**

### 產生方式

如果你使用像 Hardhart/Truffle 這類工具，或是像 [Remix](https://remix.ethereum.org/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.7+commit.e28d00a7.js) 這樣的 IDE，合約的 ABI 會自動為你產生。你也可以透過 [Solidity Compiler NPM package](https://www.npmjs.com/package/solc) 手動建立 ABI。安裝該套件後，你可以在終端機中執行「`solcjs contractname.sol --abi`」指令。若執行成功，將會產生一個 .abi 檔案。

現在你已經產生了 ABI，讓我們來看看這個檔案中的一些元素：

<ImageBlock
  src="https://media.alchemy.com/1703767374-generated-contract-abi.png"
  alt="產生的智能合約 ABI JSON 檔案範例"
  width={1600}
  height={730}
  caption="產生的合約 ABI"
/>

### **執行**

由於 ABI 是在網站的 Javascript 與 EVM 位元組碼之間扮演解譯者的角色，因此當你想要執行智能合約的任何函式時，就會需要用到它。除了 ABI 之外，還需要合約在區塊鏈上的地址。以下是一段簡短的 Javascript 程式碼片段，展示如何完成這件事：

<ImageBlock
  src="https://media.alchemy.com/1703767477-executing-abi.png"
  alt="使用 ABI 及地址執行合約函式的 JavaScript 程式碼片段"
  width={1600}
  height={880}
  caption="執行 ABI"
/>

如果你想找出某個已部署合約的 ABI，可以透過該合約的地址在 [Etherscan](https://www.alchemy.com/dapps/etherscan) 上搜尋。例如[這裡](https://etherscan.io/address/0xb4eaf48bd7f72356e1019c157e91b81a1c541073#code)：

<ImageBlock
  src="https://media.alchemy.com/1703767569-abi-of-already-deployed-contract.png"
  alt="Etherscan 合約頁面顯示已部署合約的 ABI"
  width={1600}
  height={315}
  caption="已部署合約的 ABI"
/>

### 編碼

由於所有溝通都是以位元組碼進行，若要求開發者自行編碼這些訊息並不切實際。所幸像 Remix 這類常見的編譯器也能為你處理編碼工作。這些編碼遵循一定的模式，因此可以透過查閱 [ABI Specification](https://docs.soliditylang.org/en/v0.8.11/abi-spec.html) 來更了解其運作方式。

前四個位元組是函式簽章，用來指出智能合約中正在執行的是哪一種函式。一個常見的函式識別碼是 a9059cbb，代表這是一筆 [ERC20](https://www.alchemy.com/overviews/erc20-solidity) 轉帳。這裡有一個函式簽章的[資料庫目錄](https://www.4byte.directory/)，可以進一步查閱。

<ImageBlock
  src="https://media.alchemy.com/1703767678-function-hashes.png"
  alt="ABI 函式簽章雜湊範例，包含 ERC20 transfer 選擇器"
  width={1069}
  height={418}
  caption="ABI 函式雜湊"
/>

從第五個位元組開始，就是參數編碼的部分。回應也遵循類似的結構，只是不包含函式簽章。

## **結語**

ABI 常常是使用智能合約時容易被忽略的一環，但它在這項技術的可用性上扮演著重要角色。以[智能合約教學](https://www.alchemy.com/docs/how-to-deploy-a-smart-contract-to-the-sepolia-testnet)為基礎繼續學習，是理解這個默默運作的幕後功臣的絕佳方式，也是實際應用所學知識的好機會。
