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

以下是一个集成"初始化代币发行数量""锁仓机制"和"释放规则"的完整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 = lockInfos[user];

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 = lockInfos[user];

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 = lockInfos[user];

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函数:限制转账金额不得超过"可用余额"

相关推荐
财***权8601 小时前
期权手续费一览表最新的标准
区块链
BlockChain8881 小时前
AI+区块链深度探索:算法与账本的共生时代
人工智能·算法·区块链
中冕—霍格沃兹软件开发测试1 小时前
区块链交易最终一致性测试的核心挑战与实践框架
微服务·架构·单元测试·区块链·集成测试·旅游
开源Z1 小时前
WeDPR v3.0 适配国密(SM)区块链节点部署实战:填坑官方文档未覆盖的配置
区块链·密码学·可信计算技术
Web3VentureView5 小时前
SYNBO走进以太坊中国高校行复旦大学专场:链接Web3下一代开发者
人工智能·web3·区块链·加密货币·synbo
王苏安说钢材A21 小时前
无锡卖无缝管厂家推荐@无锡佳钛合不锈钢有限公司
区块链
程序员李程峰2 天前
基础知识——区块链钱包
web3·去中心化·区块链·同态加密·零知识证明·共识算法·分布式账本
区块block2 天前
Infinity Alpha(无限阿尔法)即将发布纯链上AI收益引擎通证IA
人工智能·区块链
Datakeji2 天前
维恩波特Vairnport商业逻辑
大数据·人工智能·区块链