批量数据组成默克尔树,合约进行验证空投。
之前写空投太暴力了,直接就是批量转账,后来发现手续费极高,老板不愿意了;后来看到有方案是将空投名单全部生成默克尔根交给合约,然后用户自己去领取的时候合约根据数据验证,这样老板就不需要出gas费了,用户可以用自己的钱去换空气币啦👀️ !放出代码供大家交流学习;
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上测试成功;
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!