> For the complete documentation index, see [llms.txt](https://8olidity.gitbook.io/qu-kuai-lian-bi-ji/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://8olidity.gitbook.io/qu-kuai-lian-bi-ji/ji-ben-zhi-shi/merkle-tree-ben-di-ce-shi-js-and-solidity.md).

# Merkle Tree本地测试(js and solidity)

### JS生成MerKle Tree

代码如下，需要安装<mark style="color:blue;">`merkletreejs`</mark> 和 <mark style="color:blue;">`keccak256`</mark>

```
const { MerkleTree } = require('merkletreejs');
cost keccak256 = require('keccak256')

const whitelistAddress = ['0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', 
'0xA5A18D604b438B405a1C5a11F1cb923DBaC7bA1B', ' 0x9470F6dE2A4787a534CD21C8E115CFE1513189DA']

const leafNodes = whitelistAddress.map((addr) => keccak256(addr))
const merkleTree = new MerkleTree(leafNodes, keccak256, { sortPairs: true })
const rootHash = merkleTree.getHexRoot()
console.log('merkleTree:', merkleTree.toString())
console.log('rootHash:', merkleTree.getHexRoot())


console.log("-----------------");
console.log("生成 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 proof");

const proof = merkleTree.getHexProof(keccak256("0x5B38Da6a701c568545dCfcB03FcB875f56beddC4"));
console.log("proof:",proof);  // 只有在列表中的才可以生成出proof

console.log("------------------");
console.log("认证 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 是否在白名单中");
const v = merkleTree.verify(proof,keccak256("0x5B38Da6a701c568545dCfcB03FcB875f56beddC4"),rootHash);
console.log(v);


```

针对whitelistAddress生成root,再针对0x5B38Da6a701c568545dCfcB03FcB875f56beddC4生成proof，最后用proof和0x5B38Da6a701c568545dCfcB03FcB875f56beddC4进行校验判断

运行之后得到下面的结果

```
merkleTree: └─ 50c87af1a426b59a17b6c16a9de10875012947e06ea6c89494fb3afe492e1d78
   ├─ 3fb0a9cab2f2350ff96e70c80f6797c9549662d480a67ec9a00abc31264c7bbb
   │  ├─ 5931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229
   │  └─ 67291d3d99b77ed052d1c50f719ae942e92c20b63f93fbad3bc707182f2256bf
   └─ 8c1b4d3f6998419f132d37bd1138d350ee57df13b6076744bccb5f6b8c8a305a
      └─ 8c1b4d3f6998419f132d37bd1138d350ee57df13b6076744bccb5f6b8c8a305a

rootHash: 0x50c87af1a426b59a17b6c16a9de10875012947e06ea6c89494fb3afe492e1d78
-----------------
生成 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 proof
proof: [
  '0x67291d3d99b77ed052d1c50f719ae942e92c20b63f93fbad3bc707182f2256bf',
  '0x8c1b4d3f6998419f132d37bd1138d350ee57df13b6076744bccb5f6b8c8a305a'
]
------------------
认证 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 是否在白名单中
true
```

### solidity校验

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;

import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MerkleTest is Ownable {
    bytes32 private root;
    function isWhiteList(address _address, bytes32[] calldata _merkleProof) public view returns (bool){
            bytes32 leaf = keccak256(abi.encodePacked(_address));
            require(MerkleProof.verify(_merkleProof, root, leaf), "Incorrect proof");
            return true; // Or you can mint tokens here
        }
    function setMercleRoot (bytes32 _merkleRoot) public onlyOwner {              
        root = _merkleRoot;
    }
 
}
```

1.先设置好root

2.输入address校验

输入proof的时候有坑,一定要双引号

\["0x67291d3d99b77ed052d1c50f719ae942e92c20b63f93fbad3bc707182f2256bf","0x8c1b4d3f6998419f132d37bd1138d350ee57df13b6076744bccb5f6b8c8a305a"]

![](https://1074961489-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiJzir9UNmKRbv22Aq3ms%2Fuploads%2FGkW6Nb48QjdZvnJYr4Qy%2Fimage.png?alt=media\&token=abe3027b-576b-4348-8313-1dd3760cb4c8)

可以看到校验通过

参考：

{% embed url="<https://mirror.xyz/clearlove.eth/wgDFvBx1ER-UyweTQoLFvO3ghRtLg6NPkTtKvCab-EE>" %}

{% embed url="<https://medium.com/my-blockchain-development-daily-journey/%E5%B0%87-merkle-trees%E7%94%A8%E6%96%BC-nft-%E7%99%BD%E5%90%8D%E5%96%AE-248a5c2c1570>" %}
