常见盲盒实现方案

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

https://learnblockchain.cn/article/2939

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

https://mirror.xyz/0xC0329563206dd8d6565F2878FCEB189480Cd3197/XnOxEeg9z5rJu9tCZJ6SSs4hUzIUvWYDqED4ajFgXo8

解决方案

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

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

方案一

项目方统一开盒,这种比较简单,实际上就是修改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);

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

https://mirror.xyz/0xC0329563206dd8d6565F2878FCEB189480Cd3197/VXYRBEi79hZ6BmEy9TQRdQXpDaE_ik5t_SNOb_bwx4Q

2022-5-13更新

方案三

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

https://opensea.io/collection/zombieclub-token

前期准备

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

开盒模式

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

第一步先申请开盒

申请开盒
申请开盒

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

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

第二步开盒

开盒逻辑
开盒逻辑

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

总结

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

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