在以太坊发送交易的时候,如果手续费计算有误或者没有事先判断账户余额是否足够,便会碰到“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的乘积然后和余额进行比较。
还有一些其他原因引起的此异常。比如有同学说,我通过区块链浏览器查询地址上余额足够,通过上面的公式计算获得的金额也小于余额,但每次通过节点发送交易,都会抛出此异常。
针对这个问题,需要做的第一步排查就是:发出交易的节点是否同步到了账户的余额,不是通过区块链浏览器查询余额,而是要直接在本地节点中查询余额。