# 批量数据组成默克尔树,合约进行验证空投。 **Published by:** [Verin](https://paragraph.com/@verin/) **Published on:** 2022-04-16 **URL:** https://paragraph.com/@verin/uJwiDOTPATpScGjuLPNG ## Content 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上测试成功; ## Publication Information - [Verin](https://paragraph.com/@verin/): Publication homepage - [All Posts](https://paragraph.com/@verin/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@verin): Subscribe to updates