---
title: "ERC721 vs. ERC721A：批次鑄造 NFT"
description: "由 Azuki 團隊建立的 ERC721 標準替代實作，可用於優化批次鑄造 NFT。"
---

# ERC721 vs. ERC721A：批次鑄造 NFT

許多 NFT 創作者都知道，[在 Ethereum mainnet 上部署智能合約](https://www.alchemy.com/overviews/nft-deployment-cost)可能會非常昂貴。

然而，智能合約部署成本並**不是**區塊鏈工程師和 NFT 團隊唯一需要考慮的成本。[打造成功的 NFT collection](https://www.alchemy.com/overviews/how-to-create-a-successful-nft-project)或收藏頭像專案，還包括建立社群，並讓使用者能夠輕鬆**鑄造**、**交易**與**使用**他們的 NFT。

我們來了解一個能幫助社群節省 NFT 鑄造 gas fee 的強大 NFT 智能合約優化方式：

透過 ERC721A 合約實現批量鑄造（batch minting）！

### 什麼是 ERC721A？

1 月 6 日，Azuki NFT 開發團隊公開發布了 [ERC721A，一個探索批量鑄造的 ERC721 NFT 標準新實作](https://www.azuki.com/erc721a)：

<ImageBlock
  src="https://media.alchemy.com/1704712932-azuki-team-introducing-erc721a-implementation.png"
  alt="Azuki 團隊介紹 ERC721A 實作"
  width={1108}
  height={938}
  caption="Azuki 團隊介紹 ERC721A 實作"
/>

在說明 ERC721A 智能合約實作的部落格文章中，**@locationtba** 和 **@2pmflow** 展示了估算數據，比較透過最常用的 NFT 智能合約起始程式碼——[OpenZeppelin 的 ERC721Enumerable 合約](https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#ERC721Enumerable)——進行批量鑄造，與使用新的 Azuki [ERC721A 合約](https://github.com/chiru-labs/ERC721A)進行批量鑄造，兩者能節省多少 gas：

<EmbeddedTable
  table={{
    columns: [
      { key: "1", width: 200, title: "NUMBER MINTED", dataType: "object" },
      { key: "2", width: 200, title: "GAS USED (ENUMERABLE)", dataType: "object" },
      { key: "3", width: 200, title: "GAS USED (ERC721A)", dataType: "object" },
      { key: "4", width: 200, title: "GAS SAVED", dataType: "object" },
    ],
    data: [
      {
        "1": { title: "<p>Mint 1</p>", tooltip: "", icon: "" },
        "2": { title: "<p>154,814</p>", tooltip: "", icon: "" },
        "3": { title: "<p>76,690</p>", tooltip: "", icon: "" },
        "4": { title: "<p>78,124</p>", tooltip: "", icon: "" },
        id: 0,
      },
      {
        "1": { title: "<p>Mint 2</p>", tooltip: "", icon: "" },
        "2": { title: "<p>270,339</p>", tooltip: "", icon: "" },
        "3": { title: "<p>78,819</p>", tooltip: "", icon: "" },
        "4": { title: "<p>191,520</p>", tooltip: "", icon: "" },
        id: 1,
      },
      {
        "1": { title: "<p>Mint 3</p>", tooltip: "", icon: "" },
        "2": { title: "<p>384,864</p>", tooltip: "", icon: "" },
        "3": { title: "<p>80,948</p>", tooltip: "", icon: "" },
        "4": { title: "<p>303,916</p>", tooltip: "", icon: "" },
        id: 2,
      },
      {
        "1": { title: "<p>Mint 4</p>", tooltip: "", icon: "" },
        "2": { title: "<p>501,389</p>", tooltip: "", icon: "" },
        "3": { title: "<p>83,077</p>", tooltip: "", icon: "" },
        "4": { title: "<p>418,312</p>", tooltip: "", icon: "" },
        id: 3,
      },
      {
        "1": { title: "<p>Mint 5</p>", tooltip: "", icon: "" },
        "2": { title: "<p>616,914</p>", tooltip: "", icon: "" },
        "3": { title: "<p>85,206</p>", tooltip: "", icon: "" },
        "4": { title: "<p>531,708</p>", tooltip: "", icon: "" },
        id: 4,
      },
    ],
  }}
/>

這個表格顯示，隨著鑄造數量增加，ERC721A 使用的 gas 是以更小的常數因子在成長。

鑄造 NFT 的 gas 成本增加幅度為：

- 使用 Azuki ERC721A 合約：每多鑄造一個 **約增加 2k gas**
- 使用 [OpenZeppelin](https://www.alchemy.com/dapps/openzeppelin) ERC721Enumerable 合約：每多鑄造一個 **約增加 115k gas**

這個結果其實**非常驚人**！

以透過 ERC721Enumerable 合約鑄造一個 token 的價格，使用者透過 ERC721A 合約可以鑄造多達 5 個 token（甚至可能更多）。

誰不希望使用者的鑄造費用能節省高達 80% 呢？

更棒的是：

不只個別交易的 NFT 鑄造價格會變便宜，在熱門 collection 開賣期間，Ethereum 網路的**壅塞程度**也會降低，**gas 價格的暴漲**也會減少。

相當不錯的結果。

### 驗證批量鑄造多個 NFT 的 gas 節省效果

我想自己驗證這個結果，所以實作了兩個基本的 NFT 合約來[建立 NFT](https://www.alchemy.com/docs/how-to-interact-with-erc-721-tokens-in-solidity)：

1. 一個[使用 ERC721Enumerable 鑄造的智能合約](https://github.com/thatguyintech/demo-erc721a/blob/main/src/DemoErc721.sol)，以及
1. 一個[使用 ERC721A 鑄造的智能合約](https://github.com/thatguyintech/demo-erc721a/blob/main/src/DemoErc721a.sol)

接著，我分別呼叫兩者的 mint 函式，並記錄每筆交易的 gas 成本。

以下是我的結果：

這些測試的程式碼可以在這個 GitHub repo 中找到：[demo-erc721a](https://github.com/thatguyintech/demo-erc721a)

這裡鑄造多個 NFT 的 gas 成本跟 Azuki 部落格文章顯示的數字略有不同，但相當接近，而且從鑄造一個、兩個到多個的 gas fee 增幅趨勢是一致的。

我們驗證了批量鑄造 NFT 確實能節省 gas！✅

### ERC721A 智能合約如何透過批量鑄造節省 gas fee？

ERC721A 做了一些假設，這些假設影響了它的智能合約設計：

1. **Token ID 應該永遠從 0 開始連續遞增**。大多數 NFT 專案本來就是這麼做的，Azuki 也在他們的假設中明確說明了這一點。
1. **降低鑄造 NFT 的 gas 成本，比優化其他任何 ERC721 呼叫都更重要**。鑄造正是 Ethereum 網路壅塞發生的時刻，也是使用者對一個 NFT collection 的第一印象。鑄造過程越輕鬆，口碑就越好。

在這些假設之下，ERC721A 做了以下的合約優化：

1. **減少 token metadata 的儲存浪費**。
1. **將 ownership 狀態更新限制為每批次鑄造只更新一次**，而不是每鑄造一個 NFT 就更新一次。

我們會來看看這些優化是怎麼做到的，但在那之前，我們應該先了解哪種交易的 gas fee 成本最高。

### 減少發送寫入交易所需的工作量，能為使用者節省 gas

區塊鏈上的交易大致可分為兩種：寫入（write）和讀取（read）。

**寫入**發生在我們修改或更新區塊鏈狀態時（例如：轉帳、寫入訊息、交易 NFT）。

**讀取**發生在我們請求既有資料以進行查看時。

使用者**為寫入函式支付的 gas fee，永遠會比讀取函式的還要多**。

因此，透過減少寫入交易的數量，或是減少發送寫入交易所需的工作量——即使這會讓之後的讀取交易需要更多工作量——都能降低使用者需支付的 NFT 鑄造成本！

而這正是 ERC721A 所達成的目標。

在 NFT 鑄造這件事上：儲存越多，問題越多；儲存越少，問題越少。

很聰明，對吧？

<EmbeddedTable
  table={{
    columns: [
      { key: "1", width: 200, title: "Unit ID", dataType: "object" },
      { key: "2", width: 200, title: "Owner", dataType: "object" },
    ],
    data: [
      {
        "1": { title: "<p>#100</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Alice</p>", tooltip: "", icon: "" },
        id: 0,
      },
      {
        "1": { title: "<p>#101</p>", tooltip: "", icon: "" },
        "2": { title: "<p>&lt;not set&gt;</p>", tooltip: "", icon: "" },
        id: 1,
      },
      {
        "1": { title: "<p>#102</p>", tooltip: "", icon: "" },
        "2": { title: "<p>&lt;not set&gt;</p>", tooltip: "", icon: "" },
        id: 2,
      },
      {
        "1": { title: "<p>#103</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Bob</p>", tooltip: "", icon: "" },
        id: 3,
      },
      {
        "1": { title: "<p>#104</p>", tooltip: "", icon: "" },
        "2": { title: "<p>&lt;not set&gt;</p>", tooltip: "", icon: "" },
        id: 4,
      },
    ],
  }}
/>

ERC721A 合約只需要設定兩次 ownership metadata：Alice 那批一次，Bob 那批一次。

然而，這也代表當要轉移一個沒有明確設定 owner 地址的 tokenID 時，合約必須從頭跑迴圈遍歷所有 tokenID，直到找到第一個有明確 owner 地址的 NFT，才能找到有權轉移該 token 的擁有者，然後設定新的 owner——也就是說，為了維持正確的分組，ownership 狀態可能會被修改不只一次。

以下是一個測試，用來[模擬轉移情境並記錄 gas 成本](https://github.com/thatguyintech/demo-erc721a/blob/main/test/gas-costs.js#L84-L97)：

<EmbeddedTable
  table={{
    columns: [
      { key: "1", width: 200, title: "", dataType: "object" },
      { key: "2", width: 200, title: "Mint 1", dataType: "object" },
      { key: "3", width: 200, title: "Mint 2", dataType: "object" },
      { key: "4", width: 200, title: "Mint 3", dataType: "object" },
      { key: "5", width: 200, title: "Mint 4", dataType: "object" },
      { key: "6", width: 200, title: "Mint 5", dataType: "object" },
    ],
    data: [
      {
        "1": { title: "<p>t0</p>", tooltip: "", icon: "" },
        "2": { title: "<p>71355</p>", tooltip: "", icon: "" },
        "3": { title: "<p>92043</p>", tooltip: "", icon: "" },
        "4": { title: "<p>92043</p>", tooltip: "", icon: "" },
        "5": { title: "<p>92043</p>", tooltip: "", icon: "" },
        "6": { title: "<p>92043</p>", tooltip: "", icon: "" },
        id: 0,
      },
      {
        "1": { title: "<p>t1</p>", tooltip: "", icon: "" },
        "2": { title: "<p></p>", tooltip: "", icon: "" },
        "3": { title: "<p>91197</p>", tooltip: "", icon: "" },
        "4": { title: "<p>111885</p>", tooltip: "", icon: "" },
        "5": { title: "<p>111885</p>", tooltip: "", icon: "" },
        "6": { title: "<p>117345</p>", tooltip: "", icon: "" },
        id: 1,
      },
      {
        "1": { title: "<p>t2</p>", tooltip: "", icon: "" },
        "2": { title: "<p></p>", tooltip: "", icon: "" },
        "3": { title: "<p></p>", tooltip: "", icon: "" },
        "4": { title: "<p>93927</p>", tooltip: "", icon: "" },
        "5": { title: "<p>114615</p>", tooltip: "", icon: "" },
        "6": { title: "<p>114615</p>", tooltip: "", icon: "" },
        id: 2,
      },
      {
        "1": { title: "<p>t3</p>", tooltip: "", icon: "" },
        "2": { title: "<p></p>", tooltip: "", icon: "" },
        "3": { title: "<p></p>", tooltip: "", icon: "" },
        "4": { title: "<p></p>", tooltip: "", icon: "" },
        "5": { title: "<p>96657</p>", tooltip: "", icon: "" },
        "6": { title: "<p>111885</p>", tooltip: "", icon: "" },
        id: 3,
      },
      {
        "1": { title: "<p>t4</p>", tooltip: "", icon: "" },
        "2": { title: "<p></p>", tooltip: "", icon: "" },
        "3": { title: "<p></p>", tooltip: "", icon: "" },
        "4": { title: "<p></p>", tooltip: "", icon: "" },
        "5": { title: "<p></p>", tooltip: "", icon: "" },
        "6": { title: "<p>99387</p>", tooltip: "", icon: "" },
        id: 4,
      },
    ],
  }}
/>

閱讀這張表格的方式是先看 x 軸，再看 y 軸，例如：

- 「批量鑄造 1 個 NFT，然後轉移 tokenID 0」，或
- 「批量鑄造 3 個 NFT，然後轉移 tokenID 1」，或
- 「批量鑄造 5 個 NFT，然後轉移 tokenID 4」

從這些結果可以看出，轉移位於較大批次中間的 tokenID（例如 t1、t2）所需的成本，比轉移批次兩端的 tokenID（例如 t0、t4）要來得高。

請注意，這個簡單的實驗只追蹤了鑄造後單次轉移的成本。

### 降低批量鑄造 NFT 後轉移成本的變通方法

這裡有一個有趣的解法，可以將整批 NFT 轉移的總成本降到最低（原始來源為 William Entriken @fulldecent）：

1. 批量鑄造時，永遠鑄造允許的最大數量的 NFT。
1. 轉移時，先從編號為奇數的 token 開始，並依**升序**進行。
1. 之後再轉移編號為偶數的 token。

<ImageBlock
  src="https://media.alchemy.com/1704713646-making-subsequent-transfers-cheaper-to-execute.png"
  alt="讓後續轉帳的執行成本更低"
  width={1106}
  height={934}
  caption="讓後續轉帳的執行成本更低"
/>

這個策略之所以有效，是因為它強制填入了 `\_addressData` 的 mapping，使得後續的轉移執行成本更低。

### 使用 ERC721A 合約的 NFT 專案範例

以下是[目前正在使用 ERC721A 合約的專案清單](https://twitter.com/fulldecent/status/1491506123987431428?s=20&t=DZ-FrTtgF2gjSsPEv_1gZw)：

- @AzukiZen
- @cerealclubnft
- @TheLostGlitches
- @standardweb3
- @KittyCryptoGang
- @XRabbitsClub
- @WhaleTogether
- @pixelpiracynft
- @dastardlyducks
- @MissMetaNFT
- @StarcatchersNFT
- @LivesOfAsuna
- @richsadcatnft
- @themonkeypoly
- @womenofcrypto\_
- @TravelToucans
- @HuhuNFT

### 用於批量鑄造 NFT 的 ERC721A 替代方案

對於更願意嘗試新事物的人，也可以花點時間看看一個更_新_的 ERC721 標準優化方案，稱為 [ERC721Psi](https://medium.com/@medievaldao/erc721psi-a-truly-scalable-nft-standard-for-low-gas-on-chain-applications-and-randomized-metadata-c25c9e8ac8a8)：

<ImageBlock
  src="https://media.alchemy.com/1704713758-newer-optimization-of-the-erc721-standard-called-erc721psi.png"
  alt="ERC721 標準的新優化版本，稱為 ERC721Psi"
  width={1112}
  height={940}
  caption="ERC721 標準的新優化版本，稱為 ERC721Psi"
/>

我們不會在本文深入探討 ERC721Psi，但如果你感興趣，想進一步了解它的運作方式，歡迎在推特上私訊我 [@thatguyintech](https://twitter.com/thatguyintech)，我會另外寫一篇深入介紹的文章！

我們甚至可以進一步探索使用 Alchemy 部署一些範例專案。

### ERC721A 合約仍然算是 NFT 嗎？

簡短的答案是：**是的**，ERC721A 合約絕對是 NFT。

任何實作了 [ERC721 token 標準或 ERC1155](https://www.web3.university/article/comparing-erc-721-to-erc-1155) 介面的合約，都被視為 non-fungible token（不可替代代幣）或 semi-fungible token（半同質化代幣）。

ERC721A 是 ERC721 標準的一種延伸與優化。

ERC721Enumerable 和 ERC721Psi 也是如此。

它們都屬於 ERC721 家族！

### 如何銷毀（burn）ERC721A token

當你想要處理掉錢包中的某個 NFT 或 token，但不想把它送給其他人，也不想出售時，可以把它發送到一個沒有人使用的特定錢包地址，藉此銷毀它。

很多人喜歡使用相同的 burn 地址，因為它們容易記住。

例如，0 地址：

`0x0000000000000000000000000000000000000000`

然而，對於 ERC721A NFT 來說，**你不能把 token 轉移到 0 地址來銷毀 NFT**，因為批量鑄造中的大多數 token 預設就是對應到 0 地址。

選擇另一個地址來銷毀你的 ERC721A NFT 就沒問題了！

例如，另一個常見的 burn 地址是「0xdead」地址：`0x000000000000000000000000000000000000dEaD`

### 你會使用 ERC721A 合約來批量鑄造你的 NFT 嗎？

ERC721A 合約是一種強大的方式，能幫助你的社群節省 gas 成本，並透過批量鑄造 NFT，避免 Ethereum 網路出現不必要的壅塞。

歡迎告訴我們你正在打造什麼樣的 NFT 專案，以及我們能提供什麼協助！我們有各種工具能協助你部署、監控、通知，以及[行銷你的下一個 NFT collection](https://www.alchemy.com/amplify)。

別再猶豫，發推特給我們 [@Alchemy](https://x.com/Alchemy)，或是傳訊息來聊聊吧！
