🫥

ERC6551(Token Bound Accounts)とは何か?

2023/11/04に公開

ERC6551のコンセプト

NFTがオンチェーン資産(NFTやFT)を保有することができる。

ERC6551のコンセプトイメージ

ブロックチェーンにおけるID(DID)を、walletではなく、NFTにするべきである。
つまり、walletがNFTを保有する構造ではなく、NFTがwalletを保有する構造になっている。

ERC6551の技術的な構造

EIP6551の提案には以下のような図解があります。

それを元に自分の理解のイメージ図を以下にまとめてました。

主な登場人物は4人です。

①NFT

ERC6551はERC721AのようなERC721を継承した別テンプレートではなく、ERC721に対して後から拡張可能な、装備品のようなイメージだと考えています。そのため、現状存在する全てのERC721に対して、ERC6551を装備(拡張)することができます。

②Proxy Contract(Token Bound Accounts)

Proxy ContractというのはTBAのアカウントだけを持つ、最小限のスマートコントラクトです。ほとんどの実装部分は、Implement Contract側が担うことで、TBAの発行コストを最小限にしています。

③Implement Contract

Implement Contractというのは、TBA(Token Bound Accounts)における実行部分のコントラクトである。基本的にはここの部分がERC6551における自由部分であり、それぞれのERC721においてカスタマイズできる部分です。

④Registry

NFTからProxy Contractを紐付け、Proxy ContractとImplement Contractを紐づけるコントラクトです。ユーザーはTBAを作りたいNFTの情報を、Registerに入力することで、TBAを作成することができます。

実際に触ってみる

実際に「ERC6551を作成して触ってみたい!」という人は、ユウキさんのnoteがわかりやすく解説してあるのでおすすめです。
https://note.com/standenglish/n/n0673681c3bce

上記のnoteと以下のgithubを参考にして、コードを確認していきます。
https://github.com/kk-im/tba-tutorial-pinata

Registry

import "@openzeppelin/contracts/utils/Create2.sol";
import "./interfaces/IERC6551Registry.sol";

contract ERC6551Registry is IERC6551Registry {
    error InitializationFailed();

    function createAccount(
        address implementation,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId,
        uint256 salt,
        bytes calldata initData
    ) external returns (address) {
	// ...
    }
 
    function account(
        address implementation,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId,
        uint256 salt
    ) external view returns (address) {
	// ...
    }
}

implamentationが少しわかりづらいですが、実際の実行コントラクトのアドレスになります。

Implement Contract

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";

import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "./interfaces/IERC6551Account.sol";

import "./lib/MinimalReceiver.sol";
import "./lib/ERC6551AccountLib.sol";

contract ERC6551Account is IERC165, IERC1271, IERC6551Account {
    uint256 public nonce;

    receive() external payable {}

    function executeCall(
        address to,
        uint256 value,
        bytes calldata data
    ) external payable returns (bytes memory result) {
	// ...
    }

    function token()
        external
        view
        returns (
            uint256,
            address,
            uint256
        )
    {
        return ERC6551AccountLib.token();
    }

    function owner() public view returns (address) {
	// 所有者のアドレスを返す
    }

    function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
        return (interfaceId == type(IERC165).interfaceId ||
            interfaceId == type(IERC6551Account).interfaceId);
    }

    function isValidSignature(bytes32 hash, bytes memory signature)
        external
        view
        returns (bytes4 magicValue)
    {
	// そのユーザーが署名可能かを返す
    }
}

全体感

ERC721が普及してきたことで、ERC6551のようなERC721を前提に装備(拡張)するような規格が生まれてきたと感じる。ただし、誰でも比較的自由に拡張することができるため、画面としてどのように見えるようにするのかは難しいと感じる。ちなみにOpenseaはこんな感じ。

左のNFT画像の左上に新たなアイコンが表示される


TBAに入っているアセットが一覧で表示される

Discussion