初始化代币发行数量并设置好锁仓和释放信息

以下是一个集成"初始化代币发行数量""锁仓机制"和"释放规则"的完整ERC20代币合约示例(基于OpenZeppelin安全库),支持按时间线性释放锁仓代币,适合项目方对团队、投资者代币进行分阶段解锁场景。

核心功能说明

  1. 初始化发行:部署时设定总供应量,自动分配给部署者(项目方)。

  2. 锁仓配置:支持对指定地址设置锁仓金额和释放周期(如分12个月线性释放)。

  3. 释放规则:锁仓代币按"时间比例"逐步解锁,未到释放时间的代币无法转账。

完整合约代码

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import "@openzeppelin/contracts/access/Ownable.sol";

contract LockableToken is ERC20, Ownable {

// 锁仓信息结构:记录每个地址的锁仓详情

struct LockInfo {

uint256 totalLocked; // 总锁仓数量(含未释放部分)

uint256 releasedAmount; // 已释放数量

uint256 startTime; // 锁仓开始时间(时间戳)

uint256 duration; // 释放周期(秒,如365天=31536000秒)

bool isLocked; // 是否处于锁仓状态

}

// 地址 => 锁仓信息

mapping(address => LockInfo) public lockInfos;

// 事件:记录锁仓操作

event TokenLocked(address indexed user, uint256 amount, uint256 startTime, uint256 duration);

// 事件:记录代币释放

event TokenReleased(address indexed user, uint256 amount);

/**

* @dev 构造函数:初始化代币名称、符号、总供应量

* @param name_ 代币名称

* @param symbol_ 代币符号

* @param totalSupply_ 初始总供应量(单位:枚,自动处理18位小数)

* @param initialOwner 合约初始拥有者(项目方地址)

*/

constructor(

string memory name_,

string memory symbol_,

uint256 totalSupply_,

address initialOwner

) ERC20(name_, symbol_) Ownable(initialOwner) {

// 发行总代币:乘以10^18处理小数位,全部分配给初始拥有者

uint256 totalSupplyWithDecimals = totalSupply_ * (10 **decimals());

_mint(initialOwner, totalSupplyWithDecimals);

}

/**

* @dev 为指定地址设置锁仓(仅合约拥有者可操作)

* @param user 被锁仓地址

* @param amount 锁仓数量(单位:枚,自动处理小数位)

* @param duration 释放周期(秒,如"365天"传入31536000)

*/

function lockTokens(

address user,

uint256 amount,

uint256 duration

) external onlyOwner {

require(user != address(0), "无效地址");

require(amount > 0, "锁仓数量需大于0");

require(duration > 0, "释放周期需大于0");

require(balanceOf(owner()) >= amount * (10** decimals()), "拥有者余额不足");

// 1. 将代币从拥有者转账到被锁仓地址(但处于锁仓状态)

uint256 amountWithDecimals = amount * (10 **decimals());

_transfer(owner(), user, amountWithDecimals);

// 2. 记录锁仓信息

LockInfo storage lockInfo = lockInfosuser;

require(!lockInfo.isLocked, "该地址已处于锁仓状态"); // 简化版:暂不支持重复锁仓

lockInfo.totalLocked = amountWithDecimals;

lockInfo.releasedAmount = 0;

lockInfo.startTime = block.timestamp; // 锁仓开始时间为当前时间

lockInfo.duration = duration;

lockInfo.isLocked = true;

emit TokenLocked(user, amountWithDecimals, lockInfo.startTime, duration);

}

/**

* @dev 计算指定地址当前可释放的代币数量

* @param user 被锁仓地址

* @return 可释放数量(含小数位)

*/

function getReleasableAmount(address user) public view returns (uint256) {

LockInfo storage lockInfo = lockInfosuser;

if (!lockInfo.isLocked) return 0;

uint256 elapsedTime = block.timestamp - lockInfo.startTime;

uint256 totalLockTime = lockInfo.duration;

// 若未到释放周期:可释放0;若已过周期:可释放全部未释放部分

if (elapsedTime >= totalLockTime) {

return lockInfo.totalLocked - lockInfo.releasedAmount;

}

// 按时间比例计算可释放数量(线性释放)

uint256 releasable = (lockInfo.totalLocked * elapsedTime) / totalLockTime - lockInfo.releasedAmount;

return releasable;

}

/**

* @dev 手动触发代币释放(被锁仓地址可自行调用)

*/

function releaseTokens() external {

address user = msg.sender;

LockInfo storage lockInfo = lockInfosuser;

require(lockInfo.isLocked, "无锁仓代币");

uint256 releasable = getReleasableAmount(user);

require(releasable > 0, "暂无可释放代币");

// 更新已释放数量

lockInfo.releasedAmount += releasable;

// 若全部释放,标记锁仓结束

if (lockInfo.releasedAmount == lockInfo.totalLocked) {

lockInfo.isLocked = false;

}

emit TokenReleased(user, releasable);

}

/**

* @dev 重写transfer函数:限制转账金额不得超过"可用余额"

相关推荐
梦帮科技16 小时前
从零到一构建音乐版权公链:RNS Token 区块链基础设施与智能合约架构全解析
架构·区块链·智能合约
Web3李李17 小时前
如何利用真实故事做 Web3 项目营销 —— 结合\(LABUBU、\)ASTEROID 两大万倍代币拆解
web3·区块链·软件开发·dapp开发·太空狗·拉布布labubu
区块链小八歌19 小时前
探索 Aqua,Hyperliquid 如何打通衍生品流动性向零售渗透的最终圣杯
区块链
mykj15511 天前
RWA与Web3双向融合:开启资产数字化新时代
web3·区块链
筱璦1 天前
量化交易系统源码可售
区块链·交易·期货·期货交易
mykj15511 天前
RWA与Web3区块链:一场“实体”与“数字”的双向奔赴
web3·区块链
m0_3801671418 天前
面向开发者的Top10加密货币数据API(2026年最新)
大数据·人工智能·区块链
2601_9594801519 天前
Moneta Markets亿汇:“比特币高位修复风险偏好”
区块链
m0_3801671419 天前
加密货币价格 API、市场数据 API 与 分析 API 有什么区别?
人工智能·ai·区块链
LedgerNinja19 天前
AEGET:提升决策效率,助力交易者建立清晰的交易体系
区块链