# ERC 1155 のモヤッている部分を調べてみた **Published by:** [蒼い惑星](https://paragraph.com/@blueplanet42/) **Published on:** 2022-11-30 **URL:** https://paragraph.com/@blueplanet42/erc-1155 ## Content 複数トークン規格と言われている ERC 1155 ですが、下記部分はモヤっていたので調べてみました。マルチトークンの扱い方NFT と FT はどう区別されるかERC 1155 の基本規格詳細は下記 EIP ページ参照 https://eips.ethereum.org/EIPS/eip-1155 openzeppelin の実装はこちら https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC1155/ERC1155.sol 保持しているデータは下記 2 種類になっています。// Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; _balances の token ID の値は、コントラクトアドレス + ERC 721 の index のような役割になりますトークンを表す際に、ERC 20 の場合、コントラクトアドレスのみでしたが、ERC 721 の場合は、コントラクトアドレスと index の2階層になっていますなので、ERC 1155 はマルチトークンをサポートするなら少なくとも2階層の構造が必要ですが、その2階層をこの1つの id で表すように設けられています例をあげましょうアカウントA 0xa…1 が下記のようにトークンを持っているとします。GameToken ERC20:99 枚SwordNFT ERC721 #2SwordNFT ERC721 #5ShieldNFT ERC721 #1これらのトークンが全部 ERC 1155 で管理しているなら、各 id の値は下記の形で表すことができます{ "0000000100000000": { "0xa...1": 99 }, "1000000100000002": { "0xa...1": 1 }, "1000000100000005": { "0xa...1": 1 }, "1000000200000001": { "0xa...1": 1 }, } つまり、256 ビットの id を分割して前半の 128 ビット(16 進数の場合 8 桁)で トークン の id を表す後半の 128 ビット(16 進数の場合 8 桁)で index を表すERC20 タイプの場合 index 使わないため、全部 0 を指定していますただ、ややこしいのは、このやり方は、EIP 1155 規約の最後の `Usage` 節に例として記載され、 The standard does NOT mandate how an implementation must do this. となって、必須の実装ではありません調査結果1. マルチトークンの扱い方 については、上記通りでした2. NFT と FT はどう区別されるか は、意外な結果ですが、EIP 1155 標準のインファフェースでは、区別できませんERC 20 / ERC 721 と異なる部分ownerOf 関数がないERC 721 に _owners mapping があるので上記関数で調べられますが、ERC 1155 の場合そもそもこの mapping がないし、関数もありませんname / symbol もないEIP 1155 の Metadata Choices節にかかれてありますが、意図的にこの2つの関数を削除したようですsymbol は通貨取引以外であんまり使われてないので、一般的に有用なデータではない、かつ、衝突の可能性があるため、削除されましたnameは、メタデータで表せばよいので、重複を減らすため削除されましたまた、メタデータにすることで、ローカライズも可能になりますmint と転送系のメソッド(safeTransferFrom / safeBatchTransferFrom) に _data というパラメータがありますこのパラメータは、コントラクトの処理中には使われていませんEIP には 転送するために送信者によって提供された情報を変更せずに受信者にそのまま転送するように実装する必要がありますと書かれてありますよって、コントラクトの動作確認などの場合は、その値を無視して問題ございませんちなみに、remix などで動作確認する場合は、0x0を入力すればチェックを通れますERC 1155 コントラクトで定義しているトークンであれば、複数の転送を一括で1つのトランザクションで処理できます上の例では、SwordNFT#2とShieldNFT#1 とアカウトBに転送したい、その2つの NFT は ERC 721 である場合、2つの NFT コントラクトの転送関数を別々呼び出して2つのトランザクションになりますが、ERC 1155 で定義されている場合、下記のように一括転送関数を1回の呼び出しで完結しますsafeBatchTransferFrom( '0xa...1', // from '0xb...2', // to [1000000100000002, 1000000200000001], // token ids [1,1], // token amount "" // オプションデータ ) これこそが複数トークンを扱う一番のメリットじゃないかと思われますねまとめERC 1155 1つのコントラクトで複数のトークンを扱うことは確かにできますが、インタフェースは、ERC 20 と ERC 721 と異なっているため、互換性はないようにみえます。 特に、FT / NFT を1つのコントラクトで管理できるのに、区別するインタフェースが設けられていないのは意外でした。 また、1つの idで複数トークンを表現するのは、gas 節約する目的があるのは理解できていますが、ルールが決められていないところも結構意外でした。結局このルールは、コントラクトを実装する際だけではなく、コントラクトを利用する側もそのルールを把握して使う必要があるので、若干使いにくいと感じられますね。 ## Publication Information - [蒼い惑星](https://paragraph.com/@blueplanet42/): Publication homepage - [All Posts](https://paragraph.com/@blueplanet42/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@blueplanet42): Subscribe to updates - [Twitter](https://twitter.com/blueplanet42): Follow on Twitter