Crypto Coven 加密女巫 NFT 合约解读
本文主要是对 @mannynotfound 的推文 https://twitter.com/mannynotfound/status/1470535464922845187 的整理和补充。
加密女巫的合约代码堪称艺术品。代码出自工程师 Matthew Di Ferrante(@matthewdif),涉及 gas 优化,修改器以及 Opensea 预授权等诸多优化措施,对于学习 NFT 合约是个很好的参考材料。
基本情况
名称;Crypto Coven
符号: WITCH
合约地址:0x5180db8f5c931aae63c74266b211f580155ecac8
合约代码地址:https://etherscan.io/address/0x5180db8f5c931aae63c74266b211f580155ecac8#code
Solidity版本: ^0.8.0
这个 banner 可以体会到项目方想要做的不是像 Crypto Punks 或者其他像素风格 NFT 一样的作品。
/* |
避免使用 ERC721Enumerable
使用 ERC721Enumerable
会带来大量 gas 消耗,合约中使用 ERC721 + Counters
的方式节省 Gas。主要原因是由于 totalSupply()
函数的使用。
详细可以阅读文章:Cut Minting Gas Costs By Up To 70% With One Smart Contract Tweak
contract CryptoCoven is ERC721, IERC2981, Ownable, ReentrancyGuard { |
修改器让代码更简洁和清晰
合约中使用修改器对权限进行控制,其中包括:
publicSaleActive
公开销售状态communitySaleActive
社区销售状态maxWitchesPerWallet
每个钱包最大 token 数量canMintWitches
控制token总数量canGiftWitches
isCorrectPayment
判断购买时价格是否正确isValidMerkleProof
用于白名单机制中的 Merkle 验证
这些修改器可以使得权限控制更简便,代码的可读性也大大提升。
// ============ ACCESS CONTROL/SANITY MODIFIERS ============ |
NFT 素材的存储
NFT 项目都需要包含图片的存储,合约将 NFT 对应的元信息存储在 IPFS 中,并将对应的图片存储都在 Amazon S3 存储中。
string private baseURI; |
比如 tokenId
为 1
的 NFT,对应的 tokenURI
为 ipfs://QmZHKZDavkvNfA9gSAg7HALv8jF7BJaKjUc9U2LSuvUySB/1.json
,在 IPFS 中可以看到这里面的内容为:
{ |
其中包含女巫的ID,名称,图片地址,属性等信息。
不得不说,如果 Amazon S3 出问题了,可能这些图片就没法显示了。
使用 Merkle 证明实现白名单机制
对于预售,项目方使用白名单方式进行,而对于白名单验证,合约中使用 Merkle 证明的方式进行验证。
在 mint 时,只需发送正确的 Merkle 证明来验证即可实现白名单功能,这个方法不仅效率高,而且省去了在合约中存储所有白名单地址造成的 Gas 消耗。
modifier isValidMerkleProof(bytes32[] calldata merkleProof, bytes32 root) { |
详细细节可以参考我之前的一篇文章:
预先批准 Opensea 合约
可以看到在 OpenSea 上列出这些 NFT 费用为 0 gas,因为合约预先批准了 OpenSea 合约以节省用户的 gas,同时合约还包括一个紧急功能来消除这种行为!
/** |
为了防止 Opensea 关闭或者被入侵,合约可以通过 setIsOpenSeaProxyActive
方法关闭预先批准。
// function to disable gasless listings for security in case |
ERC165
这是一种发布并能检测到一个智能合约实现了什么接口的标准,用于实现对合约实现的接口的查询。这个标准需要实现 suppoetsInterface
方法:
interface ERC165 { |
加密女巫实现复写这个方法是因为它额外实现了 EIP2981 这个标准,需要指出。
function supportsInterface(bytes4 interfaceId) |
EIP2981:NFT 版税标准
EIP-2981 实现了标准化的版税信息检索,可被任何类型的 NFT 市场接受。EIP-2981 支持所有市场检索特定 NFT 的版税支付信息,从而实现无论 NFT 在哪个市场出售或转售都可以实现准确的版税支付。
NFT 市场和个人可通过检索版税支付信息 royaltyInfo()
来实施该标准,它指定为特定的 NFT 销售价格向指定的单一地址支付特定比例的金额。对于特定的 tokenId
和 salePrice
,在请求时需提供一个版税接收者的地址和要支付的预期版税金额(百分比表示)。
女巫合约规定了 5% 的版税,但是这个标准并不是强制性的,需要靠市场去实施此标准。
/** |
不太确定此函数中的注释 See {IERC165-royaltyInfo}.
是否正确,需要确认。
其他细节
-
没有
tokensOfOwner
方法可能是基于女巫NFT的具体场景与优化 Gas 做的权衡,查询 token 所有者的功能需要靠 Opensea 的 API 或者 The Graph 去实现。
-
在没有外部调用的函数中也加了
nonReentrant
-
msg.sender
可能是合约 -
对
onlyOwner
也加了nonReentrant
,避免可能的被利用。