NFT记录(zz)

AI数据  收藏
0 / 738

Token 的区块链演化——NFT 的诞生

“Token”原来只是一个计算机术语,例如早期基于令牌的计算机网络,token一般只是一个身份凭证,并没有流通价值,如果说流通也只是机器之间的流转,进而代表一定的操作权限。

区块链本质上是分布式数据库,允许我们以一种安全和可公开访问的方式存储信息。区块链也提供了避免欺骗的经济激励,从而允许真正的经济稀缺性。区块链还为数字身份问题提供了一些有趣的解决方案: 我们在区块链上进行的每一笔交易都与一个公共地址相关联----一个匿名的安全标识符,可以重复使用。

区块链是非常强大的,带来了第一个广泛使用的加密货币,但比特币只是作为一种货币有用。它只不过是一个值的表示、记录或占位符。V神创建了以太坊,使用区块链来让更复杂的信息,甚至是脚本进行去中心化操作。人们开始使用以太坊来创建新的加密货币(通常称为Token)和去中心化应用程序(或 dApps) ,

这里的“Token”,即可流通的加密数字证明,是区块链上的一个价值凭证,具有流通的价值,可以直接进行交易,往往被称为“代币”。进一步,Token可以代表任何有价值的东西,实现权益的数字化,进而被称为“通证”,具有物权、股权、货币的属性。就像股票一样,我们能够获得损益。

基于以太坊编码更复杂数据结构的能力导致了对标准的需求,Ethereum 开发者社区编写了ERC——Ethereum Request for Comments”,它产生了一套使用以太坊构建软件的标准。基于ERC,开发人员可以构建与其他代码兼容的软件,通过确保不同的token和应用程序共享相似的组件,开发人员可以交换这些组件来构建新的体验。像比特币、以太币这样的加密货币代币都是可互换的,或者说是“同质的”,因为一个代币可以兑换任何其他代币。唯一改变的是块环链上的一个记录,记录了交易。ERC20只是大多数可替代代币的制造标准。

以太坊使开发人员将更复杂的数据去中心化,那么为什么一个token不应该包含比一个简单的单位值和所有者更多的变量呢?换句话说,代币之间不可替换呢?

至此,NFT——non-fungible token诞生了,中文名叫非同质化通证。正如 ERC20标准化的同质化通证一样,ERC721也是为了标准化非同质化通证而编写的。通过标准化 NFT,开发者社区迎来了一个新的数字内容、游戏和使用 NFT的应用程序的生态系统。

什么是NFT?——非同质化通证(代币)

​ NFT 是 Non-Fungible Token 的缩写,中文称为「非同质化代币」,通常是指开发者在以太坊平台上根据 ERC721 标准/协议所发行的代币。

在区块链上,数字加密货币分为原生币和代币两大类。前者如BTC、ETH、Filecoin等,拥有自己的主链,使用链上的交易来维护账本数据;代币则是依附于现有的区块链,使用智能合约来进行账本的记录,如依附于以太坊上而发布的各种代币。代币之中又可分为同质化和非同质化两种。

​ 既然NFT被称作「非同质化代币」,那么相应的肯定有「同质化代币」,下图是二者一个形象的举例。

同质化代币
​ 同质化代币的典型代表就是以 ERC20 标准/协议发行的 token。 在 ERC20 标准/协议我们中可以知道,ERC20 的 token 是指定小数位数的,也就是 token 可以任意分割,token 与 token 之间是等价的。简单来说同质化代币就是一种能够相互替换、具有统一性、可被拆分的代币。就像美元之间可以进行交换,即使序号不同,价值却不会有任何不同。

非同质化代币
​ 非同质化代币的典型代表就是以 ERC721 标准/协议发行的 token。而在 ERC721标准/协议 中则定义的是一种不可分割的 token ,每个 token 都是独一无二的,我们可以追踪每个 token 的转移和其价值的变动的。可以认识到非同质化代币就是由于包含了记录在其智能合约中的识别信息使得每种代币都具有独一无二的特性,因此不能被另一种代币直接取代。

我们常见的Token(如BTC,ETH等)都是同质化的,即FT(Fungible Token),互相可以替代、可接近无限拆分的token。

NFT是非同质化通证(代币),具有不可分割、不可替代、独一无二等特点。每一个NFT拥有独特且唯一的标识,两两不可互换,最小单位是1且不可分割。例如,在以太坊的迷恋猫中,每一只猫都对应着链上的一个NFT,拥有独特的id和基因,更重要的是,拥有独立的价值。

原生数字资产即存在于数字世界,或发源于数字世界的资产。因此,相较于FT,NFT的关键创新之处在于提供了一种标记原生数字资产所有权的方法,且该所有权可以存在于中心化服务或中心化库之外。NFT 的所有权并不阻止其他人读取,并不是捕获信息然后把它藏起来,只是捕捉信息后发现该信息与链上所有其它信息的关系和价值。

基于NFT的非同质化、不可拆分的特性,可以使它锚定现实世界中商品的概念,简单地说,就是在发行在区块链上的数字资产,这个资产可以是数字艺术品、纪念品、门票等等,并且具有唯一性和不可复制性。由于NFT具备天然的收藏属性和便于交易,加密艺术家们可以利用NFT创造出独一无二的数字艺术品。

NFT 的实现标准

非同质化通证标准允许NFT轻松跨越多个生态系统。当一个开发人员启动一个新的 NFT 项目时,这些 NFT 可以立即在几十个不同的钱包提供商中显示出来,可以在市场上交易,最近,还可以在虚拟世界中显示出来。这是完全可能的,因为开放标准为读写数据提供了清晰、一致、可靠和许可的 API。

互操作性带来的最引人注目的特性是开放市场上的自由贸易。NFT的即时交易性将导致更高的流动性。智能合约允许开发人员对不可替换令牌的供应设置硬上限,并强制执行在发出 nft 之后无法修改的持久属性。nft 是完全可编程的,设计空间充满了可能性。

由 CryptoKitties 率先推出的 ERC721是第一个代表不可替代数字资产的标准。ERC721是一个可继承的 solid 智能合同标准,这意味着开发人员可以通过从 OpenZeppelin 库导入 ERC721,轻松创建新的兼容 ERC721的合同。ERC721实际上相对简单: 它提供了唯一标识符(每个标识符代表一个资产)到地址的映射,地址代表该标识符的所有者。ERC721还使用 transferFrom 方法提供了转移这些资产的许可方式。

interface ERC721 {
function ownerOf(uint256 _tokenId) external view returns (address);
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
}

这两个方法实际上就是代表 NFT 所需要的全部: ownerOf检查谁拥有什么,transferFrom实现资产转移。标准还有其他一些附加功能(其中一些对于 NFT 市场非常重要) ,但 ERC721的核心是相当基本的。

ERC1155,由Enjin (https://enjinx.io)团队首创,将半替换的想法带到了 NFT 世界。在 ERC1155中,ID代表的不是单个资产,而是资产的类别。例如,一个 ID 可能代表“宝剑”,而一个钱包可能拥有1000把这样的宝剑。在这种情况下,balanceOf 方法会返回一个钱包所拥有的剑的数量,用户可以通过“剑”ID 调用 transferFrom 来转移任意数量的这些剑。

interface ERC1155 {
function balanceOf(address _owner, uint256 _id) external view returns (address);
function transferFrom(address _from, address _to, uint256 _id, uint256 quantity) external payable;
}
这种系统的一个优点是效率: 基于ERC721,如果用户想要转移1000把剑,需要修改智能合同的状态(通过调用 transferFrom 方法) ,以获得1000个唯一的通证。而使用 ERC1155的话,只需要调用 transferFrom 方法,和数量为 1,000的参数并执行一次操作。当然,这种效率的提高伴随着信息的丢失: 人们再也无法追踪单把剑的历史。

ERC1155提供了 ERC721功能的超集,这意味着可以使用 ERC1155构建 ERC721资产(对于每个资产,只需要有一个单独的 ID 并且数量1)。最近Opensea在 Github 上开发了一个仓库(https://github.com/ProjectOpenSea/opensea-erc1155),用于ERC1155标准的使用。

作为组合创新,ERC-998标准提供了一个模板,凭借这个模板,NFT可以同时拥有同质化和非同质化的资产。目前在主网络上只部署了几个可组合的NFT,但可能是一些令人难以置信的机会!  

虽然以太坊是NFT目前最活跃的地方,但也有一些NFT标准出现在其他的区块链上。DGoods 由 Mythical Games 团队开发,致力于从 EOS 提供一个功能丰富的跨链标准。Cosmos 项目也在开发一个 NFT 模块,可以作为 Cosmos SDK 的一部分加以利用。

NFT 附加信息的存储

NFT通过元数据为特定的标记 ID 提供描述性的附加信息。在 CryptoKittty 的例子中,元数据是猫的名字、猫的照片、描述文字和任何其他特征(在 CryptoKitties 的例子中称为“cattributes”)。对于票证,元数据可能包括事件的日期和票证的类型,以及名称和描述。上面这只猫的元数据可能是这样的:

{
"name": "Duke Khanplum",
"image": "https://storage.googleapis.com/ck-kitty-image/0x06012c8cf97bead5deae237070f9587f8e7a266d/1500718.png",
"description": "Heya. My name is Duke Khanplum, but I've always believed I'm King Henry VIII reincarnated."
}

在哪里存储这些数据

为了方便NFT 的应用程序能够访问这些数据,如何以及在哪里存储这些数据呢?第一个决定是链上存储还是链下存储。也就是说,是将元数据直接放入代表令牌的智能协议中,还是单独托管?

链上存储元数据的好处是:

它永久地驻留在通证中,超出了任何给定应用程序的生命周期;

它可以根据链上逻辑进行更改。

如果数字资产的长期价值远远超过其最初创造的价值,例如,一件数字艺术作品被认为会流传千古,那么就不管用来创作这件艺术作品的原始站点是否仍然存在。因此,NFT的元数据必须与标记标识符的生命周期保持在一起。

尽管有这些好处,但由于以太坊区块链的存储限制,目前大多数项目的NFT存储仍然是链下存储。因此,ERC721标准包含一个名为 tokenURI 的方法,人们可以实现这个方法来告诉应用程序在哪里可以找到给定项的元数据。

function tokenURI(uint256 _tokenId) public view returns (string)
tokenURI 方法返回一个公有的 URL,通过URL返回一个 JSON 数据字典,类似于上面 CryptoKitty 的示例字典。这些元数据应该符合官方的 ERC721元数据标准,以便 OpenSea 之类的应用程序能够获取。

链下存储最简单的方法是在某个集中式服务器上,或者在像 AWS 这样的云存储解决方案上。当然,这也有缺点: 1)开发人员可以随意更改元数据; 2)如果服务挂掉,NFT的元数据可能会从原始源中消失。为了缓解问题2,现在有几个服务开始在自己的服务器上缓存元数据,以确保即使原始主机解决方案出现故障,也能有效地为用户服务。

然而,越来越多的开发人员,尤其是数字艺术领域的开发人员,正在使用IPFS来实现NFT的链下存储。IPFS 是一个p2p的文件存储系统,允许内容跨计算机托管,这样文件就可以在许多不同的位置复制。确切地说,是用另一个链来存储NFT的元数据。这样可以确保:

元数据是不可变的,因为它是由文件的散列唯一解决的;

只要有节点愿意承载数据,数据就会随着时间的推移持久化。

现在, Pinata 这样的服务通过处理部署和管理 IPFS 节点的基础设施,使开发人员的过程更加简单,备受期待的 Filecoin 网络可以在 IPFS 之上增加一个层,以激励节点托管文件。 

构建尝试—— NFT 的helloword

如上所述,所有的NFT都有所谓的元数据。基本上,我们发现在以太坊上存储图片真的很费劲,而且花费很大。如果存储一张8 x 8的图片,还算便宜,但是如果想要一张分辨率不错的图片,就需要花费更多的钱。但是,在 IPFS 中添加图片就比较容易,而且不需要运行服务器。

以下是来自Opensea 的一个教程摘要, 当然需要在钱包里放入 Rinkeby Testnet ETH 和 Rinkeby Testnet LINK 才能继续,具体所要做的步骤是:

使用 Chainlink VRF 建立一个可验证的随机 D&D 字符串

使用 IPFS 添加一个 tokenURI

在 OpenSea Marketplace 中添加这个随机的NFT

首先,在 bash _ profile 文件中设置环境变量如下:

export MNEMONIC='cat dog frog....'

export RINKEBY_RPC_URL='www.infura.io/asdfadsfafdadf'

接下来,clone 示例代码库:

git clone https://github.com/PatrickAlphaC/dungeons-and-dragons-nft

cd dungeons-and-dragons-nft

git checkout opensea-update

npm install

truffle migrate --reset --network rinkeby

然后,生成一个字符:

truffle exec scripts/fund-contract.js --network rinkeby

truffle exec scripts/generate-character.js --network rinkeby

truffle exec scripts/get-character.js --network rinkeby

这将创建一个新的随机统计字符!

我们可以免费获得一个 Etherscan API 密钥,并与链上的NFT进行交互,需要将 ETHERSCAN API的 key 设置为环境变量:

npm install truffle-plugin-verify

truffle run verify DungeonsAndDragonsCharacter --network rinkeby --license MIT

这将验证并发布这一智能合约,另外,还可以使用 oneclickdapp 并添加契约地址和 ABI,ABI可以在 build/contracts 文件夹中找到。

一旦创建了一个NFT,需要给它一个 tokenURI,是向外界展示NFT数据。这使得像图片这样的东西更容易存储,且不必浪费将它们添加到链上存储中的gas。NFT元数据的示例如下:

{
"name": "Name for it ",

"description": "Anything you want",

"image": "https://ipfs.io/ipfs/HASH_HERE?file.png",

"attributes": [...]
}

为了将NFT代表的一张图片和元数据线下存储到IPFS,需要下载相关的工具,包括IPFS,IPFS companion和Pinata。

IPFS companion 让我们可以在Chrome 这样的浏览器中本地查看 IPFS 数据。如果在浏览器中点击这个链接,就会知道 IPFS companion正在工作: IPFS https://IPFS.io/IPFS/qmtgqnhfbmkft9s8phkcdxbn1f5bg3q5hmbar4u6hotvb1?filename=chainlink_elf.png

一旦启动 IPFS 节点,就可以开始向其添加文件。首先要上传 NFT 的图像,然后,需要将元数据 JSON 对象添加到 IPFS 中,从部署的token中获取名称和属性,可以使用create-metadata.js来运行:

truffle exec scripts/create-metadata.js --network rinkeby
元数据 json 文件将是将是的 tokenURI,因此我们将修改 set-token-uri.js的 tokenId,并添加IPFS 的tokenURI:

truffle exec scripts/set-token-uri.js --network rinkeby
现在,可以得到这个 NFT 的地址,然后就前往 OpenSea 测试网市场(https://testnets.opensea.io/get-listed/step-two)来查看了甚至尝试售卖了。

NFT 的应用场景
自从2017年CryptoKitty问世以来,已有近万类、数千万枚NFT藏品铸造、流通、交易,发布到用户的手中,其中以游戏、卡牌、网络域名、加密艺术品居多。

将现实或者互联网世界里的“非对等权益”通过NFT的方式呈现之后,最本质的改变在于,NFT的价格发现机制将由原先的市场交易转变为权益的“隐含溢价”,每个希望持有或者转让NFT的用户会评估该NFT的非对等权益对于自身的价值究竟几何,在保持弱流动性基本特性不变的前提下,将极大的增强NFT的可交易性。  

NTF的应用场景很多,几乎会充满想象力的空间。

游戏
NFT在游戏行业很流行,因为这些令牌解决了一些固有的问题。例如,用作游戏中的宠物,武器道具,服装和其他的物品。使用NFT,这些特性可以很容易在不同的游戏中转移和使用。因此,NFT可以帮助推动游戏中的经济。

数字资产
例如,Decentraland,在这里,参与者可以购买虚拟土地。另一个更接近家庭的例子是 ENS (Ethereum Name Service,以太坊域名服务) ,它使用NFT买卖.ETH的域名。

另外,数字艺术家已经接受了NFT来创造基于NFT 的艺术品。然而,NFT 有如此大的吸引力是因为艺术家们可以在 NFT 市场上获得的利润。值得注意的是,2020年下半年,数字艺术家以最高的价格出售他们的产品。例如,在2020年9月,一件随着比特币价格变化的 NFT 数字艺术品卖出了262 ETH (当时为101,100美元)。

知识产权
NFT 可以代表一幅画,一首歌,一项专利,一段影片,一张照片,或者其他的知识产权。在这个领域,NFT起到的是专利局的作用。帮助每一个独一无二的东西进行版权登记,帮助其识别专利。

实体资产。房屋等不动产等其他的实物资产,可以用NFT来表示进行代币化。可以用作资产的流通等金融市场。

记录和身份证明
NFT 可以用来验证身份和出生证明,驾照,学历证书,医疗记录等方面。这些可以用数字形式进行安全保存,而防止被滥用或篡改。Nft 是打击身份盗用的理想工具,可以被数字化以代表身份的例子甚至可以是我们的外表。

金融
发票,订单,保险,账单等可以转变为 NFT,进行交易。特别地,NFT 正开始与DeFi融合,例如,DeFi 协议Yearn Finance,为任何虚拟货币资产开发了一种名为 Y.Insure 的保险产品。Y.Insure 利用 NFT 机制(ERC-721)来代表保单的独特性质。基本上,当定义保险单的独特特征时,标准的 ERC-20通证就显得“没有意义”了。

DeFi目前是通过跨链来解决抵押,通过保证金制度来解决杠杆,最终实现了类似于信用衍生一样的操作。有了杠杆、有了抵押、有了资金池。金融最基本的东西都具备了,理论上什么复杂的衍生品都能设计出来的。

小结
我们有很多数字产品,只是我们从未没有真正拥有。

事实上,NFT的影响并不仅限于数字商品的物质所有权。它延伸到与技术互动的情感体验ーー它改变了产品和消费的内容之间关系的方式。最终,让人们更多地控制自己的创作,更少地控制自己的用户,用户更多地控制自己的身份。这些影响是深远的,不仅仅是简单的所有权。像任何全新的创新技术一样,我们只能推测NFT将如何使用,我们只能拭目以待。

【参考资料与关联阅读】

https://coinmarketcap.com/alexandria/article/what-is-a-non-fungible-token-nft

https://blog.chain.link/build-deploy-and-sell-your-own-dynamic-nft/

https://dao2.io/liao-jie-nft-quan-mao-kan-zhe-pian-jiu-gou-liao/

https://decentraland.org/blog/technology/what-are-nfts/

https://opensea.io/blog/guides/non-fungible-tokens/

https://www.btcfans.com/article/33456

Web3.0,区块链后花园的姹紫嫣红

区块链性能提升:链上设计之道

区块链、货币和社交扩展性

区块链之比特币的潜在激励

学习IoT与区块链的融合

老码农眼中的区块链

Coin和Token的区别

比特币的学术谱系
————————————————
版权声明:本文为CSDN博主「半吊子全栈工匠」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wireless_com/article/details/114609306

NFT铸造
​ 说了NFT的独特,那我们再来谈谈它是怎么被铸造的,基于什么逻辑实现它的独一无二。

以下非同质化代币的铸造分析,原始代码参考以太坊ERC721 提案。

​ 首先非同质化代币的铸造会执行

​ _safeMint 函数,该函数存在两个参数,他们分别的作用是:

to:新铸的代币接受地址

tokenId:新铸代币的 id 序列

function _safeMint(address to, uint256 tokenId) internal virtual {
    _safeMint(to, tokenId, "");//接收以上两个参数加上空字符凑齐3个参数传入同名 _safeMint 函数(重载)
}
```​ 可以看到接下来调用三参数同名 _safeMint 函数,

function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {//接收_safeMint 函数传参
_mint(to, tokenId);//将传参 to 和 tokenId 传入 _mint 函数
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");//调用_checkOnERC721Received函数来检测函数接口合法性
}

​ 最后调用 _mint 函数进行铸币:

function _mint(address to, uint256 tokenId) internal virtual {//接收来自_safeMint 函数的传参
require(to != address(0), "ERC721: mint to the zero address");//校验传参地址是否为空(为假继续后续操作,为真终止操作)
require(!_exists(tokenId), "ERC721: token already minted");//接着校验 tokenId 是否已经存在(为假继续后续操作,为真终止操作)

_beforeTokenTransfer(address(0), to, tokenId);//初始化;

_balances[to] += 1;//在传参地址 to 上生成一个 token 
_owners[tokenId] = to;//将传参地址 to 与引索 tokenId 进行绑定

emit Transfer(address(0), to, tokenId);//触发 token 生成事件

}

​ 就这样一个独一无二的 NFT 被铸造出来了。总体过程如下:

合约中使用_safeMint 函数调用铸币函数并检查函数的 ERC721 函数接口合法性,该函数在 ERC721 中有所体现,代码如下:
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
private returns (bool)
{
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
// solhint-disable-next-line no-inline-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
在_mint函数中首先检查了地址是否是0地址,还有 tokenId 是否已存在。该 tokenId 在 ERC721 标准中生成规则是一个不可互换的通证。检测通过后为 to 地址铸币(相应的 tokenId ),同时记录余额与该 NFT 艺术品的归属者。
NFT铸造示例
​ 看到这,相信你也了解到什么是 NFT 了,来让我们通过部署一个 ERC721 智能合约来进行铸造演示。

​ 需要用到的工具有remix,metamask和IPFS。

将图片上传到 IPFS
​ 我选择制成 NFT 的是一张可爱的猫猫图片。

​ 在使用这张图片前我们需要对它进行一些处理,这里要用到 IPFS 工具:

打开终端初始化 IPFS repo;

$ ipfs init
1
再打开一个终端开启 daemon 服务;

$ ipfs daemon
1
在第一个终端中输入以下命令将图片加入到 IPFS 中,并复制下生成的 hash;

$ ipfs add 2.png
1
向 IPFS 添加 JOSN 文件,同样复制下生成的 hash。

$ ipfs add nft.json
1
JSON文件格式

{
"name": "NFT Art",
"description": "This image shows the true nature of NFT.",
"image": "https://ipfs.io/ipfs/QmWdRcjx6Yhjvu97qKjVhCj7Zj8wZpVuFu4aape1MTbxib",
}
1
2
3
4
5
合约代码
​ 我们直接通过模拟合约在 remix 上测试。

​ NFT 模拟测试合约如下,为了方便和安全,我们使用了 0xcert/ethereum-erc721 合约来创建我们的 NFT 合约。

// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

import "https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol";
import "https://github.com/0xcert/ethereum-erc721/src/contracts/ownership/ownable.sol";

contract NFT is NFTokenMetadata, Ownable {
uint256 public constant NFT_SIGN_BIT = 1 << 255;
uint256 public constant ID_PREFIX_MASK = uint256(~uint152(0)) << 104;
uint256 public totalSupply = 0;

constructor() {
nftName = "MaoMao NFT";
nftSymbol = "MMN";
}

function mint(address _to, uint256 tokenIdPre, string calldata _uri) external onlyOwner {// 铸币

uint256 _tokenId = NFT_SIGN_BIT | (tokenIdPre & ID_PREFIX_MASK) |
    (block.timestamp << 64) | uint64(totalSupply + 1);// 生成ID

_mint(_to, _tokenId);//为指定地址铸币
super._setTokenUri(_tokenId, _uri);//使用tokenId 和 JSON 文件的 URI 设置代币 URI

}
function batchMint(address _to, uint256[] memory tokenIdPres, string calldata _uri) external onlyOwner {// 批量铸币

uint256 length = tokenIdPres.length;

for (uint256 i = 0; i != length; ++i) {
    uint256 _tokenId = NFT_SIGN_BIT | (tokenIdPres[i] & ID_PREFIX_MASK) |
        (block.timestamp << 64) | uint64(totalSupply + 1);// 生成ID
    
    _mint(_to, _tokenId);//为指定地址铸币
    super._setTokenUri(_tokenId, _uri);//使用tokenId 和 JSON 文件的 URI 设置代币 URI
}

}

}
铸造 NFT
​ 使用 Injected Web3 进行部署。编译合约前一定要在 Metamask 上选择测试网络,我选择的是 Kovan 测试网络。

​ 现在进入 Remix 中的 Deployed Contracts 部分,展开部署的合约。你会看到一堆函数/方法。展开 mint 函数并添加以下参数:

在_to 中添加你的 Kovan 地址。
在 tokenIdPre 中输入任何数字值。
在_uri 字段中,添加获得的 JSON 文件的 URI。
点击交易,并从 metamask 确认交易。

​ 接下来在我们的钱包就可以看到一个名叫 MMN 的 NFT 已经生成了。

拓展&NFT随机数安全
​ 相信仔细阅读了测试合约代码的小伙伴会发现,我并没有直接使用传参 tokenIdPre 作为代币的标识,而是将它作为依据由算法生成的随机数来作为代币标识。为什么要这样呢?不知道大家有没有玩过盲盒——指消费者不能提前得知具体产品款式的玩具盒子,具有随机属性。很明显 NFT 同样适用于盲盒属性,只要适当的使用随机数就能有各种各样的 NFT 盲盒玩法。

​ 现实玩法如在 BlindBoxes dApp 中,创作者通过主智能合约在 xDai 生成空的收藏品盒,创作者将NFT存入NFT Holder(dApp部署在以太坊上的智能合约);NFT Holder 将其状态通过AMB同步到 xDAI 上的主智能合约;创作者通过主智能合约往收藏品盒中添加一个或多个 NFT,之后可以选择发布。这些发布的 NFT 会通过 RandomAura(基于 RANDAO 链上随机数生成器)引入随机性,确保盲盒的随机性。

​ 但是盲盒也可能不"盲",因为盲盒的随机性是有随机数生成器生成的,一但随机数生成器被破解,如各类预言机被破解事件,足以提醒我们要使用安全的随机数生成器。

​ 以下让我们来分析一些简单的盲盒随机化规则,谈谈其安全性:

function _randomRole(uint index) internal returns (uint8){
require(msg.sender == tx.origin, "human only");//仅允许个人地址调用该函数
uint result = (block.timestamp.mul(index)).mod(TOTAL_ROLE);//抽奖结果
return uint8(result);
}

​ 首先我们可以看到该函数仅允许被个人地址调用,这样可以杜绝黑客使用其它方法来调用该函数。

​ 接着就是最关键的抽奖结果的生成,一共涉及两个变量一个常量:

变量1:index 由调用该函数的个人决定
变量2:block.timestamp 由当前的区块决定
常量:TOTAL_ROLE 总量53不会改变
​ 这时问题就出现了,作为该函数的调用者一共能控制变量 index 和常量 TOTAL_ROLE,那如果黑客能控制最后一个变量,是不是他就能操作抽奖结果?

​ 而这并非不能办到。因为链上的数据都是可以计算和预测的,甚至矿工还可以提前计算结果。而当黑客能预测 block.timestamp 值时,也就相当于他控制了该变量。

​ 所以盲盒真的会不"盲",使用安全的随机数极为重要。

总结
​ 无论什么时代都会有人最求独一无二,数字化的世界里同样如此。NFT 的出现既是对人们追求独一无二欲望的满足,也是数字化时代认证方式的开拓。相信在不断完善的未来世界,NFT 一定能发挥出举足轻重的作用,但同时我们也不能对其安全掉以轻心。
————————————————
版权声明:本文为CSDN博主「虎皮熊233」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/S123456215/article/details/117355802