---
title: "如何除錯 pending 的 Ethereum 交易"
description: "了解 Ethereum 交易從送出到被挖出的過程，包括 mempool、pending 交易，以及 Alchemy 的工具如何提供協助。"
---

# 如何除錯 pending 的 Ethereum 交易

當你送出一筆交易到 Ethereum 區塊鏈時，它會去哪裡？什麼是 pending transaction，在它被納入區塊之前發生了什麼事？什麼是 mempool？為什麼有些交易會成功，有些卻會失敗？

我們將深入探討 Ethereum 網路上交易的整個流程，從你按下「送出」的那一刻，到交易完全被納入區塊為止。我們也會討論可能出錯的地方，以及 Alchemy 的開發者工具如何協助你除錯並掌握這整個過程。

雖然這篇指南是針對 Ethereum 撰寫的，但核心原則基本上適用於所有區塊鏈！

## 什麼是 Ethereum 交易？

Ethereum 交易最基本的形式，是使用者請求將新資訊寫入區塊鏈永久狀態的請求。這個請求的內容通常屬於以下幾種形式之一：

1. 單純將價值從使用者的公開帳戶轉移到另一方（例如將 ETH 送給商家）
1. 將一個新的智能合約編碼到公開區塊鏈上，供其他第三方存取（例如啟動一個新的樂透智能合約）
1. 向現有的智能合約傳送資訊以與該合約互動（例如將你的名字與資金輸入一個樂透智能合約）

## 什麼是 mempool？

在理解 Ethereum 的交易流程之前，我們得先理解什麼是 mempool！mempool 是 Ethereum 節點中一個等待區，專門用來暫存尚未確認的交易，作為一個暫存區運作。依你使用的客戶端不同，它也可能被稱為 TX-POOL 或 TX-QUEUE。

送到節點的交易會先進入 mempool，並停留在那裡，直到被網路完全確認為止。mempool 負責處理這個流程中的幾個關鍵步驟，包括：

1. 執行一連串驗證測試，確保交易一旦提交給礦工後能夠成功。節點可能執行的驗證項目包括：是否有足夠的資金支付 gas 費用？交易簽章是否有效？這個 nonce 對於該傳送地址來說是否是下一個順位？
1. 根據 gas 價格，對要處理的交易列表進行排序。較高的 gas 價格意味著該交易更可能被礦工優先處理。
1. 將 pending 交易分享給相鄰節點的 mempool，這些節點會繼續轉發給其他 mempool，讓整個網路都能看到 pending 交易的列表。當一個區塊被挖出時，整個網路中 gas 價格最高的交易將會被確認。

## Ethereum 交易流程是什麼樣子？

了解 mempool 之後，接下來看看從使用者送出交易，到這筆交易永久儲存在區塊鏈上，中間經歷了哪些步驟？

1. 使用者產生一筆新的交易，用自己的私鑰對交易簽章，然後透過呼叫 **eth_sendTransaction** 或 **eth_sendRawTransaction** 方法，將交易送到區塊鏈上的某個節點，這通常是透過像 [Alchemy 的 Node API](https://www.alchemy.com/rpc-api) 這類服務來完成。
1. 交易被送到某個節點的 mempool。
1. mempool 執行一連串驗證測試。如果交易通過這些驗證，就會進入 pending 狀態。
1. 該節點會將交易廣播給區塊鏈上的其他節點，這筆交易最終會出現在這些節點各自的 mempool 中。
1. 一旦區塊鏈上某個節點挖出新區塊，約 200 筆 gas 價格最高的 pending 交易會被納入區塊鏈的下一個區塊中。這些交易會從 mempool 中移除，新區塊與新的 mempool 狀態會傳播到整個網路。
1. 在再確認 5 到 7 個區塊之後，區塊鏈重組並改採另一條分叉（含有不同的一組已確認交易）的機率會變得微乎其微。此時，可以合理假設這筆交易已經永久寫入區塊鏈。

<ImageBlock
  src="https://media.alchemy.com/1703772601-ethereum-transaction-flow.jpeg"
  alt="從簽署到區塊確認的 Ethereum 交易流程圖"
  width={1335}
  height={1600}
  caption="Ethereum 交易流程"
/>

## Pending 中的 Ethereum 交易可能出什麼問題？

### 1. mempool 可能已滿

先從簡單的開始講起。mempool 的大小是有限制的（除非你使用像 Alchemy 這樣的工具！），限制同時存在於整個節點層級，以及節點中每個地址的層級。以 [Geth](https://www.alchemy.com/overviews/what-is-a-geth-node-and-how-to-run-one) 為例，通常限制是 4096 筆 pending 交易，Geth 會捨棄較舊的 pending 交易，優先保留較新的。

### 2. 你的參數可能無效

送出交易時，你需要填入一些相關參數，例如：

- 傳送地址與目標地址是什麼？
- 要轉移的金額是多少？
- 你願意為這筆交易付出多少 gas？
- 這筆交易的 nonce 應該是多少？

如果你在填寫這些參數時出錯，節點通常會回傳一個錯誤代碼來說明問題所在。如果你看不懂錯誤訊息，或是透過 Google 也找不到答案，可以到 [Alchemy 支援中心](https://www.alchemy.com/support)查詢。

### 3. 你的 gas 價格可能太低

為了決定要優先處理哪些交易，Ethereum 交易在提交時必須附上 gas 價格。就像一般的拍賣一樣，較高的 gas 價格意味著你的交易更有機會被納入下一個區塊——而 gas 價格太低則可能導致交易永遠無法上鏈。

由於 gas 價格會根據需求在一天之內快速且難以預測地波動，正確設定這個欄位非常重要。這裡有幾種做法：

- 如果你是手動送出單筆交易，可以到 **ETH Gas Station 網站**查看最新的 gas 價格，並依此設定你的價格。
- 如果你是透過像 Alchemy 這樣的節點提供者送出請求，Ethereum JSON-RPC 規範提供了一個名為 [**eth_estimateGas**](https://www.alchemy.com/docs/node/ethereum/ethereum-api-endpoints/eth-estimate-gas) 的端點，可以讓你估算需要多少 gas 才能讓交易被納入區塊！你可以利用這個功能，以程式化的方式自動設定 gas 價格。
- 如果你想在 gas 價格漲到某個價位以上或跌到某個價位以下時收到推播通知，我們提供一個叫做 [**Alchemy Notify 中的 Gas Price Notifications**](https://www.alchemy.com/docs/reference/notify-api-quickstart) 的工具，可以在這些情況發生時提醒你！因為它是一個 webhook，很容易整合進你的程式碼中，在 gas 價格較低時自動送出交易。

<VideoCta
  title="看看 Alchemy 儀表板實際運作"
  description="30 分鐘導覽：現場示範儀表板中的每項工具。"
  ctaHref="/resources/dashboard-demo"
  thumbnail={{
    src: "https://media.alchemy.com/alchemy-dashboard-demo-thumbnail.png",
    alt: "Alchemy Dashboard Demo",
  }}
/>


### 4. 你的 nonce 可能不正確

啊，每個人心中都有的疑問——nonce 到底是什麼鬼東西，我為什麼需要它？這是個很合理的問題，很高興你問了。

簡單來說，nonce 就是從某個地址送出的交易數量。如果你已經成功確認了五筆交易（nonce 0 到 4），你下一筆 pending 交易的 nonce 就會是 5。

nonce 遵循幾條規則：

- **nonce 必須按順序出現。** nonce 為 4 的交易一定會在 nonce 為 5 的交易之前發生。
- **nonce 不能重複或跳過**——每一筆成功的交易恰好對應一個 nonce。如果你沒有 nonce 為 5 的交易，就不能提交 nonce 為 6 的交易。同樣地，你也不能提交兩筆 nonce 都是 5 的交易——只有一筆會成功。

為什麼我們需要 nonce？從密碼學的角度來看，nonce 是必要的，可確保來自某個地址的交易按照你送出的順序發生，並且能保護你的交易不受[雙重花費問題](https://en.wikipedia.org/wiki/Double-spending)影響。

實際上，nonce 只是你在建立交易時必須設定的一個參數。它讓你能夠精細地手動控制交易的順序。

舉一個實際的例子：假設你想從某個市場購買一個 NFT，然後付一筆小額的「介紹費」給 Bob，感謝他幫你發現這個 NFT。在這種情況下，你只想在成功買到 NFT 之後才付錢給 Bob。如果沒有 nonce，你就沒有辦法同時送出這兩筆交易，還能確保它們按照特定順序發生。使用 nonce，你只需要把其中一筆交易標記為 nonce N，另一筆標記為 nonce N + 1！

不過，這種精細的控制也意味著你每次都必須用正確的 nonce 提交交易！如果你的交易卡住了，就需要檢查你的 nonce，確認它是否依照上述規則正確設定。

### 5. 你的區塊可能被分叉

你會愛上這個問題：即使你的交易成功被納入區塊，你也**還沒**完全脫離險境 😡。

由於區塊鏈是去中心化的，網路中不同的節點集合，可能對網路狀態有不同的看法。特別是，偶爾會有兩個礦工幾乎同時挖出新區塊，而相鄰的節點也會以大致相同的速度跳上這兩條新鏈。在這種情況下，兩條新鏈會平行成長——但最終其中一條會獲得稍微多一點的共識！

當整個網路都轉向其中一條鏈，並放棄另一條時，舊鏈上已經「被挖出」的交易就會被分叉掉，因而失效。這些被分叉的區塊也被稱為「uncle blocks」。

也就是說，即使你的交易已經被挖出，它仍然可能因為區塊分叉而失效！你可以在[這裡查看 Etherscan 上的分叉區塊歷史記錄](https://etherscan.io/blocks_forked)。所幸在 [Ethereum 主網](https://www.alchemy.com/rpc/ethereum)上，這種情況並不常見，且通常深度不超過 5 個區塊，但這也是為什麼在 DeFi 交易協議中，你的交易在至少 5 到 7 個區塊確認之前，永遠不會被視為「完全」確認。

## 有哪些工具可以用來管理我的 mempool 和 Ethereum pending 交易？

### Alchemy mempool watcher

假設你在四十分鐘前送出一筆交易到某個節點的 mempool，但一直沒看到它在區塊鏈上被確認。你想知道它目前的狀態、送出時的 gas 價格，以及 nonce，以便再次確認。這時候該怎麼辦？

過去（現在也一樣）要查看你 mempool 交易的狀態是一件很麻煩的事。由於進入 mempool 狀態的唯一介面是透過 Ethereum JSON-RPC API，開發者常常得花好幾個小時去查詢各個送出交易的節點、合併並篩選一頁又一頁的日誌，試圖手動重建整個 mempool 的狀態——這一切只為了一次查詢。

以下是一個繁忙 mempool 的一般查詢結果：

<ImageBlock
  src="https://media.alchemy.com/1704722572-successful-request-to-the-mempool-to-fetch-its-status.jpg"
  alt="mempool 狀態請求的原始 JSON 回應，密密麻麻難以閱讀"
  width={1600}
  height={683}
  caption="祝你讀這團亂碼讀得開心。"
/>

更糟的是，當開發者為了擴展規模，開始將請求送往多個節點時，就會出現嚴重的一致性問題——因為交易是從單一節點發出的，針對特定交易的請求每次都需要黏著（sticky）路由到同一個節點。

為了解決這些挑戰，我們打造了 [Mempool Watcher](https://dashboard.alchemy.com/mempool)——一個能大幅簡化這種複雜度的工具。首先，我們處理了所有的節點路由問題，讓你即使同時利用數十個節點來擴展規模，你的 mempool 看起來仍然像是單一實體——mempool 請求會在我們的基礎架構中被正確地路由到對應的節點。

其次，我們提供了一些相當好用的工具，讓你能即時查看交易的狀態。交易會被標記為已挖出（mined）、pending 或已捨棄（dropped）。每筆交易紀錄都包含該交易處於 pending 狀態的持續時間、所需的 gas 數量，以及查看更多詳細資訊的入口。

<ImageBlock
  src="https://media.alchemy.com/1704724124-alchemy-mempool-watcher.png"
  alt="這就是用我們的工具查看 mempool 時的樣子！"
  width={1600}
  height={579}
  caption="這就是用我們的工具查看 mempool 時的樣子！"
/>

### Alchemy explorer

如果你透過一個腳本同時送出二十筆不同的交易到某個節點，卻發現其中有些交易甚至沒能送達節點，這時該怎麼追蹤這些失敗的回應，並找出規律以判斷原因？

和前面提到的情況類似，通常身為開發者，你得翻閱大量日誌才能找出規律。為了解決這個問題，我們打造了一個請求／回應瀏覽工具，讓你可以追蹤透過我們 API 送出的 JSON-RPC 請求的狀態！

<ImageBlock
  src="https://media.alchemy.com/1704724183-alchemy-explorer.png"
  alt="Alchemy Explorer 列出歷史 JSON-RPC 請求與回應"
  width={1600}
  height={928}
  caption="Alchemy Explorer"
/>

我們的 [**Alchemy Explorer**](https://dashboard.alchemy.com/explorer) 讓你可以搜尋從 1 秒前到 7 天前之間，透過我們基礎架構送出的歷史請求與回應！再也不用大海撈針地找日誌——現代化的技術就在你的指尖。

在這些請求中，你可以依照各種參數篩選查詢，例如方法類型、HTTP 回應，或是節點特定的錯誤！你也可以依照時間戳記、請求持續時間等多種條件來查看請求。

## 我為什麼應該使用 Alchemy 來管理我的交易？

Alchemy 是一個節點提供者，這代表我們負責管理與 Ethereum 區塊鏈（以及其他幾條鏈！）之間送出與接收請求所需的所有基礎架構。以下是[為什麼你需要一個節點提供者](https://www.alchemy.com//overviews/blockchain-node-providers)的相關資訊。

一旦你透過我們的系統送出請求，你就能享有前面提到的所有 pending 交易相關優勢：可擴展的 mempool、儀表板工具、gas 價格 webhook。

除此之外，我們還提供：

- 存取 Alchemy 的 Node API，背後由專屬基礎架構支撐，解決了困擾區塊鏈已久的可擴展性與一致性問題。
- 存取我們的 Dashboard，透過上述那些探索請求的工具，協助你建置並監控你的應用程式。
- 存取 Alchemy Notify，這是一個針對區塊鏈上發生的事件（例如交易）提供推播通知（webhook）的工具。
- 存取我們的 Enhanced APIs，讓你能夠執行那些原本在區塊鏈上計算成本高昂或根本無法實現的請求。
- 還有更多，包括在多條鏈上使用這些功能，例如 [Flow](https://www.alchemy.com/flow)、[Crypto.org](https://www.alchemy.com/crypto-org)，以及 L2 如 [Polygon](https://www.alchemy.com/layer2/polygon)、[Optimism](https://www.alchemy.com/layer2/optimism) 和 [Arbitrum](https://www.alchemy.com/layer2/arbitrum)！

## 開始使用 Alchemy
解鎖 Alchemy 的 Node API 與開發者工具非常簡單——事實上，這應該只需要一行程式碼！如果你一直在使用 [web3.js](https://www.alchemy.com/dapps/web3-js) 或 [ethers.js](https://www.alchemy.com/dapps/ethers-js)，只要[免費建立一個 Alchemy 帳號](https://alchemy.com/?a=a437fb8d33)、產生一組 API key，再把實例化的部分換成類似這樣的程式碼即可：

如果你想要完整的教學，請閱讀我們的 [Getting Started with Alchemy guide](https://www.alchemy.com/docs/alchemy-quickstart-guide)。如果你需要更多協助，歡迎造訪 [Alchemy 支援中心](https://www.alchemy.com/support)。
