NFT 開発者のための考慮事項
NFT とは何か?
NFT または Non-fungible Token は、特定のデジタルアセットまたは物理的アセットに関連付けられたブロックチェーン上の記録です。ブロックチェーン上での一意なデジタル表現により、所有権の証明や売買が可能になります。
Internet Computer の NFT
Internet Computer(IC)は NFT に多くの可能性をもたらします。画像、サウンドクリップ、ビデオなどのデジタルアセットでは、アセット全体をオンチェーンでライブ配信し、オンチェーンゲームやメタバース体験に含めることができます。さらに、HTTPS アウトコール を介して IC 内部や外部のデータに基づいて変化する動的な NFT を想像することができます。
多くのアプリケーションにとって、その決定的な特徴は永続性と不変性(または事前に定義されたルールに従った変化)です。リバースガスモデルや Canister 型スマートコントラクトのアップグレード可能性など、IC の設計決定の中には、NFT 開発者が特に意識する必要があるものがあります。
IC 上の NFT 実装は通常、以下の3つの機能を備えています:
- 所有権を追跡し、譲渡を可能にするレジストリ
- 台帳または取引履歴
- 現物(デジタルアセットの場合)
アーキテクチャによっては、これらの機能はすべてひとつの Canister に含まれることもあれば、複数の Canister にまたがって、個々の NFT ごとにひとつのアセット Canister まで含まれることもあります。これらの各 Canister は、 Cycle 不足になってはならず、また任意のコード変更から保護される必要があります。以下では、NFT 開発者とそのユーザがこれらの目標を達成するためのメカニズム、ツール、アイデアについて説明します。
基礎
すべての Canister に十分にトップアップする
まず、すべての Canister に数年間維持できる十分な Cycle があることを確認します。IC 上のストレージと計算は他のプラットフォームよりはるかに安価なので、これは一般的に大きな費用ではありません。他の人が簡単に Canister をトップアップ(補充)できるようにするには、NFT Canister のコントローラーとしてブラックホール Canister や他の不変のプロキシ Canister を追加することを検討すべきです。これにより、ユーザーは Tip Jar サービス を使って Canister にトップアップすることができるようになります。
凍結閾値(freezing threshold)を余裕をもって設定する
IC には、Canister を Cycle 切れから救うための便利なメカニズムがあります。Canister には設定可能な freezing_threshold
があります。freezing_threshold
は、Canister のコントローラーで設定することができ、秒単位で指定できます。IC は、これを閾値として動的に Cycle を評価させます。この値は、freezing_threshold
で指定された時間内は少なくとも Canister がアイドル状態のリソースを支払うことができるというものです。これを保証するために、Canister は Cycle バランスが閾値に達するとフリーズし、ハートビートを含むすべてのアップデートコールが直ちに拒否され、それ以後の Canister の Cycle バランスに影響を与えません。デフォルト値は約30日ですが、NFT の場合、開発者は freezing_threshold
を最低でも90日、できれば180日に設定すべきです。これにより、NFT の開発者とそのユーザーは、Cycle を完全に使い果たす前に Canister をトップアップして対応するための十分な時間を確保することができます。
Canister の監視が可能であることを確認する
IC 上では、Canister の Cycle バランスはコントローラーのみが確認することができます。NFT(コレクション)は作成者より長く存在する可能性があるため、サードパーティによる監視を計画する必要があります。DIP721 と EXT 規格に含まれるように、簡単なクエリーメソッドを実装することでこれを行うことができます。
この点でも、ブラックホール Canister をコントローラーとして追加することは良い方法です。なぜなら、canister_status
を取得するプロキシとして機能するからです。
また、Canistergeek のような、より完全な監視ソリューションを使用することもできます。最近、Canistergeek の開発チームは NFTgeek 製品に新しい機能を追加し、人気のNFTコレクションの Cycle バランスを観察できるようにしました。
ベストプラクティスに従った効率的な実装
実装の仕方によっては、Canister が予想以上に高価になる可能性があります。ここでは、NFT Canister を導入する際に遭遇する可能性のある事例を紹介します。
- ハートビートを利用:何もしない素のハートビートでは、〜0.055T Cycle/day のコストがかかります。より安価なスケジューリングを可能にする代替手段を実装するという議論があります。
- Motoko 開発者へのアドバイス:
- HashMap の代わりに
TrieMap
を使用すると、HashMap に関連する自動リサイズによるパフォーマンスの低下を回避することができます。 - 動的にサイズを変更する必要がある場合は、
Array
ではなくBuffer
を使用してください。 - 大きなバイナリアセットを保存する場合は、
[Nat8]
の代わりにBlob
を使用します。 - Candid
vec nat8/blob
値を送受信する場合は、[Nat8]
ではなくBlob
を使用することを検討してください。選択するのはあなたですが、Blob
の方が4倍コンパクトで、ガベージコレクション(GC)への負担がずっと少なくなります。 - Blob の手動メモリ管理が単純な場合(例えば、追加するだけで、削除はしない)、GC への負担をさらに減らすために、大きな
Blob
をステーブルメモリに格納することを検討してください。 compacting-gc
設定を使用することを検討してみてください。特に、追加のみ(Append-only)のシナリオでは、より大きなヒープにアクセスできるようにし、オブジェクトのコピーコストを削減することができます。
- HashMap の代わりに
- Rust の開発者へのアドバイス:
- アップグレードのためにステートをシリアライズ・デシリアライズする必要がある場合は、
Vec<u8>
やString
型を多用しないように注意してください。 - Roman の効果的な Rust Canister に関するブログポストをお読みください。
- アップグレードのためにステートをシリアライズ・デシリアライズする必要がある場合は、
また、Good practices for canister development by Joachim Breitner という一般的な記事も必読です。
高い Cycle 消費率や命令制限に驚かないように、最近追加されたパフォーマンスカウンター API を使って、稼動前でも Canister をプロファイリングすることができます。さらに、IC 上のすべてのコストのリストはここで見ることができます。
ステートのバックアップと復元を行う仕組みを実装する
IC 自体はまだ Canister のステートのバックアップと復元をサポートしていませんが、Canister 自体に実装することは可能です。定期的なバックアップは、Canister が割り当てられなくなったり、Canister のアップグレードに問題が生じたりする最悪のシナリオに対する保険となります。このフォーラムの投稿は、Distrikt が使っているアプローチについて説明しています。
取引履歴の保存には、専用サービスの利用を検討する
IC 上には CAP のようなトランザクションの監査ログを保持する専用サービスがあり、NFT コレクションがサービスとして利用することが可能です。これにより、エクスプローラーやウォレットに履歴を簡単に統合することができます。 さらに、メインの NFT Canister が紛失した場合、所有ステートを再構築することができます。しかし、NFT の転送には Canister 間コールが必要なため、追加コストがかかるなどの欠点も考慮する必要があります。
より高度なトピック
ガバナンスについて考える
ほとんどの NFT の価値は、例えばブラックホール Canister を唯一のコントローラーとして設定することによる、永続性と不変性です。NFT の Canister が開発者をコントローラーとしている限り、ユーザーは開発者の信頼性(および運用上の安全性)に依存することになります。そのため、開発者は Canister をイミュータブルにするか、DAO で Canister を管理する必要があります。中間的な方法としては、Canister への変更を監査可能にする Launchtrail のようなメカニズムがあります。
Canister をブラックホール化することにも問題があります。Canister のコードにバグがあったり、非推奨になるかもしれない実験的なシステム API を使っていたりすると、後になって Canister が機能しなくなる可能性があります。
このトピックに関する詳細は、Trust in Canisters の記事でご覧いただけます。
経済的な持続可能性を考える
理想的には、Canister がその存在を無期限に支払うために使用できる手数料を生成するメカニズムを実装することです。シンプルなアプローチは、送金手数料の一部を Canister のガスとして利用することですが、より精巧な仕組みとして、ステーキングや他の高度な仕組みを取り入れることもできます。私たちは一番良いとされるベストプラクティスをまだ発見していませんが、巧妙なメカニズムを実装しているプロジェクトをご存知でしたら、ぜひ教えてください。
リンクとリソース
以下のリソースは、コミュニティーのプロジェクトです。ご自身で調べ、ご自身の責任でご利用ください。
NFT インターフェースの仕様と実装
- DIP721:ERC-721 に類似したインタフェース。
- Extendable Token (EXT):ERC-1155 にヒントを得た拡張可能なインターフェース。