IC环境:NFT 功能开发

NFT development

Overview

An NFT or non-fungible token is a record on a blockchain that is associated with a particular digital or physical asset. The unique digital representation on a blockchain allows the proving of ownership as well as their trading.

NFT 或不可替代的代币是区块链上与特定数字或物理资产关联的记录。 区块链上独特的数字表示可以证明所有权及其交易。

NFTs on the Internet Computer

The Internet Computer (IC) brings a lot of potential for NFTs. For digital assets like images, sound clips, or videos, the entire assets can live on-chain and can be included in on-chain games or metaverse experiences. Furthermore, we can imagine dynamic NFTs that change based on IC-internal and external data via HTTPS outcalls.

互联网计算机(IC)为 NFT 带来了巨大的潜力。 对于图像、声音片段或视频等数字资产,整个资产可以存在于链上,并且可以包含在链上游戏或元宇宙体验中。 此外,我们可以想象动态 NFT 通过 HTTPS 呼出根据 IC 内部和外部数据进行更改。

For many applications, the defining characteristic is their permanence and immutability (or evolution according to predefined rules). Some of the design decisions of the IC, such as the reverse gas model and the upgradeability of canister smart contracts, require the NFT developer to be particularly aware.

对于许多应用程序来说,定义特征是它们的持久性和不变性(或根据预定义规则演化)。 IC 的一些设计决策,例如反向气体模型和罐式智能合约的可升级性,需要 NFT 开发人员特别注意。

An NFT implementation on the IC typically has the following three functions:

  • A registry that tracks ownership and allows transfers.
  • A ledger or transaction history.
  • The actual asset (in the case of digital assets).

Depending on the architecture, all of these functions may be in one canister or spread across multiple canisters right up to an asset canister per individual NFT. Each of these canisters must not run out of cycles, and should be protected against arbitrary code changes. In the following, we discuss some of the mechanisms, tools, and ideas that support NFT developers and their users to achieve these goals.

根据架构的不同,所有这些功能可能位于一个容器中,也可能分布在多个容器中,直至每个 NFT 一个资产容器。 这些容器中的每一个都不能超出周期,并且应该防止任意代码更改。 接下来,我们将讨论支持 NFT 开发者及其用户实现这些目标的一些机制、工具和想法。

The basics

Top up all canisters very generously

Make sure that all canisters have enough cycles to sustain a few years to begin with. Storage and computation on the IC are magnitudes less expensive than on other platforms, so this is typically not a huge investment. To make it easy for others to top up the canisters you should consider adding the black hole canister or some other immutable proxy canister as a controller to the NFT canisters. This allows users to use the tip jar service to top up the canisters.

确保所有罐子都有足够的周期来维持几年的开始时间。 IC 上的存储和计算比其他平台便宜得多,因此这通常不是一项巨大的投资。 为了方便其他人充值罐,您应该考虑添加黑洞罐或其他一些不可变的代理罐作为 NFT 罐的控制器。 这允许用户使用小费罐服务来给罐加注。

Set a generous freezing threshold

The IC has a useful mechanism to save your canister from running out of cycles. Canisters have a configurable freezing_threshold. The freezing_threshold can be set by the controller of a canister and is given in seconds. The IC dynamically evaluates this as a threshold value in cycles. The value is such that the canister will be able to pay for its idle resources for at least the time given in freezing_threshold. To guarantee that, the canister is frozen when the cycle balance reaches the threshold, and all update calls, including the heartbeat and timer, are immediately rejected and won’t affect the canister’s cycle balance. The default value is approximately 30 days, but for NFTs, developers should set the freezing_threshold to at least 90 days, preferably 180 days. This makes sure that NFT developers and their users have enough time to react and top up the canisters before they finally run out of cycles.

IC 有一个有用的机制来避免您的罐子耗尽 cycles。 罐有一个可配置的 freeze_threshold。 freeze_threshold 可以由罐的控制器设置,并以秒为单位。 IC 动态地将其评估为 cycles中的阈值。 该值使得容器能够至少在 freeze_threshold 中给定的时间内为其空闲资源付费。 为了保证这一点,当 cycles平衡达到阈值时,容器将被冻结,并且所有更新调用(包括心跳和计时器)都会立即被拒绝,并且不会影响容器的周期平衡。 默认值约为 30 天,但对于 NFT,开发者应将 freeze_threshold 设置为至少 90 天,最好是 180 天。 这确保了 NFT 开发人员及其用户有足够的时间做出反应并在最终用完 cycles之前给罐子充值。

Make sure your canisters can be monitored

On the IC, the cycle balance of a canister is only visible to controllers. Since an NFT (collection) might outlive its creator, you should plan for monitoring by third parties. You can do this via implementing a simple query method as included in the DIP721 and EXT standards.

在 IC 上,罐的cycle余额仅对控制器可见。 由于 NFT(集合)可能比其创建者更长寿,因此您应该计划由第三方进行监控。 您可以通过实施 DIP721 和 EXT 标准中包含的简单查询方法来实现此目的。

Again, adding the black hole canister as a controller is a good practice in this regard, since it can act as a proxy to fetch the canister_status.

同样,在这方面,添加黑洞canister作为控制器是一个很好的做法,因为它可以充当获取 canister_status 的代理。

You can also use a more complete monitoring solution like Canistergeek. Recently, the team behind Canistergeek added a new feature to their NFTgeek product that allows observing the cycles balance of popular NFT collections.

您还可以使用更完整的监控解决方案,例如 Canistergeek。 最近,Canistergeek 背后的团队在他们的 NFTgeek 产品中添加了一项新功能,可以观察流行 NFT 系列的cycle余额。

Follow best practices for efficient implementations

There are a few foot guns that could make your canister more expensive than you’d expect. Here are a few examples that you might encounter when implementing NFT canisters.

有一些脚枪可能会让你的罐子比你想象的更贵。 以下是您在实施 NFT 罐时可能遇到的一些示例。

  • Use of the heartbeat: A plain heartbeat without doing anything will cost ~0.055 T cycles/day. Instead, use canister timers — one-shot or periodic canister calls with specified minimum timeout or interval.

心跳的使用:不执行任何操作的普通心跳将花费约 0.055 T 周期/天。 相反,请使用容器计时器 - 具有指定的最小超时或间隔的一次性或定期容器调用。

  • Some advice for Motoko developers:
    • Use TrieMap instead of HashMap to avoid the performance cliff of automatic resizing associated with HashMaps.
    • Use Buffer instead of Array if you need to dynamically resize the structure.
    • Use Blob instead of [Nat8] for storing large binary assets.
    • Consider using Blob instead of [Nat8] when sending or receiving Candid vec nat8/blob values. The choice is yours but Blobs are 4x more compact and much less taxing on garbage collection (GC).
    • Consider storing large Blobs in stable memory, to reduce pressure on the GC even further, especially when the manual memory management of that Blob is simple (e.g. they are only added, never deleted).
    • Consider using the compacting-gc setting, especially in append-only scenarios, to allow access to larger heaps and reduce the cost of copying large, stationary objects.
  • Some advice for Rust developers:

Another must-read is the general article on good practices for canister development by Joachim Breitner.

To make sure you won’t get surprised by a high cycle burn rate or hitting an instruction limit, you can use the recently added performance counter API to profile your canisters even before going live. Furthermore, a list of all costs on the IC can be found here.

为了确保您不会因高cycle消耗率或达到指令限制而感到惊讶,您甚至可以在上线之前使用最近添加的性能计数器 API 来分析您的容器。 此外,可以在此处找到 IC 上所有费用的列表。

Implement mechanisms to backup and restore state

The IC itself does not yet support backup and restoration of the canister state, but it can be implemented in the canister itself. Regular backups are insurance against the worst-case scenario that a canister gets deallocated or there are issues with upgrading a canister. This forum post describes the approach Distrikt is using.

IC本身尚不支持罐状态的备份和恢复,但可以在罐本身中实现。 定期备份可以防止最坏的情况,即容器被释放或升级容器时出现问题。 这篇论坛帖子描述了 Distrikt 使用的方法。

Consider using a dedicated service for storing the transaction history

There are dedicated services on the IC to keep an audit log of transactions such as CAP, which can be used by an NFT collection as a service. This allows simple integration of the provenance history in explorers and wallets. Furthermore, the state of ownership could be reconstructed in case the main NFT canister gets lost. However, some drawbacks have to be considered, e.g. NFT transfers incur additional costs due to the necessary inter-canister calls.

IC 上有专门的服务来保存交易的审核日志,例如 CAP,NFT 集合可以将其用作服务。 这允许简单地将来源历史集成到浏览器和钱包中。 此外,如果主 NFT 罐丢失,可以重建所有权状态。 然而,必须考虑一些缺点,例如 由于必要的容器间调用,NFT 传输会产生额外费用。

Advanced topics

Think about governance

The value proposition of most NFTs is their permanence and immutability, e.g. by setting the black hole canister as the only controller. As long as NFT canisters have their developers as controllers, users depend on the trustworthiness (and operational security) of the developers. Developers should therefore make the canisters immutable or manage the canisters with a DAO. A middle ground are mechanisms like Launchtrail that make changes to a canister auditable.

大多数 NFT 的价值主张是它们的持久性和不变性,例如 将黑洞罐设置为唯一的控制器。 只要 NFT 容器有其开发者作为控制者,用户就依赖于开发者的可信度(和操作安全性)。 因此,开发人员应该使容器不可变或使用 DAO 管理容器。 中间立场是像 Launchtrail 这样的机制,可以对容器进行更改进行审核。

Blackholing a canister has its issues as well. If there are bugs in the canister code or you’re using experimental system APIs that might get deprecated, later on, the canister might stop functioning.

黑洞化罐子也有其问题。 如果容器代码中存在错误,或者您使用的实验性系统 API 可能会被弃用,那么容器稍后可能会停止运行。

More information on this topic can be found in the trust in canisters article.

Think about economic sustainability

Ideally, your canisters implement mechanisms to generate fees that the canisters can use to pay for their existence indefinitely. A simple approach is to utilize (parts of) the transfer fee to fuel the canisters, but more elaborate schemes could involve staking or other advanced mechanisms. We’re unaware of any good best practices, but please share if you know of projects implementing clever mechanisms.

理想情况下,您的容器实施生成费用的机制,容器可以使用这些费用来无限期地支付其存在费用。 一种简单的方法是利用(部分)转让费来为罐子提供燃料,但更复杂的方案可能涉及质押或其他先进机制。 我们不知道有任何好的最佳实践,但如果您知道实施巧妙机制的项目,请分享。

Resources

The following resources are community projects. Please do your own research and use them at your own risk.

NFT interface specifications and implementations

NFT marketplaces and launchpads


IC环境:NFT 功能开发
arkMeta Crypto Network Limited, arkSong 2023年10月22日
标签
登录 留下评论

将外部代理与 IC 集成
Integrating external agents with the IC