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

Gas计算函数报错:账户余额不足以支付gas费用求助

以太坊套利合约执行时的Gas计算错误排查

我尝试调用某合约执行套利交换,触发如下错误:

Low-level call error: err: insufficient funds for gas * price + value: address 0x have 26389996078916648 want 3681518208500000000 (supplied gas 500000000)

其中3681518208500000000对应3.1354971585ETH,按当前汇率2583.29美元/ETH计算,约合8099.91美元。

我怀疑问题出在以下gasCalculated函数中,恳请帮忙排查:

func gasCalculated(from, to, token string, amount int) *big.Int {
    // Fetch the contract ABI
    contractABI, err := abi.JSON(strings.NewReader(flashLoanReceiverABI())) // Correct ABI fetching
    if err != nil {
        fmt.Println("Failed to fetch ABI:", err)
        return big.NewInt(0)
    }
    // Create context
    ctx := context.Background()

    // Fetch the base fee and gas tip (miner's tip) for the next block
    header, err := connection.Get().HeaderByNumber(ctx, nil)
    if err != nil {
        fmt.Println("Failed to get header:", err)
        return big.NewInt(0)
    }

    tip, err := connection.Get().SuggestGasTipCap(ctx)
    if err != nil {
        fmt.Println("Failed to suggest gas tip cap:", err)
        return big.NewInt(0)
    }

    // Increase the tip cap if it's too low (e.g., minimum 1 Gwei)
    minTipCap := big.NewInt(1000000000) // 1 Gwei
    if tip.Cmp(minTipCap) < 0 {
        tip.Set(minTipCap)
    }

    // Adding a margin of 2 Gwei to the base fee
    margin := big.NewInt(2000000000) // 2 Gwei

    // Calculate GasFeeCap by adding a margin to the base fee to ensure transaction inclusion
    gasFeeCap := new(big.Int).Add(header.BaseFee, margin)

    // Add the suggested gas tip cap to ensure priority in the transaction pool
    gasFeeCap.Add(gasFeeCap, tip)

    // Specify the sender and recipient addresses
    fromAddress := common.HexToAddress(from)
    toAddress := common.HexToAddress(to)
    tokenAddress := common.HexToAddress(token)

    addressType, err := abi.NewType("address", "", nil)
    if err != nil {
        log.Fatalf("Failed to create address type: %v", err)
    }

    addresses := abi.Arguments{
        {Type: addressType},
        {Type: addressType},
        {Type: addressType},
    }

    packedData, err := addresses.Pack(fromAddress, toAddress, tokenAddress)
    if err != nil {
        log.Fatalf("Failed to pack addresses: %v", err)
    }

    data, err := contractABI.Pack("onFlashLoan", fromAddress, tokenAddress, big.NewInt(int64(amount)), big.NewInt(0), packedData)
    if err != nil {
        fmt.Println("ABI packing failed:", err)
        return big.NewInt(0)
    }

    callMsg := ethereum.CallMsg{
        From:      fromAddress,
        To:        &toAddress,
        GasFeeCap: gasFeeCap,
        GasTipCap: tip,
        Value:     big.NewInt(0), // Adjust if ETH is sent along with the call
        Data:      data,
    }

    // Perform the low-level eth_call to check the transaction
    var result hexutil.Bytes
    result, err = connection.Get().CallContract(ctx, callMsg, header.Number)
    if err != nil {
        fmt.Printf("Low-level call %v\n", err) //<--Low-level call error: err: insufficient funds for gas * price + value: address 0x have 26389996078916648 want 3681518208500000000 (supplied gas 500000000)
        return big.NewInt(0)
    }

    // Decode or inspect `result` to understand the failure
    fmt.Printf("Low-level call result: %x\n", result)

    // Estimate the gas required for the transaction
    gasLimit, err := connection.Get().EstimateGas(ctx, callMsg)
    if err != nil {
        fmt.Println("Failed to estimate gas:", err)
        return big.NewInt(0)
    }

    return big.NewInt(int64(gasLimit))
}

问题排查分析

  1. GasFeeCap计算逻辑错误
    当前代码中gasFeeCap的计算是baseFee + margin + tip,但按照EIP-1559规则,gasFeeCap是用户愿意支付的单Gas最高费用,正确值应为baseFee + tip(实际支付的费用是min(gasFeeCap, baseFee + tip))。你直接将三者相加,导致gasFeeCap被大幅拉高,结合默认的超大GasLimit(500000000),总费用计算值直接超出地址余额。

  2. CallContract流程顺序错误
    代码先执行CallContract再做Gas估算,此时CallMsg未指定Gas字段,节点会使用默认的高GasLimit值。过高的GasLimit乘以错误计算的gasFeeCap,直接触发余额不足提示。正确流程应该是先估算Gas用量,再传入CallContract中。

  3. 参数匹配风险
    需确认目标合约onFlashLoan函数的参数签名是否与你打包的参数结构完全匹配,错误的参数可能导致合约执行异常,间接影响Gas费用计算。

修复建议

  • 修正gasFeeCap计算逻辑:
    // 正确计算gasFeeCap:取baseFee+tip与baseFee+margin的较大值
    basePlusTip := new(big.Int).Add(header.BaseFee, tip)
    basePlusMargin := new(big.Int).Add(header.BaseFee, margin)
    gasFeeCap := basePlusTip
    if basePlusMargin.Cmp(basePlusTip) > 0 {
        gasFeeCap = basePlusMargin
    }
    
  • 调整流程顺序,先估算Gas再执行Call:
    // 先估算Gas用量
    gasLimit, err := connection.Get().EstimateGas(ctx, callMsg)
    if err != nil {
        fmt.Println("Failed to estimate gas:", err)
        return big.NewInt(0)
    }
    // 将估算的GasLimit加入CallMsg
    callMsg.Gas = gasLimit
    // 再执行CallContract
    result, err = connection.Get().CallContract(ctx, callMsg, header.Number)
    
  • 验证目标合约onFlashLoan的函数签名,确保ABI打包的参数数量、类型完全匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:57:32