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

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

解决方案
那么怎么能安全的公开透明的公布盲盒数据呢?
我这里总结从交互方式上分为两种:
方案一
项目方统一开盒,这种比较简单,实际上就是修改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);
具体实现可以参考我另一篇文章:

2022-5-13更新
方案三
方案二有个点就是一旦有一个NFT开盒后,ipfs上的文件夹地址就暴露了,那么剩下的盲盒长啥样也都能看到了,只是因为开盒是随机映射的,所以还不确定哪个tokenId能开出哪张图。今天看到有个项目规避了这个问题(前提是项目方不暴露):
前期准备
项目方提前把图片上传至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