はじめに

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

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

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

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

動機

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

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

Mint(生成) → トークンの供給量が増える。 Burn(破棄) → トークンの供給量が減る。

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

仕様

EIP20

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

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

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と同じ受け取りアドレスのチェックを実装する必要があります。

ここでのチェックとは、受け取りてのアドレスがコントラクトの場合に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に従って、インターフェースを定義しています。

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などからお気軽に質問してください!

採用強化中!

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

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