# [ERC2309] 複数のNFTの作成や送付時に発行されるログの標準規格を理解しよう！

> 1つ以上の連続したトークンIDのERC721規格のNFTを発行、もしくは送付する標準化されたイベントを発行する。

- URL: https://cardene.dev/articles/f79a04d6b879178053d5
- 公開日: 2023-07-16
- 更新日: 2023-07-16
- トピック: Blockchain
- タグ: ethereum, solidity, ブロックチェーン, nft

## はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、1つ以上の連続したトークンIDのERC721規格のNFTを発行、もしくは送付する時に発行されるイベントを定義している、**ERC2309**についてまとめていきます！

:::message
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-2309

:::message
「**そもそもインターフェースって何？**」という方は以下の記事を参考にしてください！
:::

https://chaldene.net/erc721#st-toc-h-5

## 要約

1つ以上の連続したトークンIDのERC721規格のNFTを発行、もしくは送付する標準化されたイベントを発行する。

## 概要
1つ以上のERC721規格のNFTを発行、もしくは送付するかには触れず、実行された後に発行されるイベントについて定義されています。

## 動機
この機能拡張は、ERC721規格のスケーラビリティをさらに強化します。
1つのトランザクションで最大`2^256`のNFTを発行、送付、破棄することが可能です。
しかし、1つのトランザクションでその数の`Transfer`イベントを発生させることはできません。
`Transfer`イベントはERC721規格の中で以下のように述べています。

> NFTの所有権が変更されたときに発行します。このイベントは、NFTが発行されたとき（`from == 0`）と破棄されたとき（`to == 0`）に発行されます。コントラクトのデプロイ時には`trasfer`イベントは発行されません。

ERC721規格の中では`Transfer`イベントは1つのNFTに対して発生することが可能となり、これにより我々には`O(n)`の時間的複雑度をもたらします。
10億のNFTを効率的に1つのトランザクションで発行することは可能だが、ERC721規格に従って`Transfer`イベントを発生させるためには、ガスを使い果たすか、トランザクションのタイムアウト制限を超える1億のループが必要です。
これはERC721規格では実現できないですが、**ERC2309**ではその問題を解決できます。

多くの分散型マーケットプレイスやブロックエクスプローラーは、`Transfer`イベントを利用してアドレスが所有しているNFTを判断しています。
**ERC2309**は、プラットフォームなどが多数のNFTの所有権を判断するための標準的なメカニズムを提供します。

## 仕様
- ERC721規格のコントラクトは、**ERC2309**を実装して1つ以上のトークンIDが連続したNFTの発行、破棄、または送付時に発生する標準イベントを提供することができます。

- トランザクションを実行するアドレスは、`fromTokenId`と`toTokenId`の範囲内のすべてのNFTを所有しているか、権限を付与されたアドレスでなければならない。
- `fromTokenId`と`toTokenId`は、連続したトークンIDでなければならない。
- `fromTokenId`、`fromAddress`、`toAddress`はインデックス付きパラメータ（adress indexed ~）でなければならない。
    - `indexed`をつけることで、付与されたパラメータでフィルタリングすることができます。
- `toTokenId`はインデックス付きパラメータであってはいけない。
- NFTを発行するとき、`fromAddress`引数は`0x0`（ゼロアドレス）に設定しなければならない。
- NFTを破棄するとき、`toAddress`引数は`0x0`（ゼロアドレス）に設定しなければならない。
- `ConsecutiveTransfer`イベントを発行するとき、`Transfer`イベントは発行してはいけない。

## 実装コード

```javascript
  event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed fromAddress, address indexed toAddress);
```

## 実装例
`ConsecutiveTransfer`イベントは、単一のNFTと多数のNFTの両方に使用できます。

#### 単一NFTの作成

- `from`が0アドレス。

```javascript
emit ConsecutiveTransfer(1, 1, address(0), toAddress);
```

#### 複数NFTの作成

```javascript
emit ConsecutiveTransfer(1, 100000, address(0), toAddress);
```

#### 複数NFTの送付

```javascript
emit ConsecutiveTransfer(1, 100000, fromAddress, toAddress);
```

#### NFTの破棄

- `to`が0アドレス。

```javascript
emit ConsecutiveTransfer(1, 100000, from, address(0));
```

## 補足
`ConsecutiveTransfer`イベントの標準化により、新たなNFTの規格をサポートすることなく、大量のNFTの所有権を判定する分散プラットフォームの標準仕様が提供されます。
NFTのバッチ発行と送付の実装方法は複数あります。

`Consecutive Transfer Extension`は、コントラクトの作成者がNFTのバッチ発行、送付、破棄機能を自由に実装できるようにし、すべての実装において使用できる標準イベントを提供します。
連続したトークンIDを指定することで、最大2^(256)のNFTの発行や送付を簡単に実行でき、分散プラットフォームが対応できます。

<hr>
例えば、私が魔法の果実を販売しており、それぞれが異なる果実を持つ10,000本の魔法の果実の木を持つ農園を経営しているとします。
数年ごとに1,000本の新しい木を追加します。
私は、各木をNFTに変え、人々が所有できるようにしたいと考えています。
私の木のNFTの一つを所有する人は、その木からの収穫の四半期ごとのパーセントを受け取ることになります。
しかし問題は、これらのNFTを1つ1つ発行し、送付する必要があるということです。
これには多くの時間とお金がかかり実現が困難です...。
<hr>

**ERC2309**を使用すれば、初めての10,000本の木のNFTを1回のトランザクションで発行できます。
バッチで追加の1,000本の木のNFTを迅速かつ安価に発行することができます。
その後、10,000本以上の木のNFTをすべて、販売と資金配布を追跡する特別なスマートコントラクトを使用して1回のトランザクションで送付できます。
これは全て規格に沿って実行できます。

#### NFTの発行、送付、破棄をカバーする単一イベントの補足

`ConsecutiveTransfer`イベントは、NFTの発行、送付、破棄のイベントをカバーするために使用できます。
`ConsecutiveTransfer`の提案を確認し、コントラクトがERC165標準を使用してERC721インターフェイスをサポートしていることか確認できます。

#### インデックス付きイベントパラメータ

Solidityのイベントでは、最大で3つのインデックス付きパラメータを使用できフィルタリングが可能です。
**ERC2309**では、`fromAddress`、`toAddress`、`fromTokenId`をインデックス付きパラメータとして設定します`toTokenId`はログのデータ部分から取得できます。
これは、要件によってはイベントを検索することがあるためです。
その後、`fromTokenId`を他の2つのインデックス付きパラメータと共に簡単に取得できます。

#### `ConsecutiveTransfer`が発行されたときに`Transfer`を発行しない理由

NFTの所有権を追跡するためにこれらのイベントを使用しているプラットフォームに対してバグや複雑なロジックを引き起こす可能性があります。
1つのNFTを送付するときは、元の`Transfer`イベントを発行することが許容されるが、同じトランザクション中に`ConsecutiveTransfer`イベントを発行するべきではなく、逆も同様です。

#### 2309と1155の比較

NFT市場が成長し続けるにつれて、スマートコントラクトのスケーラビリティも必要になります。
ユーザーは一度に大量のNFTを発行したり、大量のNFTを送付したり、所有権を追跡できる必要があります。
これは費用対効果の高い方法で、イーサリアムブロックチェーンの制約内で行う必要があります。
何百万ものNFTが発行されるとスケーラビリティのあるコントラクトが必要になります。

**ERC1155**はこれらの問題を解決するために作成されましたが、大量のユニークなNFTを費用対効果の高い方法で発行するという点では不十分です。
**ERC1155**では、何百ドル（あるいは何千ドル）もの費用がかかるか、ガスが不足するかのどちらかになります。
**ERC1155**は、多数の同じトークンIDのNFTを発行する場合にはうまく機能するが、多数のユニークなNFTを発行する場合には不十分です。
**ERC2309**を使用すれば、大量のNFTを前もって発行し、それぞれのメタデータを費用対効果の高い方法で更新することができます。

:::message
**ERC1155**については以下の記事を参考にしてください。
:::

https://chaldene.net/erc1155

## 最後に

今回は「1つ以上の連続したトークンIDのERC721規格のNFTを発行、もしくは送付する時に発行されるイベントを定義している**ERC2309**」についてまとめてきました！
いかがだったでしょうか？

実装については今後追記していきます。

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

## 採用強化中！

CryptoGamesでは一緒に働く仲間を大募集中です。

https://www.wantedly.com/companies/cryptogames

この記事で書いた自分の経験からもわかるように、裁量権を持って働くことができて一気に成長できる環境です。
「ブロックチェーンやWeb3、NFTに興味がある」、「スマートコントラクトの開発に携わりたい」など、少しでも興味を持っている方はまずはお話ししましょう！
