赞
踩
最近我在学习空投合约,学习资料中的合约样例非常的简单,就一个负责转账的函数,下面是合约代码:
Airdrop.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./IERC20.sol"; //import IERC20 contract Airdrop { function multiTransferToken( address _token, address[] calldata _addresses ) external { IERC20 token = IERC20(_token); uint _amountSum = _addresses.length * 100; require(token.allowance(msg.sender, address(this)) > _amountSum, "Need Approve ERC20 token"); for (uint256 i; i < _addresses.length; i++) { token.transferFrom(msg.sender, _addresses[i], 100) } } }
通过一番学习,现在我要来完善一下它,给它升级一下。
首先,来分析一下需要完善的点:
1.发起空投得自己输入账户地址数组,如果数量多了,会很麻烦;
解决思路:既然是空投合约,那么就应该是给主动参与活动的账户都投递空投,那就需要设置一个join函数让大家主动加入活动,获得奖励。
2.空投的代币数量固定,不够方便;
解决思路:给每个参与空投的账户设置一个空投数量,用一个数组存储它们,还得能由合约拥有者进行设置,这样就更灵活了。
那么首先,要定义一个数组来存储参与空投的账户地址和它们对应的空投数量,在这里mapping就是很好的选择了:
mapping(address => uint) private _addresses;
之后,写一个参加活动的函数:
function join() public {
payable(msg.sender).transfer(0);
_add(msg.sender);
}
function _add(address _address) private {
require(_addresses[_address] == 0,"This address has already participated in the activity!");
_addresses[_address] = 100;
_addressArr.push(_address);
_token.approve(_address,_addresses[_address]);
}
接下来,我们写一个设置空投数量的函数:
function setAirdropNumber(address _address, unit num) public {
require(msg.sender == owner,"you are not owner!")
_addresses[_address] = num;
}
发起空投的函数也需要修改一番:
function multiTransferToken() external {
uint _amountSum = _getSum(_addressArr);
require(_token.balanceOf(address(this)) >= _amountSum, "Need enough ERC20 token");
for (uint i; i < _addressArr.length; i++) {
_token.transfer(_addressArr[i], _addresses[_addressArr[i]]);
}
}
function _getSum(address[] memory _arr) private view returns(uint sum){
sum = 0;
for(uint i = 0; i < _arr.length; i++){
sum = sum + _addresses[_arr[i]];
}
}
根据以上的代码和需求,我对代码进一步进行完善,最终的代码就出现了:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./IERC20.sol"; //import IERC20 /// @notice 向多个地址转账ERC20代币 contract Airdrop { address private _owner; IERC20 private _token; mapping(address => uint) private _addresses; address[] private _addressArr; constructor(address tokenAddress) { _owner = msg.sender; _token = IERC20(tokenAddress); } function join() public { payable(msg.sender).transfer(0); _add(msg.sender); } function _add(address _address) private { require(_addresses[_address] == 0,"This address has already participated in the activity!"); _addresses[_address] = 100 * (10 ** 18); _addressArr.push(_address); _token.approve(_address,_addresses[_address]); } function setAirdropNumber(address _address, uint num) public { require(_owner == msg.sender, "you are not owner!"); _addresses[_address] = num; _token.approve(_address,_addresses[_address]); } function multiTransferToken() external { uint _amountSum = _getSum(_addressArr); require(_token.balanceOf(address(this)) >= _amountSum, "Need enough ERC20 token"); for (uint i; i < _addressArr.length; i++) { _token.transfer(_addressArr[i], _addresses[_addressArr[i]]); } } function _getSum(address[] memory _arr) private view returns(uint sum){ sum = 0; for(uint i = 0; i < _arr.length; i++){ sum = sum + _addresses[_arr[i]]; } } }
现在,将新合约部署上链,测试一下吧。
1.将之前的代币设置为合约的默认奖励代币;
2.在CHAINPIP社区中先将加入活动的功能开放出来,这样所有想加入的朋友都可以加入活动;
3.现在使用俩个测试账户来加入活动:
地址1:0x754EcB8939e806b365f59aeF9Eadf0cd12b84831
地址2:0x0A67e0A87b9E436808253E3a6EdA2ce333996ccB
4.之后我给其中一个账户修改一下空投的数量,将数量修改为300:
地址:0x754EcB8939e806b365f59aeF9Eadf0cd12b84831
5.最后发起空投,查看一下他们是否收到了奖励。
下面是他们账户的截图:
最后
现在这个合约与之前相比,有了很大的改进,让大家更加方便地加入活动。但是合约目前都只是考虑功能方面,在安全性方面还有不足,所以还需要继续学习新知识来更好地完善它。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。