---
title: "以 gas 優化交易擴展 Smurfs' Society"
description: "Smurfs' Society 使用 Alchemy 的 gas 優化交易，在 Polygon 上 gas 價格劇烈波動期間確保交易能被打包上鏈。"
---

## 與 Alchemy 合作擴展鏈上交易規模

**作者：** **The Smurfs' Society Team**

[The Smurfs' Society](https://thesmurfssociety.com/) 是 Smurfs 官方的 web3 專案。這個專案是一個僅限邀請、完全上鏈的遊戲化平台，於 2022 年 12 月上線，在不到一個月內就產生了超過 30,000 個錢包連接以及 150 萬筆鏈上轉帳，使其成為 DappRadar 上使用量前 100 名的應用程式之一。

在這篇文章中，其 CTO 暨共同創辦人將探討擴展大量鏈上交易所面臨的技術挑戰，以及他們的團隊如何與 Alchemy 合作，為使用 [Transact API suite](https://www.alchemy.com/transact) 的數萬名玩家提供流暢且穩定的使用者體驗。

## **區塊鏈情境下「擴展性」的相對性**

包括我自己在內，大多數人不會認為每分鐘 100 筆交易是個「規模」或量級問題。過去，我曾協助許多公司在跨多個資料中心、TB 級資料量、低延遲與高流量的環境下最佳化 Cassandra 叢集部署；在那個時候，我從未想過，在處理區塊鏈基礎設施時，這麼低的交易量竟然會難以達成。

挑戰有兩方面：

1. 我們需要能夠實際執行交易
1. 我們需要[確保交易的正確性](https://alchemy.com/blog/data-accuracy)，更精確地說，是其最終資料的一致性與準確性。

要解決第一個挑戰，基本上與在 k8s 中部署具有自動擴展能力的任何平台叢集的規模設定相同。唯一的差異在於我們使用 HD wallet 在 StatefulSet 中分片負載的方式，讓每個 pod 擁有自己直接管理的錢包。而且，別忘了區塊鏈要求交易必須依序執行（針對特定錢包的順序而言）。

至於第二個挑戰，可以想像一筆[交易卡在 mempool 中](https://www.alchemy.com/overviews/transaction-propagation)，卻因為 gas 的關係沒有被打包。

**我們的選項有：**

1. 等待網路降溫（如果可行），讓交易自然被打包
1. 用新交易覆寫原交易（強制使用相同 nonce），並提高 gas 設定
1. 直接換一個錢包

顯然，在我們的情境下，選項 1 和選項 3 都不可行。所以選項 2 是我們唯一的選擇，而這也帶來了自己的複雜性。

以下簡要說明我們與 Alchemy 合作，從 [Reinforced Transactions](https://www.alchemy.com/docs/reference/mev-protection) 轉向 [Gas Optimized Transactions](https://www.alchemy.com/docs/reference/mev-protection) 的經驗。

### **在最大化正確性的同時，每天打包 20,000 筆交易**

為什麼要擴展一個以區塊鏈為骨幹、大量使用區塊鏈功能的應用程式或遊戲會這麼困難？

- 我們是否受限於單一區塊能打包的交易數量？
- 我們是否受限於整體網路的容量？
- 我們是否受限於網路壅塞以及特定的日內使用模式？
- 我們是否受限於區塊鏈上交易的執行方式？
- 我們是否受限於 gas 價格的波動性？

經過幾週的運作，以及對所有控制機制進行大量反覆調整後，我們現在已經有一個讓遊戲能在最佳條件下運作的平台。

在說明我們為了走到這一步所克服的所有障礙之前，先讓我介紹遊戲的運作機制，概述我們從區塊鏈角度自動化的操作及其挑戰，接著再說明我們如何與 Alchemy 合作解決這些問題。

## **Smurfs 的鏈上遊戲是如何運作的？**

目前這款遊戲是對傳統「候補名單」概念的一種顛覆，玩家混合食材，嘗試找出能製成藥水的配方，其中某些配方可以取得水晶的資格（保證享有折扣的鑄造資格）。

遊戲中使用的所有資產都以 NFT 表示。對於我們視為可替代且可消耗的物品（例如食材、藥水、藍色黏土、小雕像等），採用 ERC-1155 代幣；對於不可替代的物品（例如水晶），則採用 ERC-721 代幣。

### Smurfs 遊戲的互動方式

以下是我們的平台與 Polygon 網路之間、為讓遊戲運作所需的互動：

1. **領取由食材組成的掉落箱** - 玩家每天都可以領取一個含有 3 種食材的箱子
1. **鑄造小雕像（遊戲的核心元件）** - 所有玩家都必須擁有一個小雕像，才能完成遊戲中的各種操作。玩家登入遊戲時會免費獲得小雕像。小雕像的作用將於遊戲後續階段公佈。
1. **燃燒黏土** - 當玩家嘗試配方失敗時，藍色黏土會被燃燒（x1）

另一方面，玩家在 Polygon 網路上只需執行一項操作：

1. **混合配方** - 玩家混合 3 種食材來製作一個配方（此情況下由玩家支付 gas 費用）。

<ImageBlock
  src="https://media.alchemy.com/1704556400-player-mixing-a-recipe.png"
  alt="Smurfs' Society 遊戲畫面，顯示玩家將三種素材混合成一個配方"
  width={654}
  height={319}
  caption="圖 1：玩家混合配方"
/>

對於前兩項功能，我們可以用完全非同步的方式運作，即使某筆嘗試的交易遲遲未被打包，對遊戲也不會有實質影響。當然，從體驗角度來說，我們當然希望這些等待時間越短越好。

燃燒黏土則比較具有挑戰性，實作上的選擇主要是由遊戲本身所決定的。當玩家實際提出一個配方時，他們會簽署一個 EIP-712 結構，其中包含他們想用來混合的所有食材，並附上 3 小時的期限，如下所示。

<ImageBlock
  src="https://media.alchemy.com/1704556456-player-signs-eip-712-to-propose-a-recipe.png"
  alt="圖 2：玩家簽署 EIP-712 以提交配方"
  width={354}
  height={499}
  caption="圖 2：玩家簽署 EIP-712 以提交配方"
/>

如果找不到與該組合對應的配方，這個簽章就會被用作燃燒的授權依據。而我們會代表玩家執行這筆 burnClay 交易，承擔相關的交易手續費。

**從這裡開始，我們必須管理幾種狀態：**

1. 交易處於傳輸中 - 儲存於鏈下 -\> 正在移至鏈上。用於對帳。
1. 交易位於 mempool 中，等待被打包 - 這是個過渡狀態，需要我們核對我們認為使用者「進行中」的狀態，與實際正在處理的狀態是否一致 - 而且完全無法保證需要多久時間
1. 交易已被打包 - 畫面上顯示的藍色黏土數量現在是準確的。這是最終狀態，不構成任何挑戰 - 區塊鏈即是真實來源
1. 交易已被打包，但被視為已中止

### 為什麼 Smurfs 團隊選擇 Polygon

在理想情況下，我們希望所有狀態都能在 1 分鐘以內收斂，以確保操作的正確性與遊戲體驗。針對這個應用場景，我們決定在遊戲化階段使用 Polygon 網路。以下是幫助我們[選擇 Polygon 作為網路](https://www.alchemy.com/polygon)的一些重要考量：

- 快速的最終確認時間，以確保反應靈敏
- 降低交易手續費，便於管理營運成本
- 與 Ethereum 的互通性，著眼於長期規劃

**我們的挑戰：在最大化一致性的同時，每天打包 20,000 筆交易**

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

## **在維持高成功率的同時，降低 Polygon gas 波動性的影響**

Polygon 可能會遇到壅塞，這會直接影響我們，為前面描述的各項操作增加延遲。有一些基本做法可以用來應對：

1. **分片** - 讓多個錢包同時與區塊鏈互動。只要有一個可運作的錢包（類似資料庫的連線池），交易就能進行。
1. **提高出價** - 為了確保我們的交易能及時被處理，我們可以提高[優先費用（EIP-1559）](https://www.alchemy.com/docs/how-to-send-transactions-on-ethereum)的誘因。

我們最初的設定是使用 [**Reinforced transaction**](https://www.alchemy.com/docs/reference/mev-protection) 方案，並在 gas 費用上高於市場出價，以最佳化交易的最終確認時間。

<ImageBlock
  src="https://media.alchemy.com/1704556545-example-of-extreme-gas-prices-on-polygon.png"
  alt="Polygon 上極端 gas 價格的範例。"
  width={558}
  height={199}
  caption="Polygon 上極端 gas 價格的範例。"
/>

<ImageBlock
  src="https://media.alchemy.com/1704556581-example-of-dramatic-gas-price-volatility-on-polygon.png"
  alt="Polygon 上劇烈 gas 價格波動的範例。"
  width={546}
  height={191}
  caption="Polygon 上劇烈 gas 價格波動的範例。"
/>

這兩張截圖是在幾分鐘的間隔內（約 5 分鐘）拍攝的。可以看到在很短的時間範圍內，gas 出現了很大的變化，這對我們有直接的影響：市場上 gas 價格的任何劇烈波動，都可能讓我們的交易卡住，進而卡住我們其中一個錢包！

### 如何在 gas 波動期間最佳化 Polygon 交易

我們開始著手在 gas 波動期間最佳化交易，方式包括：

- 為我們的應用程式增加韌性，並在更長的時間範圍內更好地追蹤交易狀態
- 追蹤並在出現異常徵兆時發出警示 - 我們是透過追蹤一則訊息被處理所需的時間來達成這一點的

**微觀來看一切正常時，會看到這樣的情況：**

<ImageBlock
  src="https://media.alchemy.com/1704556646-processing-time-that-varies-but-below-20-second-mark.png"
  alt="處理時間雖有變動但維持在 20 秒以下的健康流程。"
  width={1600}
  height={432}
  caption="處理時間雖有變動但維持在 20 秒以下的健康流程。"
/>

**而從宏觀層面來看，當事情變得更有意思時：**

<ImageBlock
  src="https://media.alchemy.com/1704556694-messages-that-are-older-than-200-seconds.png"
  alt="超過 200 秒未處理訊息的範例。"
  width={1600}
  height={436}
  caption="超過 200 秒未處理訊息的範例。"
/>

偶爾會有訊息「老了」將近 200 秒（上面的例子是我們遇過最棘手的一天）。當這個時間差距變得過大時，玩家就會開始察覺到：最明顯的訊號就是藍色黏土計數器不會減少。

在我們最慘的一天，也就是 Polygon 升級之後，我們不得不暫停遊戲 30 分鐘，因為有些交易一直無法被打包。

從那時起，我們便積極與 Alchemy 合作，利用他們其中一項新功能來應對這個挑戰，並決定加入 [**Gas Optimized transactions**](https://www.alchemy.com/docs/reference/mev-protection) 的 beta 測試。

**Gas optimized transactions 的核心訴求，是管理不可預測的異常狀況。**

試想一下，與其用某種寫死的邏輯來決定 gas、簽署單一一筆交易，不如簽署 5 或 10 筆具有不同 gas 價格條件的交易，然後讓 Alchemy 自動逐步提高 nonce 的出價！

在我們的案例中，我們決定採用以下的遞增策略：1.25、1.5、1.75、2、2.25、2.5

目前為止，我們已經獲得了很不錯的成效。

我們已經成功進行了多項最佳化，並在系統中實際看到成效。我們期待繼續與 Alchemy 團隊合作，也要在此親自感謝他們在狀況出問題的那天展現出的反應速度，以及迅速的回應時間。選對合作夥伴真的很重要！

Smurfily,

The Smurfs' Society team.
