原创 标题:  以太坊手续费不足异常(insufficient funds)

在以太坊发送交易的时候,如果手续费计算有误或者没有事先判断账户余额是否足够,便会碰到“insufficient funds for gas * price + value”异常。今天就带大家看看源代码分析一下此异常的始末。

手续费不足异常

手续费不足异常,顾名思义就是发起交易所需手续费超过了地址中的余额。我们知道,发起交易所需的手续费是由gasLimit和gasPrice组成,即它们的乘积。然而交易一旦发出之后,实际消费的手续费却是由gasPrice和交易的字节数决定的。

我们先看一下异常信息:

Insufficient funds for gas * price + value

这条异常信息就是告诉我们:当前地址的余额不足以支付gasLimit乘以gasPrice再加上转账的value值。异常中的gas指的就是gasLimit,price就是gasPrice,value指的是发起交易转账的以太币。

源代码分析

异常定义代码,注释部分已经很明确的说明了异常信息发生的情况:

// ErrInsufficientFunds is returned if the total cost of executing a transaction
    // is higher than the balance of the user's account.
    ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value")

调用检验金额代码:

// Transactor should have enough funds to cover the costs
    // cost == V + GP * GL
    if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
        return ErrInsufficientFunds
    }

再看一下tx.Cost是如何计算获取得到的:

// Cost returns amount + gasprice * gaslimit.
func (tx *Transaction) Cost() *big.Int {
    total := new(big.Int).Mul(tx.data.Price, new(big.Int).SetUint64(tx.data.GasLimit))
    total.Add(total, tx.data.Amount)
    return total
}

很明显代码中也是通过amount加上gasprice和gaslimit的乘积然后和余额进行比较。

其他情况

还有一些其他原因引起的此异常。比如有同学说,我通过区块链浏览器查询地址上余额足够,通过上面的公式计算获得的金额也小于余额,但每次通过节点发送交易,都会抛出此异常。

针对这个问题,需要做的第一步排查就是:发出交易的节点是否同步到了账户的余额,不是通过区块链浏览器查询余额,而是要直接在本地节点中查询余额。