You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Solidity中创建计时器并在计时结束后重置VIP列表?

问题分析与修复方案

核心问题排查

你的VIP重置功能失效主要由以下几个原因导致:

  • VIP数组未同步更新:添加VIP时仅修改了monthlyVIP映射,未将地址存入vip数组,导致resetVIPs遍历空数组,无法执行重置操作。
  • 计时周期不符合需求:当前计时器仅设置60秒后结束,而非你需要的5周时长。
  • 重置触发逻辑缺失:timeIsOver修饰器未被任何函数使用,导致时间到期后无法触发重置(Solidity无原生定时任务,需通过外部调用触发)。
  • 重置后数组未清理:重置VIP状态后未清空vip数组,会导致后续重置操作重复处理无效地址,浪费Gas。

修复后的合约代码

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

import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
import '@openzeppelin/contracts/access/Ownable.sol';

contract TestContractV1 is ERC721, Ownable{
    uint256 public mintPrice = 0.00000000000000001 ether;
    uint256 public totalSupply;
    uint256 public maxSupply;
    bool public isMintEnabled;
    uint public start;
    uint public end;
    // 5周对应的秒数:5*7*24*60*60 = 3024000秒
    uint public constant VIP_CYCLE = 3024000;

    mapping(address => uint256) public mintedWalletes;
    mapping(address => bool) public whitelist;
    mapping(address => bool) public monthlyVIP;
    address[] public vip;

    constructor() payable ERC721('Test V1', 'TV1'){
        maxSupply = 2;
    }

    // 检查时间是否到期的修饰器
    modifier timeIsOver{
        require(block.timestamp >= end, "Time not up yet");
        _;
    } 

    function toggleIsMintEnabled() external onlyOwner{
        isMintEnabled = !isMintEnabled;
        whitelist[msg.sender] = true;
        startTimer();
    }

    function setMaxSupply(uint256 maxSupply_) external onlyOwner{
        maxSupply = maxSupply_;
    }

    function addToWhitelist(address[] calldata toAddAddresses) external onlyOwner
    {
        for (uint i = 0; i < toAddAddresses.length; i++) {
            whitelist[toAddAddresses[i]] = true;
        }
    }

    function addToVIP(address[] calldata toAddAddresses) external onlyOwner
    {
        for (uint i = 0; i < toAddAddresses.length; i++) {
            address addr = toAddAddresses[i];
            // 避免重复添加同一地址到数组
            if (!monthlyVIP[addr]) {
                monthlyVIP[addr] = true;
                vip.push(addr);
            }
        }
    }

    function removeFromWhitelist(address[] calldata toRemoveAddresses) external onlyOwner
    {
        for (uint i = 0; i < toRemoveAddresses.length; i++) {
            delete whitelist[toRemoveAddresses[i]];
        }
    }

    function resetVIPs() public timeIsOver {
        for (uint i=0; i<vip.length ; i++) {
            monthlyVIP[vip[i]] = false;
        }
        // 清空VIP数组,避免后续重复处理
        delete vip;
        // 重置计时器,开启下一个周期
        startTimer();
    }

    function whitelistFunc() public view 
    {
        require(whitelist[msg.sender], "NOT_IN_WHITELIST");
    }

    function startTimer() public{
        start = block.timestamp;
        // 直接设置结束时间,无需单独调用endTimer
        end = start + VIP_CYCLE;
    }

    function timeLeft() public view returns(uint){
        if(block.timestamp >= end) return 0;
        return end - block.timestamp;
    }

    function mint() external payable {
        // 铸造时检查是否到VIP重置时间,若到期则自动触发重置
        if(block.timestamp >= end){
            resetVIPs();
        }
        require(isMintEnabled, 'MINTING_NOT_ENABLED');
        require(whitelist[msg.sender], 'NOT_IN_WHITELIST');
        require(mintedWalletes[msg.sender] < 100, 'REARD_BEEN_CLAIMED_ALREADY');
        require(monthlyVIP[msg.sender] , 'YOU_NOT_MONTHLY_VIP');
        require(maxSupply > totalSupply, 'SOLD_OUT');
        mintedWalletes[msg.sender]++;
        totalSupply++;
        uint256 tokenId = totalSupply; 
        _safeMint(msg.sender, tokenId);   
    }
}

关键修改说明

  1. 维护VIP数组:在addToVIP中添加重复检查,仅将未加入的地址存入vip数组,确保resetVIPs能遍历所有有效VIP地址。
  2. 修正计时周期:定义VIP_CYCLE常量为5周对应的秒数,并在startTimer中直接设置结束时间,移除冗余的endTimer函数。
  3. 优化重置触发逻辑:在mint函数中增加时间检查,到期自动触发resetVIPs;同时将resetVIPs与timeIsOver修饰器绑定,确保只有时间到期后才能调用重置。
  4. 清理VIP数组:重置VIP状态后清空vip数组,避免后续操作处理无效地址,节省Gas消耗。
  5. 修复时间计算错误:timeLeft函数修正为计算剩余时间(原代码逻辑错误,返回的是已超时的时长)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:50:46