
ERC721-O:フルオンチェーンNFTの標準プロトコルおよび実装
TechFlow厳選深潮セレクト

ERC721-O:フルオンチェーンNFTの標準プロトコルおよび実装
Catddle NFTは、ERC721-Oを使用して開発された初のオールチェーンNFTとなる。
ERC721-Oは、Catddle NFTの開発チームであるCatddle Labが設計しました。Catddle NFTは、ERC721-Oを使って開発される最初の全チェーンNFTとなります。
*ERC721-Oは完全にオープンソースのプロジェクトです。ぜひGitHubでコントリビューションをお願いします!
概要
ERC721-OはERC721に基づく、全チェーンNFT(Non-Fungible Token)の標準プロトコルおよび実装です。
ERC721-Oプロトコルは、ウォレットや取引所などの第三者アプリケーションが、このプロトコルを実装したあらゆるNFTと統一的に検証・相互作用できるようにすることを目指しています。
ERC721-Oは複数のクロスチェーン機能を追加し、クロスチェーンにおけるセキュリティ課題に対する一連の解決策を提案しています。
背景
LayerZeroは、異なるブロックチェーン間でメッセージを転送するサービスを提供する新たなブロックチェーンインフラです。 LayerZeroの論文によると、このメッセージ転送サービスは有効な伝達を保証しています。受信側が有効な伝達サービスからメッセージmを受け取った場合、関連するトランザクションtが送信側のチェーン上で正常にコミットされていることが保証されます。
この汎用的なメッセージプロトコルにより、全チェーンNFTの実現が可能になりました。
ERC721-Oと既存の全チェーンNFT*との違い

ERC721-Oの改善点
より安全
・クロスチェーンガス保護メカニズム
非ブロッキングなどの一連のセキュリティ設計があるとはいえ、クロスチェーン時のガスリミット(destination gas limit)が低く設定されている場合、NFTが転送中に滞留する可能性があります。
これを回避するため、クロスチェーンガス保護メカニズムを導入しました。コントラクト所有者は適切な最小クロスチェーンガスリミットを設定することで、すべてのNFTが正常に転送され、ガス不足による失敗を防ぐことができます。他のクロスチェーン機能には影響しません。
・リモートアドレスの安全な設定
使用中の全チェーンNFTコントラクトを更新すると、資金が永久に失われる可能性があります。また、全チェーンNFTコントラクトを新規チェーンにデプロイする際、特定の関数呼び出し順序に従わないと、NFTが転送中にブロックされたり、永久に消失したりする恐れがあります。
これらの問題を解決するため、ERC721-Oは安全なリモートアドレス設定メカニズムを導入しています。この仕組みにより、コントラクト所有者はアップデートによる資金損失を避けられ、チェーン間の関数呼び出し順序を気にする必要がなくなります。
・サードパーティライブラリのバージョン固定
メッセージの送受信はLayerZeroライブラリに依存しています。LayerZeroがアップデートされた場合、サードパーティライブラリのバージョンを固定することで、アップグレードに伴う潜在的なエラーを回避できます。これはLayerZero公式が推奨するベストプラクティスでもあります。
・最後の手段としての機能保持
非ブロッキングやガス保護など複数のセキュリティ設計を導入しても、メッセージパスがブロックされ、再試行が不可能になる状況が発生する可能性があります。
forceResumeReceiveはそのような場合に使用できる最終手段であり、これを用いなければチェーン上のエラーが永久に滞留してしまう可能性があります。そのため、実装に最後の手段として残してあります。
追加機能
・第三者転送(承認)モードの提供
ERC20およびERC721では、第三者にトークンの転送を承認(Approve)する機能が提供されています。この機能を追加することで、サードパーティアプリケーションが全チェーンNFTとより円滑に相互作用できるようになります。
・自由なクロスチェーン転送先アドレス選択
ユーザーは、NFTを別のチェーン上の同一アドレスに転送するだけでなく、任意のアドレスに転送できるようになりました。
・NFT送信時にガスエアドロップを同時実行
ユーザーがNFTを別のチェーンに送信した後、それを使用するには、対象チェーン上のアドレスにネイティブガス(Ether、BNB、AVAXなど)を別途送る必要があります。この手順は煩雑です。
現在では、ガスのクロスチェーンエアドロップをNFT送信と同時に完了できるため、ターゲットチェーンでの追加操作が不要になります。
・トークンでのクロスチェーン手数料支払いを許可
LayerZeroが自社トークンをリリースした際、ユーザーは特定のトークン所有者を設定することで、クロスチェーン手数料をそのトークンで支払えるようになります。割引が適用されるかもしれません :)
より透明性が高い
・重要なデプロイ情報の公開
ERC721-Oプロトコルの設計では、送信ポートアドレス(endpoint)およびリモートコントラクトアドレス(remote)の公開が強制されています。これにより、ユーザーおよび第三者は、送信ポートアドレスがLayerZero公式のものか、リモートコントラクトアドレスが正しく設定されているかを確認できます。
このため、取引所やウォレットなどの第三者は、ERC721-Oトークンに対して簡単にチェック機構を実装でき、ユーザーの資金損失を防ぐことができます。
・重要なオンチェーン活動の開示
重要なオンチェーン活動が発生した際、イベントの発行により、ユーザーおよび第三者が即座に何が起きたかを把握できます。
ERC721-Oのインターフェース設計では、他チェーンへのNFT送信および受信時にイベントの発行が強制されています。これにより、ユーザーと第三者はオンチェーンで何が起きているかを明確に理解できます。
ERC721-Oの実装では、その他の重要な活動(例:一時停止、リモートコントラクトアドレスの設定)についてもイベントを発行し、重要な変更を通知します。
・Nonce追跡の許可
Nonceは、特定のアドレスから送信されたトランザクションの順番を表します。LayerZeroはNonce追跡機能を提供しており、ERC721-Oはこれをクロスチェーンイベントに組み込みます。イベントから得られる情報により、ユーザーおよび第三者は容易にソースチェーンとターゲットチェーンのトランザクションを照合できます。
ガス消費の削減
LayerZeroがユーザー向けにガス見積もりチェックを既に行っているため、メッセージ送信前のガス見積もりチェックは冗長です。ERC721-Oではこれを削除し、クロスチェーン時のガス消費を削減しています。
コードのオーバーライドと再利用が容易
すべての関数および変数は、オーバーライドおよび再利用が容易に設計されています。
基底クラスとして、virtual、override、internalが広く使用されており、開発者がコントラクトコードを継承する際に明確なヒントとガイドラインを提供するため、詳細なコメントも付いています。
セキュリティ設計の背後にある原理
LayerZero公式は優れた基本実装例を提供しています。また、Gh0stly Gh0stsのようなNFTは、クロスチェーンNFTの巨大な可能性をすべての人々に示しています。
しかし、全チェーントークンがさらに発展するには、いくつかの深刻なセキュリティ問題に対処し解決しなければなりません。これらの問題を解決するため、ERC721-Oは一連の独自のセキュリティ設計を導入しています。
具体的な設計に入る前に、重要な概念を紹介します:クロスチェーンメッセージブロッキングです。クロスチェーンメッセージブロッキングとは、ソースコントラクトからターゲットチェーンへメッセージが届かない状態です。この状態では、ソースコントラクトは引き続きメッセージを送信できますが、それらは空中に滞留し、ソースチェーンにもターゲットチェーンにも存在せず、受け取りや実行ができません。
これはNFTユーザーにとって不快であるだけでなく、危険な状態でもあります。なぜなら:
すべてのブロックされたメッセージはチェーン上から消え、LayerZeroが管理するキューで待機しており、リスクが生じる可能性があります。
失敗したメッセージが解析できなければ、ブロックされたメッセージキューは永久に滞留します。
コントラクト所有者が失敗したメッセージをretryPayloadではなくforceResumeReceiveで処理した場合、失敗したメッセージは永久に失われます。全チェーンNFTの実装において、メッセージの喪失はNFTの喪失と同等です。
したがって、セキュリティ設計の主な目的は、メッセージブロッキングの可能性を最小限に抑えることです。
・クロスチェーンガス保護メカニズム
注意すべき点として、非ブロッキングメカニズムを使用していても、クロスチェーンガスリミット(desination gas limit)が低いことにより、トークンが滞留する可能性があります。
ERC721-Oの設計では、アダプターパラメータがユーザーに完全に開放されており、NFT送信と同時にガストークン(例:Ether、BNB、AVAなど)をエアドロップするといった高度な機能が提供されています。ユーザーは必要に応じてクロスチェーンガスリミットを手動で設定可能です。例えば、ユーザーがクロスチェーンガスリミットを100に設定して転送要求を送信した場合、これはLayerZeroエンドポイントとしては合法ですが、実際にはトランザクションがブロックされます。非ブロッキングモードであっても同様です。
これは、クロスチェーンガスリミットが低すぎると、受信側チェーンのトランザクションがtry-catchブロックの前に失敗するためです。つまり、この状況では非ブロッキングモードは無効になります。
この問題を解決するため、ERC721-Oはガス保護メカニズムを導入しました。このメカニズムは、ユーザーが入力したアダプターパラメータの有効性をチェックします。アダプターパラメータが不正または割り当てられたガスがコントラクト所有者が指定した最低ガスリミットを下回る場合、トランザクションは送信できません。この保護メカニズムは、ユーザーが高度なアダプターパラメータを使用する能力を制限するものではなく、エアドロップなどの機能は引き続き利用可能です。
この仕組みにより、コントラクト所有者は受信関数のガス消費量に基づき、合理的な最低ガスリミットを設定し、ブロッキング問題を回避できます。
・リモートアドレスの安全な設定
誰でもLayerZeroを通じて誰かにメッセージを送信できるため、不正なメッセージの実行を防ぐためにリモートコントラクトを設定する必要があります。既存の実装では、setTrustedRemote関数がメッセージ送信元を制限するのに役立ちます。コントラクト所有者はsetTrustRemoteを呼び出してリモートコントラクトアドレスを設定し、その後そのコントラクトはそのリモートコントラクトからのみメッセージを受け取ります。
一見理にかなっていますが、異なるチェーン上での操作の確定には常に時間差が生じることを考慮していません。
以下のシナリオを想定してください。Aチェーン上のコントラクトaとBチェーン上のコントラクトbは、互いにリモートコントラクトとして設定されており、両方とも使用中です。使用中とは、両チェーン上にすでにミントされたNFTが存在することを意味します。ここで、Aチェーン上のコントラクトaを同じAチェーン上の新コントラクトcに更新したいとします。
単純にBチェーンでsetTrustRemoteを呼び出し、cをコントラクトbの新しいリモートアドレスに設定できます。しかし、これは悪い結果を招く可能性があります。この時点でもAチェーンのユーザーはBチェーンにNFTを送信でき、Bチェーンのリモートアドレスが変更されている(Aチェーンではない)ため、送信されたすべてのNFTは永久に失われます。非ブロッキングメカニズムはここでは役に立ちません。なぜなら、それは正しいリモートアドレスが設定された後にのみ機能するからです。
逆に、まずコントラクトaのリモートアドレスを変更しても同じ結果になります。BチェーンのNFTユーザーは、Bチェーンの設定が完了する前にコントラクトaにNFTを送信できます。これにより、コントラクトaのリモートアドレスが変更され、コントラクトbのアドレスに戻されることはないため、NFTは永久に失われます。
重要なのは、異なるチェーン上の操作が同時に発生することを保証できないということです。では、使用中のコントラクトを更新することは不可能なのでしょうか?
実は解決方法があります。たとえば、ERC721-Oのリモートコントラクト安全設定メカニズムがこの問題を解決できます。pauseMove関数を導入し、パラメータchainIdを受け取ります。これにより、chainIdチェーン上でmove機能がロックされます。つまり、現在のチェーンのユーザーは一時的にchainIdチェーンにNFTを送信できなくなります。コントラクト所有者は、両チェーンのsetRemote操作が確定したことを確認した後、unPauseMove(chainId)を呼び出してchainIdチェーンへのmove操作を解除し、ユーザーが再びchainIdチェーンにNFTを送信できるようにします。
この設計により、コントラクト所有者は使用中のコントラクト更新に対処できます。先ほどの例に戻ると、コントラクト所有者はBチェーンでpauseMove(A)を呼び出し、BチェーンのユーザーがAチェーンにNFTを送信できなくします。一方、AチェーンのユーザーはBチェーンにNFTを送信し続けられます。この時点でコントラクトbは依然としてコントラクトaからのNFTを正しく受け取れるため、この時間差の間にNFTが失われることはありません。次に、コントラクト所有者はAチェーンのコントラクトaでpauseMove(B)を呼び出し、AチェーンのユーザーもBチェーンにNFTを送信できなくします。同様に、AチェーンのコントラクトcでもpauseMove(B)を呼び出す必要があります。
この時点で、コントラクト所有者は任意の順序でコントラクトbとコントラクトcでsetRemote関数を呼び出し、互いにリモートアドレスを設定できます。最後に、コントラクトbとコントラクトcでunpauseを呼び出してクロスチェーン送信を再開し、Aチェーンのコントラクトaがコントラクトcに正常に置き換わります。
この設計は他のシナリオにも適用できます。たとえば、Aチェーンにデプロイされ使用中のNFTをBチェーンにデプロイする場合、コントラクト所有者はまずBチェーンでリモートアドレスを設定しなければなりません。さもなくばNFTが滞留する可能性があります。pauseMove機能があれば、まずpauseMoveを呼び出し、その後chain Aまたはchain Bで互いにリモートアドレスを設定でき、関数呼び出し順序の影響を心配する必要がありません。
実際、このパターンはERC20などの他のタイプのトークンにも拡張可能ですが、ここでは詳述しません。
議論
・オンチェーンガス見積もりを廃止すべきか?
LayerZero公式ドキュメントでは、ターゲットチェーンでのトランザクション失敗を避けるため、オンチェーンガス見積もりを行うことを推奨しています。
しかし、実際には公式がデプロイしたスマートコントラクトですでにこのチェックを実施しています。また、複数のメッセージタイプがある場合、オンチェーンガス見積もりを行ったとしても、ソースチェーン上での見積もりの正確性は保証されません。さらに、ガス見積もりが誤っていたとしても、非ブロッキング設計を持つERC721-Oコントラクトはこれを完璧に処理でき、重大な損失を引き起こしません。
したがって、オンチェーンガス見積もりを強制する意義は小さく、現在のプロトコルバージョンから削除しました。
・forceResumeReceive関数を削除すべきか?
ForceResumeRecive機能は資金損失を引き起こす可能性があります。しかし、予期しないエラーメッセージがメッセージパスをブロックし、再試行が成功しない場合、ForceResumeReciveはそのブロッキング状態を解消する唯一の方法です。非ブロッキング設計であっても、常にメッセージパスが畅通であるとは限りません。予期しないブロッキングを避けるため、現在の実装に残しています。コントラクトがIFG性質(即時決定性)を持つ場合に限り、この関数をオーバーライドして無効にできます。即時決定性とは、ソースチェーンでトランザクションが受理された場合、ターゲットチェーンでも必ず受理されることを意味します。
ブロッキングはユーザーエクスペリエンスに悪影響を与え、資金損失のリスクさえあります。そのため、ブロッキングの発生可能性を最小限に抑えたいと考えています。NFTのクロスチェーン操作においてトランザクションの順序は重要ではないため、非ブロッキングメカニズムを利用して、予期しないエラー/異常送信後もメッセージパスが畅通であることを保証できます。リモートアドレスチェック後に常に正しく実行できることが保証できるコントラクトであれば、非ブロッキングメカニズムの一部を削除することも可能です。
ERC721-Oは依然としてコミュニティが共に築くべきオープンな新規標準です。私たちは、コミュニティの貢献によって、ERC721-Oが全チェーンNFTの標準プロトコルとなることを信じています。
以上の結論はすべて、LayerZero研究所のオープンソースドキュメントおよびオープンソースコード、およびLayerZero公式ノード上での実験に基づいています。誤りを見つけた場合は、コメントを残すか、Githubでissueを提起していただけると幸いです。ご閲覧ありがとうございました!
* 注:文中ではGh0stly Gh0stsの実装と公式例を比較の基準として使用しています
TechFlow公式コミュニティへようこそ
Telegram購読グループ:https://t.me/TechFlowDaily
Twitter公式アカウント:https://x.com/TechFlowPost
Twitter英語アカウント:https://x.com/BlockFlow_News















