在 Solana 中如何表示 NFT

KingData ·2022-06-06

在之前的文章中,我们看到了 NFT 如何解锁拥有数据的新方式。现在让我们看看 NFT 在 Solana 中是如何工作的。
由于 Solana 区块链的数据结构不同于其他区块链,一开始可能会令人困惑,但在我看来,它的模型很有意义,并且更接近我们在现实世界中表示事物的方式。
因此,我们将首先查看我们如何在现实世界中做事,然后逐步走向 NFT 的表示。
忍受我,我们要去一个小旅程。
不是您的典型程序
这篇文章不是关于编码,但值得注意的是,如果你习惯了其他区块链,例如以太坊,那么你将有一些忘却的事情要做。
在这些区块链或任何典型的代码片段中,您可以在程序中添加变量,并且您的逻辑会更新这些变量。在以太坊中,部署的“智能合约”包含该合约完成其工作所需的逻辑和数据。
对于索拉纳来说,情况并非如此。在 Solana 中,“程序”(相当于智能合约)与存储在程序外部的“帐户”交互。这使我们能够创建更通用的逻辑,可以扩展到新的数量级,因为数据不再受程序大小的限制。此外,它使区块链能够更有效地运行,因为它可以与不同的账户并行运行相同的程序。
TL;DR; 这里是:Solana 中的数据存储在程序之外,在称为“帐户”的可重用和可扩展模型中。
美元印刷机
好吧,让我们回到现实世界,思考一下是什么让我们拥有了我们以给定货币拥有的钱。
金融是一门复杂的学科,拥有货币的方式有很多种:现金、银行、资产等。为了更接近我们在 Solana 中建模事物的方式,我们需要简化现实世界的模型。
想象一下,世界上所有给定货币的货币都是由一家银行产生的,而且只有一家银行。让我们称它们为“印刷机”,因为它们实际上能够控制流通中的货币量。例如,“美元印刷机”将负责管理世界上所有的美元。很好很简单。

然后,这些“打印机”将允许个人通过“银行账户”拥有资金,每个人都可以拥有任意数量的银行账户。这样,银行账户就充当了个人和货币之间的多对多关系。
在下面的示例中,Alice 通过三个不同的银行账户(两个用于美元,一个用于英镑)拥有美元和英镑,而 Bob 仅通过一个银行账户拥有英镑。

好,考虑到那个模型,让我们进入代币的世界吧!
薄荷糖和代币
在上一节中,我们创建了一个简单的模型,人们使用银行账户获取给定货币的资金。

好吧,令人惊讶的是,该模型类似于令牌在 Solana 中的表示方式。您可以将代币视为存在于区块链上的去中心化货币。
每种类型的代币都由我们所谓的“铸币厂帐户”定义。该帐户类似于“打印机”,因为它实际上可以用于“铸造代币”,这相当于印钞。
然后,个人可以通过存储所拥有代币数量的“代币账户”拥有代币。
最后,区块链中没有个人这样的东西,因为人们通过称为钱包的加密密钥对与他们进行交互。每个钱包的公钥指向 Solana 中的一个账户,该账户存储钱包拥有的 SOL 数量。因此,我将这些账户称为“钱包账户”。
因此,这导致我们进行以下类比。

请注意,个人拥有多个钱包是很常见的——通常是出于安全目的。因此,下面的类比更为准确。

在我们进入下一部分之前,让我们快速举一个 Solana 中代币所有权的例子。
代替美元和英镑,我们将使用代币USDC和AVDO. 这些是 Solana 中的真实代币。USDC是一种与美元挂钩的稳定币,AVDO是一种由牛油果行业支持的加密货币(为什么不)。

正如你所看到的,Alice 通过两个钱包和三个代币账户拥有一些 USDC 和一些 AVDO。另一方面,Bob 仅通过一个钱包和两个代币账户拥有 AVDO。
你的 IBAN 是什么?
现在,到目前为止所描述的模型存在一个很大的不便。
为了说明这个问题,假设在我们之前的示例中,Alice 想要向 Bob 发送一些 AVDO 令牌。
既然 Bob 有两个代币账户来存放他的 AVDO 代币,那么 Alice 应该选择哪个代币账户来存入她的代币?她应该要求 Bob 将他选择的令牌帐户的公钥发送给她吗?更糟糕的是,假设当 Bob 目前没有任何 USDC 代币账户时,Alice 现在想向 Bob 发送一些 USDC 代币。她应该为 Bob 创建一个新的令牌帐户,然后将其公钥发送给他吗?
这些问题都没有导致无法发送代币,但它们使我们的生活变得比应有的更加艰难。
向某人发送代币时,您通常只有他们钱包的公钥,您真的不想担心要使用哪个代币帐户,或者它是否存在。
该问题的解决方案称为“程序派生地址”或简称 PDA。这些是使用特殊算法从其他公钥派生的公钥。
这对我们来说意味着,给定一个“钱包账户”和一个“铸币账户”,我们可以确定性地找到相关的代币账户。事实上,这些账户被称为“Associated Token Accounts”(简称ATA),由“ Associated Token Account Program ”管理。
因此,我们最终得到了两种创建和使用代币账户的方法:一种是确定性的(使用 PDA),另一种不是(使用普通的代币账户)。

请注意 PDA 上方的注释。这些是派生相关代币账户地址所需的参数。如果您想了解更多关于 PDA的信息,Solana Cookbook是一个不错的起点。
由于我们将在本文中大量使用此图,因此让我们稍微缩短它的表示。我们将使用下图来表示钱包和铸币帐户之间的通用连接。他们可以使用 PDA,也可以不使用。

在我们从这个重要的 PDA 括号继续之前,让我们快速浏览一下我们之前仅使用关联令牌帐户的示例。

请注意,我们现在每个钱包每个铸币厂只有一个代币帐户,这意味着 Alice 知道将 AVDO 代币发送给 Bob 的位置。此外,即使账户还不存在,Alice 也知道向 Bob 发送一些 USDC 到哪里。
好吧,让我们继续吧!

铸币厂和代币的数据
感谢您的耐心,但您可能会想:“Loris,这与 NFT 有什么关系?”。
我保证我们会到达那里!但要回答这个问题,我们首先需要了解代币账户和铸币账户中存储了哪些数据。
为此,让我们更新图表以显示每个帐户下的所有可用数据,并且在我们使用它的同时,让我们还显示帐户的所有者——即负责创建它的 Solana 程序。

好的,我们这里有几点需要注意。
首先,请注意令牌帐户(关联与否)如何跟踪铸币厂和钱包帐户。我用虚线突出了这些连接。
代币账户的下一个重要数据是“金额”。它存储帐户中可用的令牌数量。
其余数据也很重要,但超出了本文的范围,因此我将不再赘述。我只想说,当您看到斜体属性时,这意味着它是可选的。
转到铸币厂帐户的数据。第一个属性是可选的“Mint Authority”。这代表可以铸造更多代币的账户——即印更多的钱。通常是创建它的钱包帐户。这是可选的,因为铸币局可以撤销自己的权利,因此,使铸币账户不可变——即流通中的代币数量永远不会增加。
说到,下一个属性—— “供应” ——告诉我们当前流通的代币总量。此属性不能手动更新,并由程序自动保持最新。
接下来,“小数”属性指示我们应该为该标记使用多少个小数位。例如,如果一个代币账户拥有Amount = 250并且铸币厂账户拥有Decimals = 2,这意味着代币账户实际上拥有2.50该代币。这样,所有货币值都可以使用整数存储。
我们还将跳过其余属性,因为它们超出了本文的范围。
为了更接近 NFT 的表示,让我们稍微玩一下这些属性。
如果我们创建一个小数点为零的铸币账户并立即将一个代币铸币到钱包账户会怎样?
结果将是一个只有一个代币在流通的铸币账户,不能分解成更小的单位——例如,Alice 和 Bob 不能同时拥有 0.5 个该代币。

唯一的问题是没有什么能阻止“铸币局”在未来继续铸币。如果他们这样做了,我们就会突然有不止一个代币在流通,因此,不止一个钱包可以拥有它们。
为防止这种情况,铸币机构需要在铸币后立即撤销其铸币的权利。

我们最终得到的是一个铸币帐户,其供应量永远不会超过一个,并且其代币无法共享或分割。
因此,在任何给定时间,该铸币厂只能有一个代币持有者。
NFT 只是一种特殊的铸币厂
我的朋友们,那是不可替代的代币!🥳
“可替代品”的定义是:
具有这样的性质或种类,可以全部或部分自由地交换或替换为另一个类似性质或种类的人。
换句话说,它可以被其他同类的东西代替。例如,橄榄油是可替代的。一升橄榄油可以用另一升橄榄油代替,我们并没有失去任何价值。货币也是如此:用另一张 10 美元的钞票代替 10 美元的钞票,你仍然有 10 美元。
因此,要使代币具有不可替代性,它需要具有不能与同类事物交易的特性。我们通过创建一个永远不会拥有多个代币持有者的铸币厂帐户来实现这一目标。谁拥有这个代币,谁就拥有了铸币厂账户,因此就拥有了 NFT。
回顾一下:NFT 是一个小数点为零的铸币账户,其供应量永远不会超过 1。
我还想花点时间欣赏一下该模型的优雅程度。它的表示不仅与其定义一致,而且通过依赖令牌帐户和铸币帐户,我们可以与 NFT 交互,就像我们与令牌交互一样。向某人发送 NFT 就像向他们提供该铸币厂帐户的唯一代币一样简单。
图片在哪里?
好的,老实说,我们还没有完全完成在 Solana 中解释 NFT 的旅程。到目前为止,我们所解释的确实是定义上的 NFT,但不是非常有用。它告诉我们的只是我们拥有一个代币,并且没有其他人可以拥有该代币。伟大的!但是那个令牌叫什么?它的目的是什么?图在哪里?!
好吧,听起来我们需要将更多数据附加到我们的 NFT 以使其有用。这就是 Metaplex 的用武之地!
Metaplex是一家创建和维护 Solana 程序的公司。他们最受欢迎的程序称为“令牌元数据程序”。您猜对了,它将元数据添加到我们的令牌中!
它通过使用程序派生地址 (PDA) 来做到这一点。如果您还记得,PDA 允许我们使用其他地址确定性地找到地址。
在这种情况下,令牌元数据程序将创建一个附加到该 NFT 的新“元数据帐户”。但是你能猜出它使用哪个地址来导出自己的地址吗?是薄荷账户还是代币账户?

答案是:薄荷账户!铸币厂账户是 NFT 最重要的账户。代币账户是 NFT 和钱包之间的关系。如果我们将 PDA 附加到代币帐户然后出售我们的 NFT,新所有者将丢失所有这些数据。因此,铸币账户是 NFT 的主要入口点。
好吧,让我们看看 Metaplex 在“元数据帐户”上为我们提供了什么样的数据。

让我们一一浏览所有这些属性。
Key: 这个属性就是我们所说的判别器。因为 Metaplex 在 Token Metadata Program 中有许多不同类型的账户,这告诉我们我们正在处理哪个账户。这里,“元数据帐户”由MetadataV1密钥标识。请注意,令牌程序使用帐户的大小而不是鉴别器来解决这个问题,它的性能更高但灵活性更低。
Update Authority:这是可以更新“元数据帐户”的帐户。
Mint:这又回到了造币厂帐户。
Name:NFT 的链上名称——限制为 32 个字节。
Symbol:NFT 的链上符号——限制为 10 个字节。这通常保留为空字符串,但如果您希望您的 NFT 集合具有共享符号,这可能会很有用。例如,你的“Banana Blossom”NFT 投币可能有符号“BNBL”。
URI:NFT 的 URI——限制为 200 字节。这是最重要的属性之一。它包含一个指向链下 JSON 文件的 URI。这个 JSON 文件既可以存储在传统服务器中(例如使用 AWS),也可以使用永久存储解决方案存储在另一条链上(例如使用 Arweave)。我们稍后会详细讨论这个 JSON 文件。
Seller Fee Basis Points:创作者以基点分享的版税——即550意味着5.5%。
Creators:一系列创作者和他们的版税份额。此数组仅限于 5 个创建者。每个创建者都存在一个verified属性,以确保他们签署 NFT 以证明其真实性。
Primary Sale Happened:一个布尔值,用于跟踪 NFT 之前是否已售出。这会影响版税。
Is Mutable:一个布尔值,指示是否可以修改 NFT 的链上元数据。一旦翻转到false,就无法恢复。
Edition Nonce:此可选属性稍微超出范围,但用于验证限量版 NFT 的版本号。
Token Standard:此可选属性捕获令牌的可替代性。我们将在本文中对此进行更多讨论。
Collection:此可选属性链接到另一个 NFT 的铸币厂地址,该 NFT 充当 Collection NFT。这有助于市场将 NFT 组合在一起并安全地验证这些集合。
Uses:此可选属性可以使 NFT 可用。这意味着您可以加载一定数量的“使用”并使用它直到它用完。你甚至可以让它在 NFT 完全用完时自行销毁。
呸!如您所见,有很多很酷的功能。我不打算在这里全部介绍它们,但我希望在这个系列中添加更多关于该主题的文章。同时,请随时查看Metaplex 官方文档以获取更多信息。
再次,图片在哪里?
这么多属性,还没有图片或数字资产?这不是 NFT 的重要组成部分吗?
是的!不用担心,我们确实有存储这些信息的地方。
还记得URI指向链外 JSON 对象的属性吗?好吧,该 JSON 对象遵循一定的标准以便存储更多数据。

如您所见,除其他外,我们可以提供 a name, a description,最后是 a image!URI与元数据帐户的属性类似,该image属性应该是可用于下载数字资产的 URI。对于具有更多自定义需求的 NFT,还有一个animation_url属性和一个数组。files所有这些资产都可以存储在链下(在传统服务器中)或使用永久存储解决方案(在另一个区块链中,例如 Arweave)。请务必查看 Metaplex 文档以获取有关其 NFT 标准的更多信息。
值得一提的是,您可以在该 JSON 对象中添加任何您想要的内容。如果您计划构建一个可以识别您自己的 NFT 的应用程序,这可能会很有用。但请注意,其他应用程序和市场不会知道此数据的存在,因此不会使用它。
为什么要存储两个元数据?
您可能想知道,为什么我们需要两个地方来存储 NFT 的数据?我们不能将所有内容都存储在元数据帐户上吗?
有几个问题。
首先,在链上存储数据需要花钱。在设计成千上万人使用的帐户时,您需要注意创建它们的成本。
其次,链上数据的灵活性要差得多。一旦使用某种结构创建帐户,就不能轻易更改。因此,如果我们必须将所有内容都存储在链上,我们将极大地限制可以附加到 NFT 的数据量。
因此,我们需要巧妙、安全地将数据分为两类:链上和链下。例如,Creators阵列是链上的,因为我们需要一种无需信任的方式来了解 NFT 是否真的由给定艺术家提供和签名。该Is Mutable属性是链上的,因为我们需要确保一旦翻转到false它就永远无法恢复。
底线是:代币元数据计划可以为链上数据创建保证和期望,但不能为链下数据做到这一点。
但是,这并不一定意味着链下 JSON 文件不安全且永远不可信。Arweave 等永久存储区块链通常用于存储数字资产和引用它们的 JSON 元数据,确保链下数据的不变性。此外,可以使 NFT 不可变,确保URI元数据帐户的属性永远不会指向其他地方。这是 NFT 最安全的配置,因为它保证甚至无法更改它。
此外,请注意,某些 NFT 项目可能需要其数据以有利于 NFT 所有者的方式可变。例如,如果您计划创建一个逐渐成长为成年猴子的小猴子的 NFT,您需要将 JSON 元数据存储在您控制的服务器上,以便进行这些渐进式更改。下一次,NFT 所有者打开他们的钱包,他们会看到另一个图像,但他们会高兴而不是愤怒。我的观点是,只要你信任 NFT 的创建者——由Verified链上属性的标志保证Creators——可变的链下数据可以是真实的。但是,当然,请始终进行自己的研究。
打印多个版本
好的,我们现在肯定已经达到了 Solana 中 NFT 的最终表示吗?
在大多数情况下,是的,但不完全是。
令牌元数据程序提供了另一个重要的帐户,它源自铸币帐户(使用 PDA)。
事实上,位于 PDA 内的帐户可以是两种不同类型之一。它可以是“Master Edition”或“Edition”。

“大师版”也称为“原始版”,是一种 NFT,可以由其所有者复制一定数量的“最大供应”属性。

“Edition”也称为“Print Edition”,是从“Master Edition”复制而来的 NFT。每当创建新的“版本”时,它都会跟踪其父“主版本”及其版本号。它还增加了其母公司“大师版”的供应。一旦供应量达到最大供应量,就不能再以这种方式打印 NFT。请注意,“大师版”的“最大供应量”可以为空,这意味着可以从中打印无限量的 NFT。

另请注意,“版本”NFT 上存在另一个鲜为人知的 PDA 帐户,称为“版本标记”,以确保给定“主版本”的版本号之间没有重叠。

此功能的一个用例是允许艺术家出售多于一份他们的艺术作品。例如,他们可以发布 100 个 1/1 NFT 的限量版,并且每个人都会在链上跟踪他们的版本号。

值得注意的是,打印 NFT 的多个版本是完全可选的,并且大多数 NFT 会将其“最大供应量”设置为 0 以防止使用它。

那么为什么我决定在这篇相当长的文章中提到“Master Editions”和“Editions”呢?因为,虽然印刷版是他们的主要目的,但他们的责任不止于此。

如果你还记得,我们之前说过,要使“铸币帐户”成为 NFT,它需要:

小数点为零。
已将一个代币铸造到钱包中。
已撤销其通过“铸币局”属性铸币的权利。

那么,令牌元数据程序使用版本 PDA 来保证这些属性。创建版本 P​​DA 帐户时(无论是“Master Edition”还是“Edition”),它将检查 mint 帐户是否有零位小数和正好一个供应。如果其中任何一个条件失败,它将拒绝创建帐户。如果他们成功了,它将把“铸币局”转移到新版本的 PDA 上,确保没有钱包可以铸币额外的代币。这意味着,薄荷帐户上存在“大师版”或“版”帐户这一简单事实证明了其不可替代性。

这就是为什么“Master Edition”和“Edition”账户在 Solana NFT 中很重要,在本文中值得一提。

这是我们 NFT 图的一些更新。如您所见,“Mint Authority”不再为空,而是指向只能由开源和经过审计的令牌元数据程序控制的版本 PDA。


代币标准和半可替代代币
现在,我们全面了解了使薄荷帐户成为 Solana 中的 NFT 的原因!
但是,如果我不提到 Token Metadata Program 还支持我们所说的“ Semi-Fungible Tokens ”或简称 SFT,那么这篇文章是不完整的。

SFTs 与 NFTs 基本相同,但没有不可替代的保证,我们之前谈到过。
“但是为什么?”,你可能会问,“我认为不可替代性是重点?”。
好吧,它是针对 NFT 的,但仔细想想,“元数据帐户”的核心目的是向代币添加数据。为什么我们应该只将该功能限制为不可替代的代币?

为什么我们早期的可替代鳄梨令牌(AVDO)不能将链上数据添加到其铸币帐户?它可以使用这些数据让去中心化交易所知道要使用哪个符号、要列出哪些外部链接、要显示哪个徽标等等。
另一个用例是创建一个游戏资产作为零十进制代币。例如,您可以为游戏中的“木头”资源创建一个令牌。由于玩家应该能够拥有和交易不止一种木材,因此必须为游戏中的每一块木材创建一个单一的 NFT 是没有意义的。这就是为什么在从链上数据中受益的同时使游戏资源成为可替代资产是非常有价值的。

因此,代币元数据计划允许我们为可替代的铸币帐户创建元数据帐户。这就是为什么,版本 PDA 有责任保证不可替代性。

为了让我们的生活更轻松,元数据帐户通过“令牌标准”属性跟踪令牌的“可替代性”。它可以是以下值之一。
NonFungible
如果令牌标准是NonFungible,我们知道我们正在处理 NFT。当且仅当为该铸币厂创建“Master Edition”或“Edition”帐户时,才适用此标准。
这意味着,我们有以下保证:

薄荷供应就是其中之一。
薄荷小数为零。
在版本 PDA 下存在一个帐户。
铸币厂授权已转移到 PDA 版。


FungibleAsset
如果令牌标准是FungibleAsset,我们知道我们正在处理非十进制 SFT。例如,我们的“Wood”资源示例将被标记为FungibleAsset.

这意味着我们有以下保证:

薄荷小数为零。
版本 PDA 下不存在帐户。


Fungible
如果令牌标准是Fungible,我们知道我们正在处理十进制 SFT。例如,鳄梨代币或 USDC 代币都属于这一类。
这意味着我们有以下保证:
薄荷小数严格大于零。
版本 PDA 下不存在帐户。

值得注意的是,链下 JSON 元数据标准根据我们刚刚讨论的“令牌标准”而有所不同。您可以在下面找到每种令牌类型的 JSON 标准定义。
不可替代令牌的 JSON 标准
可替代资产令牌的 JSON 标准
可替代令牌的 JSON 标准
结论
呸,多么美妙的旅程!
现在,我们不仅全面了解了 Solana 中 NFT 和 SFT 的样子,而且我们还了解了为什么事物的结构是这样的,以及它们与我们习惯的其他模型相比如何。
如果没有最终图表来恢复我们在这里学到的内容,本文将是不完整的。

为了让这个图表对那里的开发人员更加有用,我们还要添加偏移量和每个帐户属性的大小(以字节为单位)。我将使用波浪号~来表示可变帐户大小。

© 本文著作权归 KingData 所有,未经 KingData 许可,不得转载使用

分类标签Solana