-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
使用 Merkle 树做白名单验证,简单来说就是将所有的白名单钱包地址做为 Merkle 树的叶节点生成一棵 Merkle 树,在部署的NFT 合约中只存储 Merkle 树的 root hash,这样避免了在合约中存储所有白名单地址带来的高额 gas 费用。在 mint 时,链下生成钱包地址的 Merkle proof,调用合约进行验证。
合约实现
在whitelist.sol中实现了传统mapping储存白名单的方式和Merkle树储存白名单的方式,因为使用mapping需要占用大量的存储空间,所以我们选择使用Merkle的方式来验证。
openzepplin MerkleProof
openzeppelin 提供了Merkle实现库,我们仅需要import '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol';
并且实现:
1.设置Merkle root hash
2. 提供external接口对 proof进行验证,MerkleProof.verify(proof, _merkleTreeRoot, keccak256(abi.encodePacked(leaf) 其中leaf传入调用者的地址,也就是白名单中的地址才能校验成功。
Merkle proof 证明生成
调用合约验证的 Merkle proof 需要在前端生成。生成过程需要用到 merkletreejs和 keccak256 两个库,前者用于创建 Merkle 树,后者用于生成哈希。
链下实现代码在Utils/helpers.js文件中:
- 获取 hardhat-deploy生成的地址,当作白名单测试地址。
- 生成白名单地址的Merkle树:
const leafNodes = whitelistAddresses.map((adr) => keccak256(adr));
const merkleTree = new MerkleTree(leafNodes, keccak256, {
sortPairs: true,
});- 对地址列表生成Merkle证明:
proofs: whitelistAddresses.map((addr) => merkleTree.getHexProof(keccak256(addr))),
生成证明格式:
Proof of 0xc12ae5Ba30Da6eB11978939379D383beb5Df9b33: [
'0x1575cc1dded49f942913392f94716824d29b8fa45876b2db6295d16a606533a4',
'0x6c42c6099e51e28eef8f19f71765bb42c571d5c7177996f177606138f65c0c2b',
'0xb0d6f760008340e3f60414d84b305702faa6418f44f31de07b10e05bf369eb3b',
'0x4c880bf401add28c4e51270dfe16b28c3ca1b3d263ff7c5863fc8214b4046364'
]验证过程
调用checkMerkleTreeRootForWhitelist 传入验证者address 和对应的 proof。
Metadata
Metadata
Assignees
Labels
No labels