ERC721是比ERC20更复杂的标准,具有多个可选扩展名,并且分为多个合约。 OpenZeppelin合约 提供了灵活的组合方式以及自定义有用的扩展。本文讲解以OpenZeppelin合约为目标对象。
构建ERC721代币合同 我们将使用ERC721来跟踪游戏中的装备条目,每个条目都有各自独特的属性。 每当要奖励给玩家时,便会铸造(mint)并发送给他们。 玩家可以自由保留自己的代币,也可以与自己认为合适的其他人进行交易,就像区块链上的任何其他资产一样! 请注意,任何帐户都可以将awardItem称为铸造(mint)。 为了限制可以创建项目的帐户,我们可以添加访问控制 。
合约如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 pragma solidity ^0.6 .0 ; import "@openzeppelin/contracts/token/ERC721/ERC721.sol" ;import "@openzeppelin/contracts/utils/Counters.sol" ;contract GameItem is ERC721 { using Counters for Counters.Counter; Counters.Counter private _tokenIds; constructor ( ) public ERC721 ("GameItem" , "ITM" ) {} function awardItem (address player, string memory tokenURI ) public returns (uint256 ) { _tokenIds.increment(); uint256 newItemId = _tokenIds.current(); _mint(player, newItemId); _setTokenURI(newItemId, tokenURI); return newItemId; } }
ERC721合约包括了标准扩展(IERC721Metadata
和IERC721Enumerable
)。 这就是_setTokenURI方法的来源:我们使用它来存储项目的元数据。
另请注意:与ERC20不同,ERC721缺少小数,因为每个令牌都是不同的,并且无法分区。
新项目示例:
1 2 3 4 > gameItem.awardItem(playerAddress, "https://game.example/item-id-8u5h2m.json" ) Transaction successful. Transaction hash: 0x... Events emitted: - Transfer(0x0000000000000000000000000000000000000000, playerAddress, 7)
查询每个项目的所有者和元数据:
1 2 3 4 > gameItem.ownerOf(7) playerAddress > gameItem.tokenURI(7) "https://game.example/item-id-8u5h2m.json"
此tokenURI应该解析为一个类似于以下内容的JSON文档:
1 2 3 4 5 6 { "name" : "Thor's hammer" , "description" : "Mjölnir, the legendary hammer of the Norse god of thunder." , "image" : "https://game.example/item-id-8u5h2m.png" , "strength" : 20 }
有关tokenURI元数据JSON架构的更多信息,请参考==>https://eips.ethereum.org/EIPS/eip-721
ERC721 合约的前置功能 ERC721可用的预设有ERC721PresetMinterPauserAutoId。它已预设为允许Token铸造(创建),停止所有令牌传输(暂停),并允许持有人焚毁(销毁)其Token。合同使用访问控制来控制对铸造和暂停功能的访问。部署合同的帐户将被授予minter 和pauser 角色,以及默认的admin角色。
无需编写任何Solidity代码即可立即部署此合同。它可以原样用于快速原型制作和测试,但也适用于生产环境。
关联内容 ==> https://willzhuang.github.io/2019/07/04/ERC20-721Token的发行-冻结-多方签名功能