# 如何利用 MerkleTree 来实现 NFT的公平开图，以及如何验证

By [web3nomad.eth](https://paragraph.com/@web3nomad) · 2022-05-21

---

HippyGhosts 终于在 5/20 如期上线，在社区铸造的 1500 个 ghosts 中有 20 个稀有款，有部分已经被 mint 出来，例如下图，他们的 Token ID 分别是 205 和 268，一个单眼的 Ninja，一个金属 Ninja 。🥳

**#205**

!0bf413340f0db024d3621259bc4140f9defad64ac78725d90f569a131be561f4

**#268**

!413a4990d7788b4449ea4e322b03e582531ec699d4c08440a1c60f1031e425e6

### 为什么我们可以在文章里提前公开图片？

然后有人问我一个问题，因为现在 HippyGhosts 还没有开图，我是不是会根据 mint 的结果来对应分配稀有款，或者之后给某些地址开出特定的图？答案是不会。

因为所有 9999 个 HippyGhosts 的图片已经冻结，这些图片的 base64 编码进行 keccak256 哈希以后构成的 MerkleTree 已经提前生成并记录在了合约里。每当一个 Ghost 的图片公开了以后，任何人都可以验证图片的完整性和图片的位置（也就是 Token ID）。

所以，我这会儿说的稀有款，它的编号 #205 和它的图片内容，都是提前已经确定好的。而“提前确定好的图片内容和位置“这两个事实，任何人都可以在图片公开以后验证。

同理，未来开图以后，看到的每一张图，它的顺序和内容也已经提前确定，并且可以被验证，这样以确保未来开图过程的公平。

### 那比如说，如何验证上面这张图？

现在这个 HippyGhosts #205 提前开图，我需要验证，这个图不是我现在临时决定的，并且这个图，我在 mint 之前，已经把它排在了 9999 个图中的第 205 位。

首先，在新窗口打开这个图片，浏览器中可以看到这个图片的 base64 编码，这就是图片的数据，对这个数据进行 `keccak256` 哈希后，得到

`0bf413340f0db024d3621259bc4140f9defad64ac78725d90f569a131be561f4`

然后在 HippyGhosts 的 MerkleTree 中寻找这一串哈希，位置为第 205 个叶子结点

`https://api.hippyghosts.io/~/storage/merkletree`

因为这个 MerkleTree 是在 HippyGhosts 自己的服务器上的，接下来就是确认它的数据是否可信，首先从 MerkleTree 的第一行获得 MerkleRoot

`58d247a687ef48f010e2e6107a04d575787163cfb0d70543c421a5001e9f5aab`

同时这个 MerkleRoot 数据也存在于 HippyGhosts 的 Renderer 合约源代码中

`https://etherscan.io/address/0x856bd414d7c4718f844795b30510af2f5fee2ee1#code#F9#L10`

这里要提起一个叫做隔离见证的东西，意思就是：就是一个结果的出现，需要依赖于一个事实的发生。在这个例子中，**结果**就是 MerkleRoot，**事实**就是所有图片的内容和顺序。

`58d247a687ef48f010e2e6107a04d575787163cfb0d70543c421a5001e9f5aab`

现在我们在合约代码中发现了**结果**（即MerkleRoot），这个结果是在合约部署的时候就出现了，自然就是在 mint 之前，那么，所有图片的内容和顺序这个**事实**也一定发生在合约部署之前。这是因为根据 MerkleTree 的特点，如果图片的内容和顺序不同，MerkleRoot 也会变化，那么对于一个确定的 MerkleRoot，就一定有确定的图片内容和顺序。

讲完了，当然这不是公平开图的最有思路，只是我自己比较喜欢用 MerkleTree 来处理它。如果在公平开图这个事情上有其他想法，欢迎一起交流。

🔗 [https://muselink.cc/web3nomad](https://muselink.cc/web3nomad)

---

*Originally published on [web3nomad.eth](https://paragraph.com/@web3nomad/merkletree-nft)*
