---
title: "ERC721 vs. ERC721A：批量铸造 NFT"
description: "Azuki 团队创建的 ERC721 标准的替代实现，可用于优化批量铸造 NFT。"
---

# ERC721 vs. ERC721A：批量铸造 NFT

许多 NFT 创作者都知道，[在 Ethereum 主网上部署智能合约](https://www.alchemy.com/overviews/nft-deployment-cost)可能非常昂贵。

然而，智能合约部署成本并不是区块链工程师和 NFT 团队唯一需要考虑的成本。[打造一个成功的 NFT 系列](https://www.alchemy.com/overviews/how-to-create-a-successful-nft-project)或头像收藏品项目，需要建立社区，并让用户能够轻松地**铸造**、**交易**和**使用**他们的 NFT。

让我们来了解一种强大的 NFT 智能合约优化方案，它能帮助你的社区在 NFT 铸造成本上节省 gas 费：

在 ERC721A 合约中实现批量铸造！

### 什么是 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 合约铸造一个代币的价格，用户改用 ERC721A 合约却可以铸造多达 5 个代币（甚至可能更多）。

谁不想让用户在铸造上节省高达 80% 的成本呢？

更妙的是：

不仅单笔交易的 NFT 铸造价格会变得更便宜，在热门系列发售期间，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)

接着，我分别调用了每个合约的铸造函数，并记录了每笔交易的 gas 消耗。

以下是我的结果：

你可以在这个 GitHub 仓库中找到这些测试的代码：[demo-erc721a](https://github.com/thatguyintech/demo-erc721a)

这里铸造多个 NFT 的 gas 成本与 Azuki 博客文章中展示的数据略有不同，但两者非常接近，从铸造一个、两个到铸造多个的 gas 费增长趋势是一致的。

我们已经验证了批量铸造 NFT 的 gas 节省效果！✅

### ERC721A 智能合约是如何通过批量铸造节省 gas 费的？

ERC721A 的合约设计基于以下几个假设：

1. **代币 ID 应始终从 0 开始连续递增**。大多数 NFT 项目本身就是这样做的，Azuki 也在其假设中明确说明了这一点。
1. **降低铸造 NFT 的 gas 成本比优化其他任何 ERC721 调用都更重要**。铸造是 Ethereum 网络发生拥堵的时刻，也是用户对 NFT 系列的第一印象。铸造越顺畅，口碑越好。

基于这些假设，ERC721A 做了以下合约优化：

1. **减少代币元数据的存储浪费**。
1. **将所有权状态更新限制为每批铸造仅更新一次**，而不是每铸造一个 NFT 就更新一次。

我们将了解这些优化是如何实现的，但在此之前，需要先理解哪种交易消耗的 gas 费最多。

### 减少发送写交易所需的工作量可以为用户节省 gas

区块链上的交易大致分为两种：写交易和读交易。

**写交易**发生在我们修改或更新区块链状态时（例如转账、写留言、交易 NFT）。

**读交易**发生在我们请求查看现有数据时。

用户**为写函数支付的 gas 费始终高于读函数**。

因此，通过减少写交易的数量，或者减少发送写交易所需的工作量——即使这意味着之后读取数据要花费更多工作量——都可以降低用户支付的 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 合约只需要设置两次所有权元数据：一次是 Alice 那一批，一次是 Bob 那一批。

不过，这也意味着，当转移一个没有显式设置所有者地址的 tokenID 时，合约必须遍历所有 tokenID，直到找到第一个具有显式所有者地址的 NFT，以确定谁有权转移它，然后再设置新的所有者——这样为了维持正确的分组，就需要不止一次地修改所有权状态。

这里有一个测试，用来[模拟转移场景并记录 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. 转移时，先按**升序**转移**奇数编号**的代币。
1. 之后，再转移**偶数编号**的代币。

<ImageBlock
  src="https://media.alchemy.com/1704713646-making-subsequent-transfers-cheaper-to-execute.png"
  alt="让后续转账执行成本更低"
  width={1106}
  height={934}
  caption="让后续转账执行成本更低"
/>

这个策略之所以有效，是因为它强制填充了 `\_addressData` 映射，使后续转移的执行成本更低。

### 使用 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 代币标准或 ERC1155](https://www.web3.university/article/comparing-erc-721-to-erc-1155) 接口的合约都被视为非同质化代币或半同质化代币。

ERC721A 是 ERC721 标准的一种扩展和优化。

ERC721Enumerable 和 ERC721Psi 也是如此。

它们都属于 ERC721 家族！

### 如何销毁 ERC721A 代币

当你想丢弃钱包里的一个 NFT 或代币，但既不想转给别人，也不想出售它时，可以将它发送到一个没有人使用的特定钱包地址，以此销毁它。

很多人喜欢使用相同的销毁地址，因为它们容易记住。

例如，0 地址：

`0x0000000000000000000000000000000000000000`

不过，对于 ERC721A NFT，**你不能通过将代币转移到 0 地址来销毁 NFT**，因为一批中铸造的大多数代币默认都映射到 0 地址。

选择另一个地址来销毁你的 ERC721A NFT 就可以了！

例如，另一个常用的销毁地址是 "0xdead" 地址：`0x000000000000000000000000000000000000dEaD`

### 你会使用 ERC721A 合约来批量铸造你的 NFT 吗？

ERC721A 合约是一种强大的方式，可以通过批量铸造 NFT 为社区节省 gas 成本，并避免给 Ethereum 网络带来不必要的拥堵。

告诉我们你正在构建什么样的 NFT 项目，以及我们能提供什么帮助！我们有工具可以帮你部署、监控、通知，以及[推广你的下一个 NFT 系列](https://www.alchemy.com/amplify)。

不要犹豫，发推特给我们 [@Alchemy](https://x.com/Alchemy)，或者发私信聊聊吧！
