查看原文
其他

如何在NFT(ERC721)中获取随机数

Chainlink Chainlink预言机 2023-12-13



原文链接:https://blog.chain.link/random-numbers-nft-erc721/

(文中链接请复制至浏览器打开)


介绍


在遵循ERC721(http://erc721.org/)标准的非同质化代币(NFT)中生成随机数一直是智能合约开发者面临的难题。现在,Chainlink VRF已经在主网上线,基于Solidity的智能合约可以无缝生成防篡改的链上随机数,这些随机数可以证明是公平的,并且有密码学证明支持。有了Chainlink VRF,创建需要安全随机性来源的动态NFT变得非常简单、安全。虽然Chainlink也可以使用链外数据源为NFT实现任何类型的动态属性,但我们将专注于使用ERC721的随机数,或NFT。


在本教程中,我们将在以太坊区块链上构建一个龙与地下城角色!D&D(Dungeons and Dragons)是一款流行的角色扮演游戏(RPG),人们在游戏中创建角色并进行冒险。创建角色的重要环节之一是给他们赋予属性或统计数据,以显示他们的力量、敏捷、智力等。为了在区块链上为他们的统计数据创建真正的随机数,我们将展示如何使用Chainlink VRF给你的角色随机属性。使用Chainlink VRF,区块链中的随机数生成很简单!


什么是NFT?


NFT(遵循ERC721标准)定义了一个框架,用于制作独一无二且彼此不同的代币(因此被称为非同质化),而流行的ERC20标准则定义了 "同质化 "的代币,这意味着代币都可以互换,并保证具有相同的价值。"同质化 "货币的例子是美元、欧元和日元,而可互换区块链代币的例子是AAVE、SNX和YFI。在这些情况下,1个同质化的代币等于1个同类的另一个代币,就像1美元等于1美元,1LINK等于1LINK一样。然而,NFT/ ERC721是不同的,因为每个代币都是独一无二的,并不代表相同的价值或可互换的项目。


由于所有的NFT都是独一无二的,它们可以代表现实世界资产的代币化所有权要求,如一块特定的土地,或数字资产的实际所有权,如稀有的数字交易卡。而且它们越来越受欢迎。你可以参考OpenSea的NFT圣经来阅读更多内容。


构建你的随机角色


我们要看的是创造一个具有D&D角色六大属性的角色,即:


uint256 strength;uint256 dexterity;uint256 constitution;uint256 intelligence;uint256 wisdom;uint256 charisma;


角色还包含:


uint256 experience;string name;


所以我们可以把它们的等级提高,并给它们起一个有趣的名字。


我们在这里采取了一些自由的做法,并没有100%遵循龙与地下城的指导,但如果你想更准确地表现游戏,这可以很容易地修改。


这份合约应该确立以下内容:

1. 允许你转让NFT的所有权 和所有其他NFT标准。

2. 给这个角色一个名字和随机属性。


我们不去制作合约的动态,但请继续关注未来的一篇文章,它将在我们在这里学到的知识的基础上构建!


我们已经为你建立了代码仓库,我们将介绍如何使用代码仓库开始工作!


克隆代码


git clone https://github.com/PatrickAlphaC/dungeons-and-dragons-nftcd dungeons-and-dragons-nftnpm install


设置环境变量


你需要一个`MNEMONIC`和一个rinkeby网络的 `RINKEBY_RPC_URL`环境变量。`MNEMONIC`是你的钱包的助记词。你可以从节点提供者服务中找到一个`RINKEBY_RPC_URL`,比如Infura(https://infura.io/)。


然后,要么在`bash_profile`文件中设置它们,要么将它们导出到你的终端,比如:


export MNEMONIC='cat dog frog....'export RINKEBY_RPC_URL='www.infura.io/YOUR_PROJECT_ID_HERE'


代码目录中有什么


目录中有我们所有的模板代码,但真正的魔法是在`DungeonsAndDragonsCharacter.sol`文件中。我们可以看到它开始时是一个普通的Solidity文件,但我们在顶部有一些导入:


pragma solidity ^0.6.6;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";import "@openzeppelin/contracts/access/Ownable.sol";import "@openzeppelin/contracts/utils/Strings.sol";
contract DungeonsAndDragonsCharacter is ERC721, VRFConsumerBase, Ownable {


OpenZepplin是一个包的集合,它让Solidity和智能合约工程师的开发工作变得更轻松。如果你之前没有用过它,那就准备好多用它吧!由于ERC721只是一个代币标准,每一个ERC721应该都差不多,所以我们知道我们可以用一个模板就可以了。我们导入的`ERC721.sol`文件定义了一个NFT的所有标准。我们只要在合同中继承它,定义`contract DungeonsAndDragonsCharacter is ERC721`。我们需要`VRFConsumerBase.sol`来与Chainlink VRF交互,并获得随机数。最后两个导入只是帮助我们处理权限和与字符串的工作。


角色结构体和构造函数


在Character结构体中定义了我们的角色将具有的属性,并且制作了一个角色列表,这样就可以跟踪每一个被创建的角色。由于我们使用数组来存储字符列表,每个字符在数组中都会有一个唯一的 ID 来定义它。这就是所谓的`tokenId`,我们将更多地引用它。


struct Character {    uint256 strength; uint256 dexterity; uint256 constitution; uint256 intelligence; uint256 wisdom; uint256 charisma; uint256 experience; string name;   }
Character[] public characters;


定义好之后,我们可以创建构造函数。


constructor() public VRFConsumerBase(VRFCoordinator, LinkToken) ERC721("DungeonsAndDragonsCharacter", "D&D") { keyHash = 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311; fee = 0.1 * 10**18; // 0.1 LINK }


对应传入`VRFConsumerBase`和ERC721参数。Chainlink VRF需要VRF协调器地址和LinkToken地址。我们已经在Rinkeby网络中硬编码这些地址了。还有一些其他变量为Chainlink VRF定义,比如keyHash和fee。你可以在Chainlink VRF文档(https://docs.chain.link/docs/chainlink-vrf/)中阅读更多关于这些变量的作用。`ERC721("DungeonsAndDragonsCharacter", "D&D")`这一行定义了NFT的名称,然后是它的代币符号。`"D&D"`将是MetaMask和NFT市场中显示的内容。


生成你的随机字符


我们希望角色的六个属性中的每一个都有随机统计,但我们希望能够自己决定角色的名字!一个简单的调用Chainlink VRF允许我们在这个NFT / ERC721中生成随机数。在我们的请求函数中,不需要做太多的事情,只需要给新的角色一个名字,和一个`userProvidedSeed`。我们给它的种子是用来给VRF协调器验证所提供的数字是否真的是随机的。你可以选择任何你喜欢的种子,你可以阅读关于选择随机种子的文章来了解更多。


function requestNewRandomCharacter(     uint256 userProvidedSeed,     string memory name      public returns (bytes32) { require( LINK.balanceOf(address(this)) >= fee,"Not enough LINK - fill contract with faucet" ); bytes32 requestId = requestRandomness(keyHash, fee, userProvidedSeed); requestToCharacterName[requestId] = name; requestToSender[requestId] = msg.sender;return requestId; }


我们要跟踪`requestId`,这样当随机数获取到时,我们就可以把它映射到我们正在创建的角色上。这将启动Chainlink Job,需要等待Chainlink节点回调到我们的合约即可!你可以在Chainlink文档中阅读更多关于请求模型(https://docs.chain.link/docs/architecture-request-model/)的内容,了解更多关于发送Chainlink请求的工作原理。


Chainlink节点完成了对请求的处理,它就会通过调用 `fulfillRandomness` 函数来响应。这个函数包含了给出属性的计算,将角色添加到列表中,以及铸造NFT。


function fulfillRandomness(bytes32 requestId, uint256 randomNumber) internal override{ uint256 newId = characters.length; uint256 strength = ((randomNumber % 100) % 18); uint256 dexterity = (((randomNumber % 10000) / 100) % 18); uint256 constitution = (((randomNumber % 1000000) / 10000) % 18); uint256 intelligence = (((randomNumber % 100000000) / 1000000) % 18); uint256 wisdom = (((randomNumber % 10000000000) / 100000000) % 18);     uint256 charisma = (((randomNumber % 1000000000000) / 10000000000) %18); uint256 experience = 0;
characters.push( Character( strength,               dexterity, constitution, intelligence,               wisdom, charisma, experience, requestToCharacterName[requestId] ));_safeMint(requestToSender[requestId], newId);}


可以看到,只是用一次随机数来创建所有六个属性。使用取模运算对返回的大随机数取一个子集。如果我们不想这样做,我们也可以直接调用Chainlink VRF六次,但这种方式的效果是一样的。返回的随机数的最后两位数字用于强度,前面的两位数字用于敏捷,以此类推。这与CryptoKitties使用基因给猫咪赋值的方式类似。


*需要注意的是:做位操作会比我们这里的方式更有效率,但这样更容易理解,所以我们不必去研究位操作的工作原理。*


`_safeMint`是继承自`ERC721.sol`的函数,它允许我们跟踪ERC721的所有者。这一点很重要,特别是当你希望你的NFT采取一些行动,但你不希望其他人能够采取这种行动。我们将在下一篇NFT文章中了解更多的信息。


我们将使用Truffle和Chainlink,所以如果你不熟悉Truffle,这篇关于[如何使用Chainlink With Truffle的博文](将给你一个复习的机会,但我们也会在这篇博文中介绍所有的命令!


部署和快速启动


现在我们知道是怎么回事了,让我们来部署我们的随机NFT吧!你需要一些Rinkeby LINK(https://faucets.chain.link/)和Rinkeby ETH(https://faucet.rinkeby.io/)来运行这些脚本。


truffle migrate --reset --network rinkebytruffle exec scripts/fund-contract.js --network rinkebytruffle exec scripts/generate-character.js --network rinkebytruffle exec scripts/get-character.js --network rinkeby


上述命令做了下面这些事情:

1. 部署NFT合约

2. 向合约注资以便可以发起Chainlink VRF调用

3. 用Chainlink VRF调用生成角色

4. 返回NFT值


部署完毕,你还可以验证合约,甚至可以使用etherscan插件在Etherscan上阅读合约。你需要获得一个Etherscan API密钥(https://etherscan.io/apis),并设置环境变量`ETHSCAN_API_KEY`。之后运行:


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


然后它会给你一个Etherscan上的NFT链接。你可以在Etherscan上阅读合约内容。



这样你就进入到可以与合约互动的页面。如果你进入角色部分,你可以输入我们刚刚生成的tokenId,0,然后就可以看到你的新D&D角色的统计信息了。



你可以查看Rinkeyby的这个合约的例子。其中有几个角色的名字很有意思!


总结

使用Chainlink VRF在NFT中随机数很容易,使用之后会有一个全新的世界可以探索。我们在这里只是触及到了表面,所以请期待下一篇关于在市场上销售它们、渲染图像和使用元数据的博客。我们很想看到一些使用Chainlink VRF创建的很棒的角色和游戏,为它们提供动力,做到真正公平。如果你打造了一款酷炫的NFT #PoweredByChainlink,一定要在推特上告诉我们!


如果你是一名开发者,并希望将你的智能合约连接到链外数据和系统,请访问开发者文档并加入Discord上的技术讨论。如果你想安排一个电话,更深入地讨论整合问题,请在这里联系我们。


智能合约开发者正在NFT中建设一个全新的随机世界。你会成为引领这一潮流的先驱者之一吗?


Chainlink 2.0白皮书中文版已于日前发布,想要了解更多关于Chainlink 2.0的内容细节,请扫描下方二维码▼


END


▲获取Chainlink官方最新资讯

加入 Chainlink官方社区▼


Chainlink 官方渠道
QQ群: 6135525 

微博:  https://weibo.com/chainlinkofficial
知乎:https://www.zhihu.com/people/chainlink
SegmentFault:https://segmentfault.com/u/chainlink
币乎:  https://bihu.com/people/1869894547
GitHub:  https://github.com/smartcontractkit/chainlink
Discord:   https://discord.gg/aSK4zew
Twitter:  https://twitter.com/chainlink
中文 Twitter: https://twitter.com/ChainlinkChina
Telegram:  https://t.me/chainlinkofficial
合作联系:  china@smartcontract.com

点击“阅读原文” 进入 Chainlink中文官网

继续滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存