dev/Solidity

Merkle Tree - 솔리디티 화이트리스트 관리하기

_April 2022. 4. 24. 14:28

 

NFT 민팅할때 보통 화이트리스트에게 먼저 NFT를 민팅할 권리를 준다.

솔리디티에서 이부분을 구현할때

메모리나 맵에 올리면

가스비로 아주 큰 비용을 지불해야한다.

 

이 문제를 해결하는것이 머클트리이다

Merkle Tree

사용법

https://medium.com/@ItsCuzzo/using-merkle-trees-for-nft-whitelists-523b58ada3f9

 

간략하게말하면

js단:

(1) WL 리스트를 암호화해서(keccak256쓰던 SHA쓰던 본인선택) 머클트리에 넣는다.

그럼 암호화된 전체 노드가 나오는데 Root Node만 키처럼 들고있음

        const leaves = whitelistAddresses.map(addr => keccak256(addr));
        tree = new MerkleTree(leaves, keccak256, { sort: true });
        const root_merkle = tree.getRoot();

(2) 실제로 민팅할때는 주소를 암호화한 값을 머클트리에 넣었을때 proof값을 받아서,

컨트랙트로 보낸다.

        const hexProof = tree.getHexProof(keccak256(addr1.address));
        // console.log('hex: '+hexProof.toString());
        await nft_contract.connect(addr1).whitelistMint(hexProof);

 

 

솔리디티:

Root Node의 값과 머클트리 proof 값, 그리고 지갑주소값이 필요하다

MerkleProof 라이브러리로 두 값이 verify되는지 확인한다.

contract Merkle is Ownable{
    bytes32 public merkleRoot;

    mapping(address => bool) public whitelistClaimed;

    function whitelistMint(bytes32[] calldata _merkleProof) external{
        require(!whitelistClaimed[msg.sender], "Address has already claimed.");

        bytes32 leaf = keccak256(abi.encodePacked(msg.sender));

        //Verify the provided _merkleProof
        require(MerkleProof.verify(_merkleProof, merkleRoot, leaf), "Invalid Proof, No WL");

        whitelistClaimed[msg.sender] = true;

        //실제민팅하는곳
    }


    function setMerkleRoot(bytes32 _merkleRoot) public {
        merkleRoot = _merkleRoot;
    }

}

 

꼭 이런순서로 짤 필요는 없지만

어떤 구성요소가 필요한지 보고 시작하면 편하다