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

Solidity代币合约transferFrom()授权后无法转账问题求助

ERC20 transferFrom 无法正常工作的问题排查与修复

核心问题分析

1. transferFrom未验证授权额度

你的transferFrom函数在执行转账前未检查花费者(msg.sender)是否拥有足够的授权额度。根据ERC20标准,必须确保_allowance[pFrom][msg.sender] >= pToken,否则无权从pFrom地址转出代币。

2. _transfer函数余额扣减逻辑错误

_transfer函数中错误地扣减了msg.sender的余额,而非实际转出代币的pFrom地址余额。调用transferFrom时,msg.sender是获得授权的花费者,代币实际从pFrom地址转出,因此应操作_balance[pFrom]。

3. Transfer事件参数不符合ERC20标准

emit Transfer时使用msg.sender作为转出方参数,而非实际转出代币的pFrom地址,导致事件日志记录错误,违反ERC20规范。


修正后的代码片段

修正transferFrom函数

function transferFrom(address pFrom, address pRecipient, uint256 pToken) external returns (bool) {
    // 新增:检查授权额度是否充足
    require(_allowance[pFrom][msg.sender] >= pToken, "Insufficient allowance");
    _transfer(pFrom, pRecipient, pToken); 
    _approve(pFrom, msg.sender, _allowance[pFrom][msg.sender] - pToken);               
    return true;
}

修正_transfer函数关键逻辑

function _transfer(address pFrom, address pTo, uint256 pToken) private {
    require(pFrom != address(0));
    require(pTo != address(0));
    require(pToken > 0);
    require(pToken <= _balance[pFrom]);

    uint256 fee = 0;
    
    if(_balance[address(this)] >= THRESHOLD) { _liquidate(); }

    if(!_isExcluded[pFrom] && !_isExcluded[pTo]) {
           
        if(_isRouter[pFrom]) {
            fee = _calculateBuyTax(pToken);//Tax on buys
            _balance[address(this)] += fee;              
        }
        else if(_isRouter[pTo]) {
            fee = _calculateSellTax(pToken);//Tax on sells
            _balance[address(this)] += fee;
        }

    }

    // 修正:扣减实际转出地址pFrom的余额
    _balance[pFrom] -= pToken;
    _balance[pTo] += (pToken - fee);
    // 修正:事件参数使用pFrom作为转出方
    emit Transfer(pFrom, pTo, pToken - fee);     
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:09:12