每当一款类似于“Bored Ape Yacht Club”这种 PFP 风格NFT集合推出时,为每一个NFT使用一个占位符图像,并且只有在所有 NFT 都被创建后才显示最终的 NFT 的方式,已经成为一种常见的做法。我们可以称这种方式为预披露机制。
这是一个重要的操作,因为没有它,人们可以根据元数据暴露的特性的稀缺性来选择创建哪些NFT。
在开始构建此功能之前,让我们先看一下业务需求:
- 隐藏代币和元数据,直到所有代币都被铸造。
- 一旦用户铸造了代币,就向他们发送一个“pre-reveal”版本的代币。
- 允许合约所有者“显示”集合中的所有代币。
我们的智能合约负责返回每个代币 metadata.json
文件所在的 URL。
解决上述问题的方法是创建一个“pre-reveal”元数据文件,并将其上传到某处。这个“pre-reveal URI”是在显示发生之前,我们希望为每个代币返回的URI。
在此之后,我们能够使用一个新URL来更新智能合约,该URL可用于生成正确的代币URI。
例如,如果我们已经将所有的代币上传到一个响应为 https://exmaple.org/tokens/:tokenId
的 web 服务器上,那么我们希望用自己的 baseURI(https://example.org/tokens/
) 来更新智能合约,这样可以通过简单地将 tokenID
附加到 baseURI
来轻松地生成正确的 tokenURI
。
有了这些知识,现可以将问题重新定义为智能合约的更具体的要求:
- 当集合尚未显示时,它应该返回通用元数据。
- 它应该允许合约所有者更新
baseURI
。 - 当显示代币时,它应该返回正确的元数据。
实现 NFT pre-reveal 功能
假设我们正在为 NFT 集合开发一个智能合约,该集合扩展了通常的 OpenZeppelinERC721
来实现。
如果检查ERC721.sol
合约,就会发现tokenURI
实现了一个功能。
这个功能就是上图中 OpenZeppelin 对 tokenURI
的实现。这段代码主要是把 baseURI
与正在检索的 tokenID
连接起来。
这对于 AFTER reveal 非常有用,但是对于 pre-reveal,我们需要重写这个函数来返回 pre-reveal URI:
可以注意到在这里引用了两个全局变量:isRevealed
和 preRevealURI
。可以随心所欲地实现它们,但最简单的方法是,在合约的顶部定义它们:
接下来,我们需要创建一个函数来“显示”代币。
上面的 reveal
函数将传递的 baseURI
保存到一个名为 postRevealBaseURI
的全局变量中,并将 isreveal
布尔值设置为 true
。
将 _isreveal
布尔值设置为 true
,然后我们之前编写的 tokenURI
函数将推迟到父类的实现。
这个实现调用_baseURI
函数来检索基本URI。
如果检查该实现,我们可以看到它实际上可以被覆盖:
让我们使用 OpenZeppelin 并重写 _baseURI
函数来返回正确的基本 URI!
至此,我们便已了解了一种实现 NFT pre-reveal 预披露机制的简单、安全且有效的方法。