# 批量数据组成默克尔树，合约进行验证空投。

By [Verin](https://paragraph.com/@verin) · 2022-04-16

---

1.一般空投的数据格式都是：

    [{address:0xxxxxxxxxx...xxx,value:10000},{address:0xxxxxxxxxx...xxx,value:10000}]
    

2.我们先设置默克尔根供合约使用：

    let leafs = [];
      for (let k = 0; k < list.length; k++) {
        let leaf = ethers.utils.solidityKeccak256(["address", "uint256"], [list[k].address, list[k].value]);
        leafs.push(leaf);
      }
      let tree = new MerkleTree(leafs, keccak256, { sort: true });
      let root = tree.getHexRoot();
    

3.设置结点数据让合约验证领空投的数据：

    //叶子结点数据
      let leafs = [];
      for (let k = 0; k < list.length; k++) {
        let leaf = ethers.utils.solidityKeccak256(["address", "uint256"], [list[k].address, list[k].value]);
        leafs.push(leaf);
      }
    
      //树根
      let tree = new MerkleTree(leafs, keccak256, { sort: true });
      //叶子proof
      let proofs = [];
      leafs.map((item) => {
        proofs.push(tree.getHexProof(item));
      });
    
      let res = [];
      for (let index = 0; index < list.length; index++) {
        res.push([list[index].address, list[index].value, proofs[index]]);
      }
    

4.空投合约：

    // SPDX-License-Identifier: MIT
    pragma solidity >=0.8.0 <0.9.0;
    
    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
    import "@openzeppelin/contracts/access/Ownable.sol";
    import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
    
    contract Airdrop is Ownable {
        using SafeERC20 for IERC20;
        bytes32 root;
        mapping(address => bool) isGet;
        address tokenAdress;
    
        function hasGet(address _address) public view returns (bool) {
            return isGet[_address];
        }
        //设置根
        function setMerkleRoot(bytes32 _root) external onlyOwner {
            root = _root;
        }
       //验证和获取空投
        function getDrop(
            address _address,
            uint256 _amount,
            bytes32[] calldata _proofs
        ) external {
            require(isGet[_address] == false, "has got");
            bytes32 _leaf = keccak256(abi.encodePacked(_address, _amount));
            bool _verify = MerkleProof.verify(_proofs, root, _leaf);
            require(_verify, "fail");
            isGet[_address] = true;
            IERC20 dropToken = IERC20(tokenAdress);
            require(
                dropToken.balanceOf(address(this)) >= _amount,
                "Insufficient balance"
            );
            dropToken.safeTransfer(_address, _amount);
        }
    
        function setTokenAddress(address _address) public {
            tokenAdress = _address;
        }
    }
    

以上就是空投的主要代码，在rinkeby上测试成功；

---

*Originally published on [Verin](https://paragraph.com/@verin/uJwiDOTPATpScGjuLPNG)*
