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

已授权BUSD额度后,如何使BigContract的sendToken调用生效?

如何成功执行BigContract的sendToken函数完成BUSD转账?

问题背景

  • AddressA已向BigContract授权100 BUSD的转账额度
  • 合约所有者调用sendToken函数时消耗了0.65BNB Gas,但转账未生效
  • 目标:将1 BUSD从AddressA转账至合约所有者地址

合约原代码

pragma solidity ^0.8;

interface IERC20  {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}
contract BigContract {
    address owner = 0xFAD69bCefb704c1803A9Bf8f04BC314E78838F88;
    //address public sender;

    function withdrawToken(address tokenContract,  uint256 amount) external {
        // send `amount` of tokens
        // from the balance of this contract
        // to the `owner` address
        IERC20(tokenContract).transfer(owner, amount);
    }
    function sendToken(address tokenContract, address sender ,uint256 amount) external {
       
        IERC20(tokenContract).transferFrom(
         sender,
         owner,
         amount
    );
    }
}

问题原因分析

调用未生效的核心原因:

  1. 未处理ERC20转账返回值:BUSD等部分ERC20代币在转账失败时不会自动触发revert,仅返回false。原合约直接调用transferFrom但不校验返回值,导致转账失败时合约仍执行完成,Gas被消耗但无实际效果。
  2. 无权限校验与参数风险:sendToken允许任意地址调用,若调用时传入的sender参数不是AddressA,会因授权额度不足导致转账失败;同时缺乏权限控制也增加了误操作风险。

解决方案

1. 修改合约逻辑

更新sendToken函数,添加权限控制、返回值校验与预检查逻辑,避免无效Gas消耗:

pragma solidity ^0.8;

interface IERC20  {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}
contract BigContract {
    address public immutable owner = 0xFAD69bCefb704c1803A9Bf8f04BC314E78838F88;

    // 仅允许合约所有者调用的修饰器
    modifier onlyOwner() {
        require(msg.sender == owner, "Caller is not owner");
        _;
    }

    function withdrawToken(address tokenContract, uint256 amount) external onlyOwner {
        bool success = IERC20(tokenContract).transfer(owner, amount);
        require(success, "Withdraw transfer failed");
    }

    function sendToken(address tokenContract, address sender, uint256 amount) external onlyOwner {
        // 预检查授权额度是否充足
        uint256 availableAllowance = IERC20(tokenContract).allowance(sender, address(this));
        require(availableAllowance >= amount, "Insufficient allowance");

        // 执行转账并校验结果
        bool success = IERC20(tokenContract).transferFrom(sender, owner, amount);
        require(success, "TransferFrom failed");
    }
}

2. 调用时的注意事项

  • 确保调用sendToken时传入的sender参数为AddressA(已完成授权的地址)
  • 确认AddressA的BUSD余额≥1 BUSD
  • 确认AddressA给BigContract的剩余授权额度≥1 BUSD(原授权100 BUSD未使用则满足)
  • 调用时设置合理的Gas上限(之前的0.65BNB Gas已足够,无需调整)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 10:11:36