2025.04.08
マルチトークン規格ERC6909
こんにちは。次世代システム研究室のT.M です。
はじめに
ERC6909 は、従来のERC1155 などが抱えていた複雑さやガスコストの問題を解決するために登場した、新しいマルチトークンです。本記事では、ERC1155 と比較することでERC6909 の特徴を解説します。
ERC1155
複数種類のトークンを単一のコントラクトで管理できるマルチトークンです。ゲームなど複数のトークンを用いるサービスでは、個別にコントラクトのデプロイが不要になることで、開発・運用が効率化されます。また、複数トークンを同時に送信することで、ガスコストを節約することができます。他にも、セーフトランスファー機能により、安全に送金をすることができます。
一方、インターフェースが複雑なため、実装が複雑になりがちであり、セーフトランスファー機能の不要なコールバックにより無駄なガスコストが発生することがあります。
ERC6909
ERC1155などの従来のトークンが抱えていた複雑さやガスコストの問題を解消したマルチトークンです。2023年4月にEIPに提案され、2024年9月にレビューになりました。特徴として、インターフェースがシンプルになり、不要な外部呼び出しを廃止しました。
ERC6909とERC1155との比較
ERC1155 のインターフェースは以下です。トークンを転送する関数として、safeTransferFrom、safeBatchTransferFrom があります。権限委譲をする関数として、setApprovalForAll があります。
function balanceOf(address account, uint256 id) external view returns (uint256); function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); function setApprovalForAll(address operator, bool approved) external; function isApprovedForAll(address account, address operator) external view returns (bool); function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external;
ERC6909 には、トークンを転送する関数として、transfer、transferFrom という関数があります。権限委譲をする関数として、approve、setOperator があります。
function balanceOf(address owner, uint256 id) external view returns (uint256); function allowance(address owner, address spender, uint256 id) external view returns (uint256); function isOperator(address owner, address spender) external view returns (bool); function approve(address spender, uint256 id, uint256 amount) external returns (bool); function setOperator(address spender, bool approved) external returns (bool); function transfer(address receiver, uint256 id, uint256 amount) external returns (bool); function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool);
ERC1155 では、safeBatchTransferFrom という複数のトークンを転送するための関数がありますが、ERC6909 にはありません。複数のトークンを転送する関数は複雑な実装になるため、その関数がないERC6909 は実装がシンプルになります。
function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { ... uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; unchecked { ++i; } } ... }
ERC1155 では、safeTransferFrom、safeBatchTransferFrom により、転送先のコントラクトが正しく受信できるかをチェックしていますが、ERC6909 のtransfer、transferFrom にはチェックがありません。チェックをするためには、転送処理中に転送先コントラクトのコールバックを実行する必要があります。この処理にガスコストがかかります。
function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function transfer( address receiver, uint256 id, uint256 amount ) public virtual returns (bool) { balanceOf[msg.sender][id] -= amount; balanceOf[receiver][id] += amount; emit Transfer(msg.sender, msg.sender, receiver, id, amount); return true; }
ERC1155では、setApprovalForAll によって権限を委譲するが、この関数は全ての所持トークンに関する権限を委譲することになります。一方、ERC6909 では、approve によって細かくトークンごとに権限を委譲することができます。
さいごに
ERC1155 と比較することでERC6909 についての特徴を解説しました。ERC6909 はシンプルで不要なガスコストが掛からない、という利点のあるマルチトークンです。Uniswap でも利用されており、取引の多いところで特徴が発揮するトークンです。今後、さまざまなサービスで利用されると考えられるトークンですので、注目を続けたいと思います。
次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。インフラ設計、構築経験者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。
皆さんのご応募をお待ちしています。
参考
https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master
https://github.com/transmissions11/solmate/tree/main
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD