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

ERC20预售合约transferTokensToPresale函数测试无报错但未生效

问题原因分析与解决方案

核心原因1:合约未同步更新内部预售代币计数变量

你的transferTokensToPresale函数仅完成了代币从owner到预售合约的转账操作,但没有更新预售合约内部跟踪可用预售代币的状态变量(比如_presaleAvailableTokens这类自定义变量)。而tokensAvailable()函数大概率是返回这个内部变量的值,而非直接查询合约的ERC20代币余额。

举个例子,如果tokensAvailable的实现是这样的:

function tokensAvailable() public view returns(uint256) {
    return _presaleAvailableTokens;
}

但你的转账函数里没有执行_presaleAvailableTokens += presaleSupplyAmount_;,那这个变量的值永远不会变化,调用前后自然一致。

核心原因2:tokensAvailable函数实现逻辑错误

检查tokensAvailable()函数是否正确返回了预售合约的代币余额。如果它的实现不是查询token.balanceOf(address(this)),而是依赖未被更新的内部变量,就会出现这个问题。

正确的实现应该是直接查询合约的代币余额:

function tokensAvailable() public view returns(uint256) {
    return token.balanceOf(address(this));
}

或者在转账函数里同步更新内部计数变量:

function transferTokensToPresale(uint256 presaleSupplyAmount_) public onlyOwner returns (bool) {
    // 原有的require检查逻辑
    require(presaleSupplyAmount_ > 0, "Amount must be greater than zero");
    require(token.balanceOf(msg.sender) >= presaleSupplyAmount_, "Insufficient balance");
    require(block.timestamp < startTime, "Presale has already started");

    SafeERC20.safeTransferFrom(token, msg.sender, address(this), presaleSupplyAmount_);
    // 新增:更新内部可用代币计数
    _presaleAvailableTokens += presaleSupplyAmount_;
    return true;
}

其他排查点

  1. 确认owner完成代币授权
    确保在测试脚本中,owner已经给预售合约授权了足够的代币额度:

    // 测试脚本添加授权步骤
    await token.connect(owner).approve(presale.address, presaleSupply);
    

    因为safeTransferFrom要求转账发起方(owner)先授权合约转移对应数量的代币,若未授权交易本应revert,但如果你的ERC20是非标准实现,可能出现无报错但转账未生效的情况。

  2. 修正测试脚本的日志文案
    你的测试脚本两次输出的文案都是token amount before transferring...,第二次应该改为after,避免混淆判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 10:07:38