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

Solidity质押合约ERC20转账余额不足异常求助

问题分析与解决方案

核心错误原因

你在质押合约的stake函数里调用ercToken.transfer(address(ercToken), _amount)时犯了关键逻辑错误:

  • ERC20标准的transfer函数,是从调用该函数的地址(也就是你的质押合约地址)转出代币到目标地址,而非用户地址。
  • 你之前检查的是用户余额ercToken.balanceOf(msg.sender),但实际转账时系统会校验质押合约的余额——而质押合约并没有用户的代币,因此触发"ERC20: transfer amount exceeds balance"错误。

另外,原代码里的require(_amount < ercToken.balanceOf(msg.sender))用了<,应该改为<=,否则用户刚好持有等于_amount的代币时也会触发错误。

正确实现步骤

用户质押代币必须遵循用户授权→合约划转的流程:

1. 前端补充授权操作

用户需要先授权质押合约操作自己的代币,再执行质押:

async function approveAndStake() {
  const stakeAmount = 1;
  // 先授权质押合约划转指定数量的代币
  await ercTokenContract.approve(stakeContract.address, stakeAmount);
  // 再执行质押
  await stakeContract.stake(stakeAmount);
}

2. 修改质押合约的stake函数

使用ERC20的transferFrom函数,从用户地址直接划转代币到目标地址(这里以质押合约自身为例,可根据业务需求调整目标地址):

function stake(uint256 _amount) public {
    require(_amount > 0, "You must stake more than 0");
    
    uint256 userBalance = ercToken.balanceOf(msg.sender);
    require(userBalance >= _amount, "The amount exceeds your balance");

    // 检查用户给质押合约的授权额度是否足够
    uint256 allowance = ercToken.allowance(msg.sender, address(this));
    require(allowance >= _amount, "Allowance not enough");

    // 记录质押信息
    addressToStaked[msg.sender].push(Stakes(block.timestamp, _amount));
    totalStakes[msg.sender] += 1;

    // 从用户地址划转代币至目标地址
    bool transferSuccess = ercToken.transferFrom(msg.sender, address(this), _amount);
    require(transferSuccess, "Stake transfer failed");
}

补充说明

  • transferFrom的逻辑是:从from地址(用户地址)转出代币到to地址,前提是from已授权调用该函数的地址(质押合约)足够额度。
  • 你可以根据业务需求,将transferFrom的目标地址改为专门的质押池地址,而非质押合约自身。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 04:45:34