代币分发系统
代币分发系统是一种用于管理代币分配和发放的机制。本教程将介绍如何实现一个安全可靠的代币分发系统。
功能特性
- 分发管理
- 批量发放
- 锁定机制
- 权限控制
- 紧急处理
合约实现
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
/**
* @title TokenDistribution
* @dev 代币分发合约实现
*/
contract TokenDistribution is Ownable, ReentrancyGuard, Pausable {
using SafeMath for uint256;
// 分发计划
struct Distribution {
uint256 amount; // 分发数量
uint256 startTime; // 开始时间
uint256 duration; // 持续时间
uint256 interval; // 释放间隔
uint256 released; // 已释放数量
bool isActive; // 是否激活
}
// 接收者信息
struct Recipient {
uint256 totalAmount; // 总分配数量
uint256 releasedAmount; // 已释放数量
uint256 lastRelease; // 上次释放时间
bool isActive; // 是否激活
}
// 配置信息
struct DistributionConfig {
uint256 minAmount; // 最小分配
uint256 maxAmount; // 最大分配
uint256 minDuration; // 最小周期
uint256 maxDuration; // 最大周期
bool requiresApproval; // 是否需要审批
bool isActive; // 是否激活
}
// 状态变量
IERC20 public token; // 代币合约
mapping(bytes32 => Distribution) public distributions; // 分发计划
mapping(bytes32 => mapping(address => Recipient)) public recipients; // 接收者信息
mapping(address => bool) public operators; // 操作员
DistributionConfig public config; // 配置信息
// 事件
event DistributionCreated(bytes32 indexed id, uint256 amount, uint256 startTime, uint256 duration);
event DistributionUpdated(bytes32 indexed id, bool isActive);
event TokensDistributed(bytes32 indexed id, address indexed recipient, uint256 amount);
event RecipientUpdated(bytes32 indexed id, address indexed recipient, uint256 amount, bool isActive);
event OperatorUpdated(address indexed operator, bool status);
event ConfigUpdated(uint256 minAmount, uint256 maxAmount, uint256 minDuration, uint256 maxDuration);
/**
* @dev 构造函数
*/
constructor(
address _token,
uint256 _minAmount,
uint256 _maxAmount,
uint256 _minDuration,
uint256 _maxDuration
) {
require(_token != address(0), "Invalid token");
token = IERC20(_token);
config = DistributionConfig({
minAmount: _minAmount,
maxAmount: _maxAmount,
minDuration: _minDuration,
maxDuration: _maxDuration,
requiresApproval: true,
isActive: true
});
}
/**
* @dev 创建分发计划
*/
function createDistribution(
uint256 _amount,
uint256 _startTime,
uint256 _duration,
uint256 _interval
) external onlyOperator whenNotPaused returns (bytes32) {
require(config.isActive, "Distribution not active");
require(_amount >= config.minAmount && _amount <= config.maxAmount, "Invalid amount");
require(_duration >= config.minDuration && _duration <= config.maxDuration, "Invalid duration");
require(_interval > 0 && _interval <= _duration, "Invalid interval");
require(_startTime >= block.timestamp, "Invalid start time");
bytes32 id = keccak256(abi.encodePacked(
block.timestamp,
_amount,
_startTime,
_duration,
_interval
));
distributions[id] = Distribution({
amount: _amount,
startTime: _startTime,
duration: _duration,
interval: _interval,
released: 0,
isActive: true
});
emit DistributionCreated(id, _amount, _startTime, _duration);
return id;
}
/**
* @dev 添加接收者
*/
function addRecipient(
bytes32 _id,
address _recipient,
uint256 _amount
) external onlyOperator {
require(_recipient != address(0), "Invalid recipient");
Distribution storage dist = distributions[_id];
require(dist.isActive, "Distribution not active");
require(dist.released.add(_amount) <= dist.amount, "Exceeds distribution amount");
recipients[_id][_recipient] = Recipient({
totalAmount: _amount,
releasedAmount: 0,
lastRelease: 0,
isActive: true
});
emit RecipientUpdated(_id, _recipient, _amount, true);
}
/**
* @dev 批量添加接收者
*/
function addRecipients(
bytes32 _id,
address[] calldata _recipients,
uint256[] calldata _amounts
) external onlyOperator {
require(_recipients.length == _amounts.length, "Length mismatch");
Distribution storage dist = distributions[_id];
require(dist.isActive, "Distribution not active");
uint256 totalAmount = 0;
for (uint256 i = 0; i < _amounts.length; i++) {
totalAmount = totalAmount.add(_amounts[i]);
}
require(dist.released.add(totalAmount) <= dist.amount, "Exceeds distribution amount");
for (uint256 i = 0; i < _recipients.length; i++) {
address recipient = _recipients[i];
uint256 amount = _amounts[i];
require(recipient != address(0), "Invalid recipient");
recipients[_id][recipient] = Recipient({
totalAmount: amount,
releasedAmount: 0,
lastRelease: 0,
isActive: true
});
emit RecipientUpdated(_id, recipient, amount, true);
}
}
/**
* @dev 释放代币
*/
function release(
bytes32 _id,
address _recipient
) external nonReentrant whenNotPaused returns (uint256) {
Distribution storage dist = distributions[_id];
require(dist.isActive, "Distribution not active");
require(block.timestamp >= dist.startTime, "Not started");
Recipient storage recipient = recipients[_id][_recipient];
require(recipient.isActive, "Recipient not active");
uint256 releasable = getReleasableAmount(_id, _recipient);
require(releasable > 0, "No tokens to release");
recipient.releasedAmount = recipient.releasedAmount.add(releasable);
recipient.lastRelease = block.timestamp;
dist.released = dist.released.add(releasable);
require(
token.transfer(_recipient, releasable),
"Transfer failed"
);
emit TokensDistributed(_id, _recipient, releasable);
return releasable;
}
/**
* @dev 批量释放代币
*/
function batchRelease(
bytes32 _id,
address[] calldata _recipients
) external nonReentrant whenNotPaused returns (uint256) {
uint256 totalReleased = 0;
for (uint256 i = 0; i < _recipients.length; i++) {
uint256 released = release(_id, _recipients[i]);
totalReleased = totalReleased.add(released);
}
return totalReleased;
}
/**
* @dev 计算可释放数量
*/
function getReleasableAmount(
bytes32 _id,
address _recipient
) public view returns (uint256) {
Distribution storage dist = distributions[_id];
Recipient storage recipient = recipients[_id][_recipient];
if (!dist.isActive || !recipient.isActive || block.timestamp < dist.startTime) {
return 0;
}
uint256 elapsedTime = block.timestamp.sub(dist.startTime);
if (elapsedTime > dist.duration) {
elapsedTime = dist.duration;
}
uint256 periods = elapsedTime.div(dist.interval);
uint256 totalVested = recipient.totalAmount.mul(periods).mul(dist.interval).div(dist.duration);
return totalVested.sub(recipient.releasedAmount);
}
/**
* @dev 更新分发状态
*/
function updateDistributionStatus(bytes32 _id, bool _isActive) external onlyOwner {
distributions[_id].isActive = _isActive;
emit DistributionUpdated(_id, _isActive);
}
/**
* @dev 更新接收者状态
*/
function updateRecipientStatus(
bytes32 _id,
address _recipient,
bool _isActive
) external onlyOperator {
recipients[_id][_recipient].isActive = _isActive;
emit RecipientUpdated(_id, _recipient, recipients[_id][_recipient].totalAmount, _isActive);
}
/**
* @dev 更新操作员
*/
function updateOperator(address _operator, bool _status) external onlyOwner {
operators[_operator] = _status;
emit OperatorUpdated(_operator, _status);
}
/**
* @dev 更新配置
*/
function updateConfig(
uint256 _minAmount,
uint256 _maxAmount,
uint256 _minDuration,
uint256 _maxDuration
) external onlyOwner {
require(_minAmount <= _maxAmount, "Invalid amounts");
require(_minDuration <= _maxDuration, "Invalid durations");
config.minAmount = _minAmount;
config.maxAmount = _maxAmount;
config.minDuration = _minDuration;
config.maxDuration = _maxDuration;
emit ConfigUpdated(_minAmount, _maxAmount, _minDuration, _maxDuration);
}
/**
* @dev 暂停分发
*/
function pause() external onlyOwner {
_pause();
}
/**
* @dev 恢复分发
*/
function unpause() external onlyOwner {
_unpause();
}
/**
* @dev 紧急提取
*/
function emergencyWithdraw() external onlyOwner {
uint256 balance = token.balanceOf(address(this));
require(balance > 0, "No balance");
require(token.transfer(owner(), balance), "Transfer failed");
}
/**
* @dev 检查操作员权限
*/
modifier onlyOperator() {
require(operators[msg.sender] || owner() == msg.sender, "Not operator");
_;
}
/**
* @dev 更新分发计划
*/
function updateDistribution(
bytes32 _id,
bool _isActive
) external onlyOperator whenNotPaused {
Distribution storage dist = distributions[_id];
require(dist.amount > 0, "Distribution not found");
dist.isActive = _isActive;
emit DistributionUpdated(_id, _isActive);
}
/**
* @dev 更新接收者状态
*/
function updateRecipient(
bytes32 _id,
address _recipient,
bool _isActive
) external onlyOperator whenNotPaused {
Recipient storage recipient = recipients[_id][_recipient];
require(recipient.totalAmount > 0, "Recipient not found");
recipient.isActive = _isActive;
emit RecipientUpdated(_id, _recipient, recipient.totalAmount, _isActive);
}
/**
* @dev 获取分发计划信息
*/
function getDistributionInfo(
bytes32 _id
) external view returns (
uint256 amount,
uint256 startTime,
uint256 duration,
uint256 interval,
uint256 released,
bool isActive
) {
Distribution storage dist = distributions[_id];
return (
dist.amount,
dist.startTime,
dist.duration,
dist.interval,
dist.released,
dist.isActive
);
}
/**
* @dev 获取接收者信息
*/
function getRecipientInfo(
bytes32 _id,
address _recipient
) external view returns (
uint256 totalAmount,
uint256 releasedAmount,
uint256 lastRelease,
bool isActive
) {
Recipient storage recipient = recipients[_id][_recipient];
return (
recipient.totalAmount,
recipient.releasedAmount,
recipient.lastRelease,
recipient.isActive
);
}
/**
* @dev 设置操作员
*/
function setOperator(address _operator, bool _status) external onlyOwner {
operators[_operator] = _status;
emit OperatorUpdated(_operator, _status);
}
/**
* @dev 更新配置
*/
function updateConfig(
uint256 _minAmount,
uint256 _maxAmount,
uint256 _minDuration,
uint256 _maxDuration,
bool _requiresApproval
) external onlyOwner {
require(_maxAmount > _minAmount, "Invalid amounts");
require(_maxDuration > _minDuration, "Invalid durations");
config.minAmount = _minAmount;
config.maxAmount = _maxAmount;
config.minDuration = _minDuration;
config.maxDuration = _maxDuration;
config.requiresApproval = _requiresApproval;
emit ConfigUpdated(_minAmount, _maxAmount, _minDuration, _maxDuration);
}
/**
* @dev 设置分发系统状态
*/
function setActive(bool _isActive) external onlyOwner {
config.isActive = _isActive;
}
/**
* @dev 暂停/恢复合约
*/
function setPaused(bool _paused) external onlyOwner {
if (_paused) {
_pause();
} else {
_unpause();
}
}
/**
* @dev 紧急提取
*/
function emergencyWithdraw(
address _token,
address _to,
uint256 _amount
) external onlyOwner {
require(_token != address(token), "Cannot withdraw distribution token");
require(_to != address(0), "Invalid recipient");
IERC20(_token).transfer(_to, _amount);
}
/**
* @dev 检查是否是操作员
*/
modifier onlyOperator() {
require(operators[msg.sender] || msg.sender == owner(), "Not operator");
_;
}
}
关键概念
分发管理
分发功能包括:
- 计划创建
- 批量分发
- 释放控制
- 状态管理
接收者管理
接收者功能包括:
- 信息记录
- 余额追踪
- 释放计算
- 状态控制
安全控制
安全功能包括:
- 权限管理
- 暂停机制
- 紧急提取
- 状态验证
安全考虑
分发安全
- 数量验证
- 时间控制
- 状态检查
- 异常处理
接收者安全
- 地址验证
- 余额检查
- 释放控制
- 状态保护
系统安全
- 权限控制
- 暂停机制
- 重入防护
- 状态同步
升级安全
- 配置更新
- 计划调整
- 状态迁移
- 紧急处理
最佳实践
分发管理
- 合理计划
- 动态调整
- 批量处理
- 异常处理
接收者管理
- 信息验证
- 状态追踪
- 余额核对
- 释放控制
风险管理
- 计划监控
- 异常检测
- 风险预警
- 应急处理
系统维护
- 参数优化
- 性能监控
- 安全审计
- 升级预案
扩展功能
- 动态分发
- 多币种支持
- 条件释放
- 投票权重
- 分发策略
应用场景
代币分发
- 团队激励
- 社区奖励
- 生态建设
- 市场营销
资金管理
- 预算控制
- 资金分配
- 支出管理
- 财务审计
治理机制
- 权益分配
- 投票权重
- 激励机制
- 社区建设
常见问题解答(FAQ)
基础概念
Q: 什么是代币分发?
A: 代币分发是一种代币分配机制,主要特点包括:
- 多方分配
- 公平分配
- 透明记录
- 自动执行
- 灵活配置
Q: 分发系统有哪些类型?
A: 主要类型包括:
- 空投分发
- 线性分发
- 批量分发
- 条件分发
- 混合分发
操作相关
Q: 如何设计分发方案?
A: 设计要点包括:
- 确定分发总量
- 设置分发规则
- 配置时间表
- 选择分发方式
- 设置验证条件
Q: 如何执行分发操作?
A: 执行步骤包括:
- 准备代币
- 验证地址
- 确认数量
- 执行分发
- 记录结果
安全相关
Q: 分发系统有哪些风险?
A: 主要风险包括:
- 地址错误
- 数量计算错误
- 重复分发
- 合约漏洞
- 操作失误
Q: 如何确保分发安全?
A: 安全措施包括:
- 多重验证
- 批次控制
- 地址检查
- 金额限制
- 完整日志