---
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コレクション](https://www.alchemy.com/overviews/how-to-create-a-successful-nft-project)やコレクティブルアバタープロジェクトを作るには、コミュニティを構築し、ユーザーがNFTを**ミント**、**取引**、**利用**しやすくすることも含まれます。

ここでは、コミュニティがNFTのミントコストのガス代を節約できる、強力なNFTスマートコントラクトの最適化手法について見ていきましょう。

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="ERC721A実装を紹介するAzukiチーム"
  width={1108}
  height={938}
  caption="ERC721A実装を紹介するAzukiチーム"
/>

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)を使ってバッチミントした場合とで、どれだけガス代が節約できるかの試算を示しています。

<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で使用されるガス量が、はるかに小さい一定の割合でしか増えないことを示しています。

NFTをミントする際のガス代の増加は次のとおりです。

- Azuki ERC721Aコントラクトを使う場合：**追加ミント1件あたり約2kガス**
- [OpenZeppelin](https://www.alchemy.com/dapps/openzeppelin)のERC721Enumerableコントラクトを使う場合：**追加ミント1件あたり約115kガス**

この結果は実に**驚異的**です。

ERC721Enumerableコントラクトでトークン1個をミントするのにかかる代金で、ERC721Aコントラクトなら最大5個（あるいはそれ以上）のトークンをミントできることになります。

ユーザーがミント代を最大80%節約できるとしたら、それを望まない人はいないでしょう。

さらに良い点があります。

個々の取引においてNFTのミント価格が下がるだけでなく、人気コレクションのドロップ時にEthereumネットワークに影響を与える**ネットワーク混雑**や**ガス価格の急騰**も抑えられます。

なかなか興味深い話です。

### 複数NFTミント時のガス削減効果を検証する

自分でも実際に確認したかったので、[NFTを作成する](https://www.alchemy.com/docs/how-to-interact-with-erc-721-tokens-in-solidity)基本的なNFTコントラクトを2つ実装しました。

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)

次に、それぞれのミント関数を呼び出し、各トランザクションのガス代を記録しました。

結果は以下の通りです。

これらのテストのコードは、GitHubリポジトリ[demo-erc721a](https://github.com/thatguyintech/demo-erc721a)から確認できます。

ここで示された複数NFTのミントにかかるガス代は、Azukiのブログ記事に示されている数値とはやや異なりますが、近い値であり、1件・2件・複数件とミント数が増えるにつれてガス代が増加するという傾向は一致しています。

バッチミントによるNFTのガス削減効果が検証できました。✅

### ERC721Aスマートコントラクトはバッチミントでどのようにガス代を節約しているのか

ERC721Aは、コントラクト設計に影響を与えるいくつかの前提を置いています。

1. **トークンIDは常に0から連番で増加する**ことです。ほとんどのNFTプロジェクトはすでにこの方式を採用しており、Azukiもこの前提を明示しています。
1. **NFTのミントにかかるガス代の削減を、他のERC721呼び出しの最適化よりも優先する**ことです。ミント時にEthereumネットワークの混雑が発生しますし、ミントはユーザーがNFTコレクションに対して抱く最初の印象でもあります。ミントが簡単であるほど、評判は良くなります。

これらの前提のもと、ERC721Aは次のようなコントラクトの最適化を行っています。

1. **トークンメタデータの無駄な保存を削減する**
1. **所有権状態の更新を、ミントされたNFT1個ごとではなく、バッチミント1回ごとに限定する**

これらの最適化がどのように行われているかを見ていく前に、どのようなトランザクションが最もガス代がかかるのかを理解しておく必要があります。

### 書き込みトランザクションの処理量を減らすことでガス代を節約できる

ブロックチェーン上のトランザクションは、大きく分けて書き込みと読み込みの2種類があります。

**書き込み**は、ブロックチェーンの状態を変更・更新するとき（例：送金、メッセージの書き込み、NFTの取引）に発生します。

**読み込み**は、既存のデータを取得して参照するときに発生します。

ユーザーは**読み込み関数よりも書き込み関数の方に常に多くのガス代を支払います**。

したがって、書き込みトランザクションの回数を減らすか、書き込みトランザクションに必要な処理量を減らせば、たとえ後で読み込みトランザクションの処理量が増えたとしても、ユーザーが支払う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のバッチについて1回、Bobのバッチについて1回の、計2回だけです。

ただし、これは明示的な所有者アドレスが設定されていないtokenIDを転送する場合、コントラクトが明示的な所有者アドレスを持つ最初のNFTに到達するまで全tokenIDに対してループを実行し、転送権限を持つ所有者を見つけたうえで新しい所有者を設定する必要があることを意味します。つまり、正しいグループ分けを維持するために、所有権状態を複数回変更することになります。

以下は[転送シナリオをシミュレートしてガス代を記録するテスト](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軸の順に見ていきます。例えば、

- 「NFTを1個バッチミントしてから、tokenID 0を転送する」
- 「NFTを3個バッチミントしてから、tokenID 1を転送する」
- 「NFTを5個バッチミントしてから、tokenID 4を転送する」

といった具合です。

この結果から、大きなミントバッチの途中にあるtokenID（t1、t2など）を転送する方が、バッチの端にあるtokenID（t0、t4など）を転送するよりもコストがかかることがわかります。

なお、この簡単な実験ではミント後の単一転送のコストのみを追跡しています。

### バッチミント後の転送コストを抑える回避策

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

### バッチミント向けの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)のインターフェースを実装しているコントラクトは、非代替性トークン（NFT）または準代替性トークンとみなされます。

ERC721Aは、ERC721規格の拡張・最適化版です。

これはERC721EnumerableやERC721Psiについても同様です。

これらはすべてERC721ファミリーの一部です。

### ERC721Aトークンをバーンする方法

ウォレット内のNFTやトークンを処分したいが、他の人に譲るつもりも、売るつもりもない場合は、誰も使用していない特定のウォレットアドレスに送ることでバーン（焼却）できます。

多くの人は覚えやすいため、同じバーンアドレスを使いたがります。

例えば、0アドレスです。

`0x0000000000000000000000000000000000000000`

ただし、ERC721A NFTの場合、**0アドレスに転送してNFTをバーンすることはできません**。バッチでミントされたトークンの大半は、デフォルトで0アドレスにマッピングされているためです。

ERC721A NFTをバーンする際は、別のアドレスを選んでください。それで問題ありません。

例えば、よく使われる別のバーンアドレスとして「0xdead」アドレスがあります。`0x000000000000000000000000000000000000dEaD`

### ERC721AコントラクトでNFTをバッチミントしますか？

ERC721Aコントラクトは、NFTをバッチミントすることで、コミュニティのガス代を節約し、Ethereumネットワークの不要な混雑を防ぐ強力な手段です。

どのようなNFTプロジェクトを構築しているか、そして私たちがどのようにお手伝いできるか、ぜひ教えてください。デプロイ、モニタリング、通知、そして[次のNFTコレクションのマーケティング](https://www.alchemy.com/amplify)をサポートするツールを用意しています。

お待ちしています。[@Alchemy](https://x.com/Alchemy)にツイートするか、DMを送ってお気軽にお話しください。
