---
title: "Solidity 中的 event 是什麼？"
description: "了解 Solidity Event 的運作方式"
---

# Solidity 中的 event 是什麼？

[Solidity](https://www.alchemy.com/overviews/solidity) 事件對智能合約開發者來說至關重要，因為它們讓智能合約可以索引變數以重建儲存狀態，協助自動更新使用者介面，並可用於測試特定變數。本文將幫助你深入理解 Solidity 事件，並[加深你對 Solidity 程式語言的理解](https://www.alchemy.com/university/courses/solidity?a=d7f2788ae5)。

我們會先介紹 Solidity 事件，接著說明其分類，並提供範例。讀完本文後，你將能夠為下一個專案建立 Solidity 事件。

## **什麼是 Solidity 中的事件？**

**在 Solidity 中，事件是智能合約可以觸發的訊號。** 當你呼叫事件時，會讓傳入的參數被儲存到交易日誌（transaction log）中，這是區塊鏈上一種特殊的資料結構。事件會通知外部使用者（例如監聽中的前端網站或客戶端應用程式），區塊鏈上發生了某件事。

### **Solidity 中事件與函式有什麼差別？**

**函式與事件都能接收參數並被呼叫，但函式會直接修改智能合約，而事件的作用是通知區塊鏈外部的服務，讓使用者知道發生了某件事。**

[Solidity 中的函式](https://www.alchemy.com/overviews/solidity-functions)讓開發者可以在智能合約中讀取、寫入、修改及儲存資料。你可以將引數或參數傳入函式，也可以在程式碼中需要時呼叫函式。

事件同樣接受引數，但這些引數會被儲存在交易日誌中，智能合約無法存取這些資料。合約資料存放在 States trie，而事件資料則存放在 Transaction Receipts trie，這代表合約無法讀取事件資料。

與函式一樣，事件也可以被呼叫。不過呼叫或觸發事件時使用的是 _emit_ 關鍵字。這讓開發者可以知道何時呼叫了某個事件或函式。

### 事件與日誌之間的關係為何？

Ethereum 的 Log 資料結構用來儲存事件所發出的資料。

Ethereum Virtual Machine（EVM）具有日誌功能，用來將資料（包含 Solidity 事件）寫入智能合約以外的結構中。

日誌與事件經常被當作同義詞使用。事件讓你可以將資訊「印出」到日誌結構中，這種方式比使用儲存變數更省 gas，因為儲存變數會佔用更多 gas。事件（或日誌）存放在 Transaction Receipts trie 中，智能合約無法存取。

#### **Solidity 中的事件如何被索引？**

**Solidity 事件是與 EVM 日誌功能對接的介面。** 你最多可以為三個參數加上 indexed 屬性。加上此屬性後，這些參數會出現在 topics 結構中，而非日誌的 data 部分。沒有 indexed 屬性的參數，則會以 ABI 編碼方式存入日誌的 data 部分。

## **Solidity 事件的類型**

Solidity 事件有兩種類型：已索引（indexed）與未索引的事件。

沒有 indexed 屬性的參數，會被[以 ABI 編碼](https://www.alchemy.com/overviews/solidity-abi)存入日誌的 data 部分，這些參數會組成該事件的位元組陣列。資料會依照其型別進行編碼，並可依照 schema 進行解碼。

已加上 indexed 屬性的參數也稱為「topics」，是事件中可供搜尋的參數。透過這些 indexed 參數，你可以將其作為篩選條件來搜尋對應的事件。根據事件是否為匿名事件，你最多可以為 4 個或 3 個參數加上 indexed 屬性。

## **Solidity 中事件如何運作？**

**Solidity 事件的運作分為宣告、觸發與註冊三個步驟。**

1. 首先，事件型別必須使用 Solidity 中的 _event_ 關鍵字進行宣告。
1. 接著，需要使用 emit 關鍵字來觸發該事件。
1. 只要區塊鏈上發生任何變化，你的程式就會自動註冊這項變化並觸發該事件。

**注意：** 在宣告事件後將其觸發，可讓你透過應用程式使用 [Web3.js](https://www.alchemy.com/dapps/web3-js) 或 Ethers.js 等函式庫「監聽」該事件。

### **如何在 Solidity 中宣告事件？**

**事件的宣告內容包含事件名稱，以及你希望在觸發事件時儲存的參數。**

首先，你必須在 Solidity 中宣告一個事件，接著使用 _emit_ 關鍵字來觸發該事件。

以下是宣告事件的範例：

事件觸發時，會通知外部應用程式區塊鏈上發生了某項變化。

### **Solidity 中的事件如何被觸發？**

事件定義完成後，你可以使用 emit 關鍵字來觸發該事件。事件一旦被觸發，傳入的引數就會被儲存到交易日誌中。

以下語法示範如何在 Solidity 中使用 emit：

## **如何在 Solidity 中監聽事件**

事件觸發後，你可以透過訂閱的方式來監聽這些事件，例如使用 [ethers.js](https://www.alchemy.com/dapps/ethers-js)。之後，[應用程式](https://www.alchemy.com/dapps/top/defi-dapps)或任何連接到 Ethereum JSON-RPC API 的服務，都可以監聽這些事件並依此執行對應動作。

### **Solidity 事件範例**

以下範例程式碼定義並觸發了一個用於轉帳的事件。此程式碼適用於 Ethereum 轉帳應用程式，當轉帳發生時會觸發該事件。你也可以加入額外程式碼，讓事件觸發時能更新使用者介面，以顯示轉帳已完成。

<ImageBlock
  src="https://media.alchemy.com/1703866327-solidity-event-example.png"
  alt="Solidity 程式碼範例，於智能合約中定義並發出 Transfer 事件"
  width={1600}
  height={743}
  caption="定義並發出 transfer 事件"
/>

下一個範例取自 **Solidity by Example**，建立了一個帶有兩個參數的事件：傳送者的地址與字串訊息。觸發時，該事件會記錄「Hello World」與「Hello EVM」。

<ImageBlock
  src="https://media.alchemy.com/1703866441-solidity-event-with-two-parameters.png"
  alt="Solidity 程式碼範例，事件包含兩個參數：sender address 與 message string"
  width={1558}
  height={890}
  caption="包含兩個參數的事件"
/>

## **持續學習 Solidity**

本文向你介紹了 Solidity 事件，並提供了說明與資源，供你在下一個專案中使用。有了 Solidity 事件，建立高效的智能合約會變得更容易。

如果你剛接觸 Solidity 語言，並期待打造你的第一個智能合約，歡迎報名 Alchemy University 免費、為期 7 週的[線上 Solidity 程式課程](https://www.alchemy.com/university/courses/solidity?a=d7f2788ae5)。
