[EIP5679] ERC20, ERC721, ERC1155のMintとBurnの実装を統一しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、**EIP20**や**EIP721**、**EIP1155**などのトークンを生成したり、破棄したりする際の実装を統一する提案をしている**EIP5679**についてまとめていきます！

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

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

# 動機
**EIP20**や**EIP721**、**EIP1155**などのトークンの`Mint`（生成）と`Burn`（破棄）はよく実行されます。
トークンの`Mint`（生成）と`Burn`（破棄）の実行を統一した方法で行いベースとなるライフサイクルを提案します。

**EIP721**や**EIP1155**のいくつかの実装では、送付（Transfer）関数などを使用してトークンを`Mint`（生成）と`Burn`（破棄）できます。
ただし、トークンの`Mint`（生成）と`Burn`（破棄）はトークンの供給量を変更します。

:::note info
**Mint（生成）** → トークンの供給量が増える。
**Burn（破棄）** → トークンの供給量が減る。
:::

また、`Mint`（生成）と`Burn`（破棄）のアクセス制御は通常、送付（Transfer）関数とは異なる方法で実装されます。
そのため、統一された標準的な実装を提案して`Mint`（生成）と`Burn`（破棄）を行うことで、実装を簡素化し、セキュリティエラーを減らすことができます。

# 仕様

## EIP20

この提案による、**EIP20**に準拠したコントラクトを実装する際は以下のインターフェースを実装する必要があります。

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

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

```javascript
interface IERC5679Ext20 {
   function mint(address _to, uint256 _amount, bytes calldata _data) external;
   function burn(address _from, uint256 _amount, bytes calldata _data) external;
}
```

## EIP721

この提案による、**EIP721**に準拠したコントラクトを実装する際は以下のインターフェースを実装する必要があります。

```javascript
interface IERC5679Ext721 {
   function safeMint(address _to, uint256 _id, bytes calldata _data) external;
   function burn(address _from, uint256 _id, bytes calldata _data) external;
}
```

## EIP1155

この提案による、**EIP1155**に準拠したコントラクトを実装する際は以下のインターフェースを実装する必要があります。

```javascript
interface IERC5679Ext1155 {
   function safeMint(address _to, uint256 _id, uint256 _amount, bytes calldata _data) external;
   function safeMintBatch(address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
   function burn(address _from, uint256 _id, uint256 _amount, bytes[] calldata _data) external;
   function burnBatch(address _from, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata _data) external;
}
```

## 仕様の補足

- トークンの`Mint`（生成）

トークンが`Mint`（生成）される際、**EIP20**か**EIP1155**の場合は`_amount`で指定されたトークン、**EIP721**か**EIP1155**の場合は`_id`で指定されたトークンが`0x0`（0アドレス）からトークンの受け取りてのアドレス（`_to`で指定）に送付（`Transfer`）されたのち`Transfer Event`を発行する必要があります。
`totalSupply`（総供給量）は`Mint`（生成）されたトークン数に応じて増加させます。

- トークンの`Burn`（破棄）

トークンが`Burn`（破棄）される際、**EIP20**か**EIP1155**の場合は`_amount`で指定されたトークン、**EIP721**か**EIP1155**の場合は`_id`で指定されたトークンがトークンの受け取りてのアドレス（`_to`で指定）から`0x0`（0アドレス）に送付（`Transfer`）されたのち`Transfer Event`を発行する必要があります。
`totalSupply`（総供給量）は`Mint`（生成）されたトークン数に応じて減少させます。

- トークンの`safeMint`（生成）

`safeMint`は、**EIP721**や**EIP1155**で定義されている`safeTransferFrom`と同じ受け取りアドレスのチェックを実装する必要があります。

:::note info
ここでのチェックとは、受け取りてのアドレスがコントラクトの場合に**EIP721**や**EIP1155**に対応しているかです。
:::

- EIP165対応

上記を実装するにあたり、EIP165の実装が推奨されます。
実装としては以下のように、**ERC5679**が対応されているかチェックできるようにします。

```javascript
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
}
```

# 補足

- インターフェースは統一しない
**EIP1155**と同じく、**EIP20**や**EIP721**、**EIP1155**のいずれであっても`_amount`を常に引数にとるようなインターフェースにすることも可能です。
しかし、各EIPトークンは、元のトークンに実装されている`_id`と`_amount`に従って、インターフェースを定義しています。

:::note info
**EIP721**規格では、`Mint`（生成）量が`1`となっているため、`_amount`は引数に定義されていません。
:::

- Eventは既存のトークンの機能を使用
新しいイベントを作成せずに、既存の**EIP20**や**EIP721**内の`Transfer Evenet`を使用しています。
これは、**EIP20**や**EIP721**、**EIP1155**との互換性を持たせるためです。

- EIP1155の機能の追加
**EIP1155**には`safeMintBatch`および`burnBatch`メソッドを追加することを選択しましたが、**EIP721**の方には追加されていません。
これは、**EIP721**の提案に従ったためです。

**EIP777**には拡張を追加していません。
理由としては、**EIP777**は既に`Minting`と`Burning`が実装されているためです。

# 後方互換性
このEIPは、それぞれ**EIP20**や**EIP721**、**EIP1155**と互換性があるように設計されています。

# セキュリティ
**EIP20**や**EIP721**、**EIP1155**などのコントラクトでは、新しいトークンを`Mint`（生成）できる権限のアクセス制御を注意深く設計する必要があります。
設計にミスがあると、不正にトークンを`Mint`（生成）して`totalSupply`（総供給量）の増加が引き起こされる可能性があります。

`Burn`（破棄）についても、アクセス制御を注意深く設計する必要があります。

通常、以下の2つのロールだけがトークンを`Burn`（破棄）する権限を持ちます。

- トークン所有者。
- コントラクト内の特権を持つアドレス。

# 最後に

今回は「**EIP20**や**EIP721**、**EIP1155**などのトークンを生成したり、破棄したりする際の実装を統一する提案をしている**EIP5679**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

# 採用強化中！

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

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

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