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

已授权但Allowance仍为0,transferFrom提示余额不足问题

问题根源

你代码里的核心bug是approveUser函数误用了delegatecall调用USDC的approve方法。delegatecall的特性是让目标合约的代码在当前合约的上下文执行,也就是说,调用approve时的msg.sender是你的基金合约地址,而非调用approveUser的用户地址。这等于让合约自己给自己授权,根本没给用户地址设置有效allowance,所以transferFrom时始终显示授权不足。

修复步骤

1. 替换approveUser里的delegatecall

把delegatecall改成普通call或直接用接口调用,确保approve的上下文是用户地址:

方案一(推荐,类型更安全):用接口调用

function approveUser(uint256 amount) public returns(bool){
    bool success = IProperSubsetUSDC(usdcAddress).approve(address(this), amount);
    if(success){
        contractIsApproved[msg.sender] = true;
    }
    return success;
}

方案二:用普通call

function approveUser(uint256 amount) public returns(bool){
    (bool success,) = usdcAddress.call(abi.encodeWithSignature('approve(address,uint256)', address(this), amount));
    if(success){
        contractIsApproved[msg.sender] = true;
    }
    return success;
}

2. 测试时新增授权验证步骤

在测试用例里,approve之后直接查询用户对合约的allowance,确认授权成功再执行deposit:

it("Verify allowance after approval", async function() {
  await deployFunds.connect(signers[1]).approveUser(1000);
  const allowance = await deployUSDC.allowance(signers[1].address, deployFunds.address);
  expect(allowance).to.equal(1000);
})

it("Try depositing and the price of the pool tokens should be equal to one since it is new", async function() {
  const tx = await deployFunds.connect(signers[1]).deposit(1000, 2);
  const receipt = await tx.wait();
  
  filter = receipt.events?.filter((x) => {return x.event == "Deposit"});
  poolId = filter.length > 0 ? filter[0].args[1] : '0x000';
  tokensForUser = filter.length > 0 ? filter[0].args[2]: "0";
  mintedTokens = await deployERC20.balanceOf(user1);
  expect(filter.length).above(0);
  expect(poolId).to.equal(2);
  expect(tokensForUser).to.equal(1000);
})

3. 优化deposit函数的transferFrom检查

transferFrom调用后要判断返回值,失败时直接revert,避免后续逻辑无效执行:

bool transferSuccess = IProperSubsetUSDC(usdcAddress).transferFrom(msg.sender, address(this), depositAmount);
if(!transferSuccess) revert TransferFailed();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:55:22