You need to enable JavaScript to run this app. 如何在ERC-20合约中实现按时间规则分批铸造代币
优惠活动
大模型
产品
解决方案
定价
更多

如何在ERC-20合约中实现按时间规则分批铸造代币

ERC20 按时间规则分批铸币实现方案

核心实现逻辑

  • 在合约中预定义释放时间节点和对应每个节点的释放额度,需要将日期转换为Unix时间戳,你给出的示例中三个时间点对应的UTC零点时间戳分别为1630454400(2021-09-01)、1661990400(2022-09-01)、1693526400(2023-09-01)
  • 定义状态变量记录每个节点的铸造状态,避免重复铸造
  • 封装铸币方法,调用时先校验当前区块时间是否达到对应节点的释放要求,再校验该节点额度是否未被铸造,校验通过后调用ERC20标准的_mint方法将代币转入指定的接收地址(通常为项目金库、多签地址)

完整合约代码示例

推荐基于OpenZeppelin的标准ERC20库实现,无需重复造轮子:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

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

contract TimeVestedMintERC20 is ERC20 {
    // 接收铸造代币的固定金库地址
    address public immutable treasury;

    // 释放节点结构体
    struct VestingSchedule {
        uint256 releaseTime; // 释放时间戳
        uint256 amount; // 对应释放额度,单位为wei
        bool isMinted; // 该节点是否已完成铸造
    }

    // 释放节点列表
    VestingSchedule[] public vestingSchedules;

    constructor(address _treasury) ERC20("Test Token", "TT") {
        treasury = _treasury;
        // 初始化你要求的三个释放节点
        vestingSchedules.push(VestingSchedule({
            releaseTime: 1630454400,
            amount: 1_000_000 * 10 ** decimals(),
            isMinted: false
        }));
        vestingSchedules.push(VestingSchedule({
            releaseTime: 1661990400,
            amount: 1_000_000 * 10 ** decimals(),
            isMinted: false
        }));
        vestingSchedules.push(VestingSchedule({
            releaseTime: 1693526400,
            amount: 1_000_000 * 10 ** decimals(),
            isMinted: false
        }));
    }

    // 铸造符合释放条件的代币,任何人可调用,资金只会进入预设金库无风险
    function mintVestedTokens() external {
        for (uint256 i = 0; i < vestingSchedules.length; i++) {
            VestingSchedule storage schedule = vestingSchedules[i];
            if (block.timestamp >= schedule.releaseTime && !schedule.isMinted) {
                schedule.isMinted = true;
                _mint(treasury, schedule.amount);
            }
        }
    }

    // 辅助方法:查询当前可铸造的总额度
    function getAvailableMintAmount() external view returns (uint256) {
        uint256 available = 0;
        for (uint256 i = 0; i < vestingSchedules.length; i++) {
            VestingSchedule storage schedule = vestingSchedules[i];
            if (block.timestamp >= schedule.releaseTime && !schedule.isMinted) {
                available += schedule.amount;
            }
        }
        return available;
    }
}

注意事项

  • 时间戳统一使用UTC时区的数值,避免时区偏差导致释放时间不符合预期,转换前建议用Unix时间戳工具校验数值正确性
  • 计算释放额度时不要忘记乘以10 ** decimals(),否则实际铸造的代币数量会比预期少10的18次方倍(ERC20默认精度为18位)
  • 接收代币的地址建议使用多签钱包或金库合约,避免单地址私钥泄露造成资产损失
  • 若希望仅指定地址可调用铸币方法,可引入OpenZeppelin的Ownable扩展,给mintVestedTokens方法添加onlyOwner修饰符即可
  • 以太坊区块时间戳存在±几十秒的误差,不要对释放时间做秒级精度的要求,属于底层特性无法避免

内容的提问来源于stack exchange,提问作者Umair Janjua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 20:54:00