如何在Solidity合约中存储授权地址仅允许指定地址提现?
完全可以实现,这是以太坊空投类合约的标准需求,具体实现方案如下:
核心实现逻辑
- 你需要三个核心合约存储变量:合约所有者地址
owner、白名单额度映射mapping(address => uint256) public claimableAmount(存储每个符合规则用户可提取的代币数量)、活动结束时间戳uint256 public airdropEndTime(控制提现开启时间) - 用
onlyOwner权限修饰符限制仅你可以添加、修改白名单用户的可提现额度,避免无关人员篡改空投规则 - 提现逻辑天然由用户发起,交易手续费自动由调用接口的用户承担,不需要你额外支付;仅当用户在白名单内有可提取额度、且活动已结束时,才可成功提现,提现后自动清空对应地址的可提额度,避免重复提现
参考代码片段
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract AirdropClaim is Ownable { // 要发放的空投代币合约地址 IERC20 public immutable rewardToken; // 空投活动结束的秒级时间戳 uint256 public immutable airdropEndTime; // 存储每个用户可领取的空投数量 mapping(address => uint256) public claimableAmount; event Claimed(address indexed user, uint256 amount); // 构造函数初始化:传入代币地址、活动持续时长(1个月可填30*86400) constructor(address _rewardToken, uint256 _duration) { rewardToken = IERC20(_rewardToken); airdropEndTime = block.timestamp + _duration; } // 仅所有者可批量设置符合规则的用户可领额度,活动期间可随时修改 function setAirdropWhitelist(address[] calldata users, uint256[] calldata amounts) external onlyOwner { require(users.length == amounts.length, "参数长度不匹配"); require(block.timestamp < airdropEndTime, "空投活动已结束,不可修改白名单"); for (uint256 i = 0; i < users.length; i++) { claimableAmount[users[i]] = amounts[i]; } } // 用户提现接口,由用户自主调用,GAS费用户自行承担 function claim() external { require(block.timestamp >= airdropEndTime, "空投活动未结束,暂不可提现"); uint256 amount = claimableAmount[msg.sender]; require(amount > 0, "你没有可提取的空投额度"); // 先清零额度避免重入攻击 claimableAmount[msg.sender] = 0; rewardToken.transfer(msg.sender, amount); emit Claimed(msg.sender, amount); } // 可选功能:活动结束后所有者可提取未被领取的剩余代币 function withdrawRemaining() external onlyOwner { require(block.timestamp >= airdropEndTime, "空投活动未结束,不可提取剩余代币"); uint256 balance = rewardToken.balanceOf(address(this)); rewardToken.transfer(owner(), balance); } }
注意事项
- 部署合约时请准确计算活动时长,部署后活动结束时间不可修改,避免后续规则纠纷
- 合约部署完成后,你需要提前将全部要发放的空投代币转入该合约地址,否则用户提现时会因为合约余额不足失败
- 活动结束后白名单修改接口会自动禁用,无法再调整用户可提现额度
- 代码默认已实现单地址仅可提现一次的逻辑,不会出现重复冒领的问题
内容的提问来源于stack exchange,提问作者Danilo Escobar
相关产品推荐
相关产品推荐

