ERC6551(トークンバウンドアカウント)を学ぼう!
こんにちは、CryptoGamesのユウキと申します。
本日はERC6551(トークンバウンドアカウント)について、学んでいこうと思います。
0 はじめに
この記事の内容は、こちらのEIP-6551をもとにしています。
また、現在のステータスは「Draft」であり、「Final」ではないことにもご注意ください。
その他、こちらが翻訳を行った記事です。
1 概要
本日は、ERC6551のトークンバウンドアカウント(TBA)について見てみましょう。
大まかな内容としては、下の絵の通りです。
あるトークン(NFT)にアカウントが紐づいています。
これによって、何が変わるのでしょうか?
ERC721の現状などから考えてみましょう。
2 ERC721の現状について
1 現在の所有者の特定
たとえば、AコントラクトのトークンID:1の所有者にエアドロをしたいと思います。
でも、現在の所有者が本当にCさんかが心配です。
この瞬間に売られるかもしれませんね。
このエアドロがトークンID:1だけならまだしも、たくさんの人(たとえば1万人)に配るとなると、ちょっと大変そうですね。
2 エアドロ後の所有権の移動
他にも、たとえば、正しくBさんにエアドロしたものの、その直後にCさんに売ってしまったとします。
現在、持っているのはCさんですが、Cさんはエアドロのメリットを享受できません。
現在所有しているCさんにメリットがいかないのは、ちょっと悲しいですね。
3 NFTに付属するアイテム
他にも、ゲームのアイテムのようなものを考えてみましょう。
通常のNFTでは、特定のコントラクトのトークンIDにアイテムを紐づけることはできません。
ちなみに、これなら一応できます。
NFTを所有しているAさんに色々と所持させる方法です。
ただ、これでは、所有権が移動したとき、やはりアイテムはAさんの手元に残ってしまいます。
先ほどと同じ課題が残ってしまいますね。
3 トークンバウンドアカウント(TBA)による解決
一方、このトークンIDにアカウントが紐付けば、それらの問題は解決します。
このアカウントにエアドロした場合、その所有者であれば、使用でき、所有者でなくなれば、使用できません。
そのため、タイミングを憂慮したり、エアドロ後に売られてしまうことを考える必要がありません。
これは、ゲーム内のアイテムでも同じですね。
ちなみに、ここまでのところが、下の部分の話です。
トークン(NFT)とアカウントが紐づいています。
4 所有者の特定について
では、このトークンバウンドアカウント(TBA)の所有者はどのように決まるのでしょうか。
それは、下のように決まります。
具体的には、下のように、「token関数」、「owner関数」が用いられます。
なお、イメージはこれで良いのですが、少し正確ではないので、その部分は次の章で修正されます。
ちなみに、実際のコードはこの辺りになりますが、今回は詳細は省きます。
ちなみに、ここまでが、下の部分の話です。
これで、トークン(NFT)の所有者と紐づけられました。
5 実装コントラクトについて
では、先ほどの、token関数やowner関数はどこに実装されているのでしょうか?
それが、下の実装コントラクトです。
そのため、実際にはこのような関係性になります。
ちなみに、この部分はIERC6551Accountとして規定されています。
関係図としましては、この辺りのアカウントと実装コントラクトの関係を扱いました。
6 レジストリコントラクトについて
1 概要
最後に、このトークンバウンドアカウントを誰が作ってくれるのかを見てみましょう。
それが、このレジストリコントラクトです。
2 レジストリコントラクトの構成
このコントラクトを見てみると2つの関数があります。
① createAccount
② account
つまりこんな感じですね。
そして、名前からも分かるように、この「createAccount」関数を使って、アカウントを作っています。
3 アカウント作成に必要なもの
では、次に、どのようにアカウントを作っているのかを見てみましょう。
下のようになります。
つまり、こんな状態です。
では、次に実際のコードをさらっと見てみましょう。
アカウントを作っているのは、四角の部分です。
つまり、作成時に「initData」は使いません。
つまりこんな状態ですね。
そして、たとえば、「AzukiコントラクトのトークンID:1に対するアカウントを作りたい」となった場合、青の四角は一意に決定します。
チェーンIDもMainnetの1ですね。
次に、実装アドレスですが、こちらが実装コントラクトでしたね。
なので、Aコントラクトを実装させたいのか、Bコントラクトを実装させたいのかによって、変わります。
ただ、実装させたいコントラクトが決まっているのであれば、ここは一意になります。
saltについては、一旦無視します。(ただ、後でやります。)
そして、実装したいコントラクトが変わるのであれば、アカウントは別のものになります。
それが下の箇所です。
4 Create2について
次に、アカウントを作成する箇所をもう一度見てみましょう。
「Create2」というオペコードが使われています。
こちらはコントラクトをデプロイする方法の一つです。
「決定論的」(deterministic)という重要な性質を持ちます。
これは、同じパラメータで実行すると、必ず同じコントラクトアドレスがデプロイされることを意味します。
つまり、実装させたいコントラクトアドレスが決まっていれば、必ず、決まったアドレスが作られます。
(今は、saltを無視しています。)
5 「決定論的」(deterministic)のメリットについて
では、このメリットを考えてみましょう。
アドレスがあらかじめわかれば、作成前にエアドロなどをすることも可能です。
(その時点ではコントラクトアカウントではなく、EOA(ウォレットアカウントのイメージ)です。)
ただ、この場合、何か条件を変えると、アドレスが変わってしまうため、慎重に行う必要があると思います。
6 saltについて
ここまでのところで、「実装アドレス」が一意であるならば、「決定論的」(deterministic)に作成されるアドレスは一意に決まりました。
ということは、このままでは、「実装アドレス」につき、一つのトークンバウンドアカウントしか作成できません。
これをいくつでも作成可能にするのが「salt(塩)」です。
「salt」は任意に値を変えることができます。
そのため、たとえ実装コントラクトが同じであっても、複数のトークンバウンドアカウントを作ることができます。
以上が、レジストリコントラクトの内容です。
7 最後に
以上で、全ての構成の説明が終わりました。
意外とシンプルだったのではないでしょうか。
EIP-6551にサンプルコードが載っていますので、ご興味のある方は、ぜひコントラクトを作ってみてください!
また、公式のセキュリティに関する考察も読んでいただけると幸いです。
以上です。
サポートをしていただけたらすごく嬉しいです😄 いただけたサポートを励みに、これからもコツコツ頑張っていきます😊