众所周知,NFT盲盒是一个比较大众的玩法,其中也有不少事故发生,比如提前泄露稀有度事件,这里有一篇分析很细致的文章,感兴趣的同学可以看看:

Hack Replay - SupDuck | 登链社区 | 区块链技术社区

Hack Replay – SupDuck | 登链社区 | 区块链技术社区
最近的NFT异常的火热,上一篇文章中分析了Samczsun提出的HashMasks这一NFT,对EIP721进行了简单的了解。但是在后续的沟通中,发现对于NFT,其意义远远超过了冰冷的EIP721. 同时也发现,自己对于NFT的理解是非常浅薄…
learnblockchain.cn

如果对opensea上图片是如何显示的不清楚,可以参考我上篇文章:

如何接入opensea?

如何接入opensea?
我们知道opensea是一个比较大的NFT交易市场,刚开始开发NFT的时候,有个任务是调研如何接入opensea,后来发现不愧是web3,不愧是去中心化,opensea不需要接入!只需要你的合约是符合协议的,opensea会自动扫描并导入你的合约。
mirror.xyz

解决方案

那么怎么能安全的公开透明的公布盲盒数据呢?

我这里总结从交互方式上分为两种:

方案一

项目方统一开盒,这种比较简单,实际上就是修改baseURI,因为NFT的图片是由接口tokenURI控制的,所以只要修改tokenURI就能统一修改图片路径

/**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

拿图片存放在ipfs举例,开盒前的盲盒图上传至ipfs,代码中判断未开盒状态,直接返回盲盒图对应的配置文件地址即可;然后把开盒后的图片放到一个文件夹中,要求图片名跟tokenId对应上,把整个文件夹批量上传,然后把文件夹的CID访问路径设置为baseURI即可。

优点是简单易懂,gasfee低,缺点玩法比较单一,与现实中盲盒不太一样,而且项目方在开盒后,还需要证明开盒后的图片是在出售盲盒前就定死的了(实际上很多项目都没证明,甚至是图片都没上ipfs或arweave,而是存储在中心化服务器上)(证明方式:可以在盲盒合约里写上开盒后图片CID的hash值)。

方案二

玩家自己控制开盒,每个token可以自主选择什么时候开盒,一般需要玩家自己去项目方官网发起一笔开盒交易。该方案优点比较明显,盲盒与实物分开售卖,而且玩家可以自己决定什么时候开盒,与现实的盲盒玩法几乎一致,缺点是实现难度略高,gasfee稍高(开盒也需要玩家掏gasfee);

具体实现可以参考我另一篇文章:

solidity如何实现抽取池

solidity如何实现抽取池
开发智能合约的时候,可能会遇到从固定池子中随机抽取不重复item的需求。
mirror.xyz

2022-5-13更新

方案三

方案二有个点就是一旦有一个NFT开盒后,ipfs上的文件夹地址就暴露了,那么剩下的盲盒长啥样也都能看到了,只是因为开盒是随机映射的,所以还不确定哪个tokenId能开出哪张图。今天看到有个项目规避了这个问题(前提是项目方不暴露):

Just a moment...

Just a moment…
opensea.io needs to review the security of your connection before proceeding.
opensea.io

前期准备

项目方提前把图片上传至ipfs,然后把图片的cid排好的顺序组织成了Merkle Tree,将root hash值保存至合约上,这样可以证明项目方没有擅自修改图片顺序,也没有换图

开盒模式

该项目使用两步走的开盒方式

第一步先申请开盒

申请开盒
申请开盒

使用的是chainlink的VRF产生随机数,用来从tokenIdMap中随机抽一个index出来,这个跟我之前分享的随机数抽取池是类似的做法,可以参考了解。

通过这一步,拿到了一个随机数,与剩余未开盒数取模,得到一个随机的index,他这里叫revealId

第二步开盒

开盒逻辑
开盒逻辑

可以看到传进来的_index需要跟上一步获取的revealId一致,确保是合法的;然后把经过一定算法encode过的byte数组保存起来,tokenURI接口获取时,解析得到CID拼接前缀ipfs://后返回,完成真实图片的披露

总结

优点:纯随机不可预测,除项目方提前知道所有图片长啥样外,其他人只有到开盒那一瞬间才知道

缺点:开盒需要两步,且里面逻辑较复杂,导致gasfee较贵(专门去对比了下,任何一步的操作都比mint要贵)

原文 https://mirror.xyz/0xC0329563206dd8d6565F2878FCEB189480Cd3197/sAMkv3hK5MXJ0E_KzUqUtR3C6r06K5QXiOoRvL4uPF4