diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 03455c973..3d17459c2 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -612,6 +612,8 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs } else { hi = b.pendingBlock.GasLimit() } + // Track the maximum gas based on the account's available funds and the txn feeCap. + var accountGasLimit uint64 // Recap the highest gas allowance with account's balance. if call.GasPrice != nil && !call.GasPrice.IsZero() { balance := b.pendingState.GetBalance(call.From) // from can't be nil @@ -623,14 +625,17 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs available.Sub(available, call.Value.ToBig()) } allowance := new(big.Int).Div(available, call.GasPrice.ToBig()) - if allowance.IsUint64() && hi > allowance.Uint64() { - transfer := call.Value - if transfer == nil { - transfer = new(uint256.Int) + if allowance.IsUint64() { + accountGasLimit = allowance.Uint64() + if hi > allowance.Uint64() { + transfer := call.Value + if transfer == nil { + transfer = new(uint256.Int) + } + log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, + "sent", transfer, "gasprice", call.GasPrice, "fundable", allowance) + hi = allowance.Uint64() } - log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, - "sent", transfer, "gasprice", call.GasPrice, "fundable", allowance) - hi = allowance.Uint64() } } gasCap = hi @@ -686,6 +691,14 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs return 0, fmt.Errorf("gas required exceeds allowance (%d)", gasCap) } } + + // Adds a 20% pad to the estimated gas usage, not exceeding account gas limit + // to help mitigate gas underestimations + hi = hi + hi/5 + if accountGasLimit != 0 && hi > accountGasLimit { + hi = accountGasLimit + } + return hi, nil } diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index 0d33ca281..d97827ba3 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -450,7 +450,7 @@ func TestSimulatedBackend_EstimateGas(t *testing.T) { GasPrice: u256.Num0, Value: u256.Num1, Data: nil, - }, params.TxGas, nil, nil}, + }, 25200, nil, nil}, {"plain transfer(invalid)", ethereum.CallMsg{ From: addr, @@ -504,7 +504,7 @@ func TestSimulatedBackend_EstimateGas(t *testing.T) { GasPrice: u256.Num0, Value: nil, Data: common.Hex2Bytes("e09fface"), - }, 21275, nil, nil}, + }, 25530, nil, nil}, } for _, c := range cases { got, err := sim.EstimateGas(context.Background(), c.message) @@ -550,7 +550,7 @@ func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) { GasPrice: uint256.NewInt(0), Value: uint256.NewInt(1000), Data: nil, - }, 21000, nil}, + }, 25200, nil}, {"EstimateWithPrice", ethereum.CallMsg{ From: addr, @@ -559,7 +559,7 @@ func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) { GasPrice: uint256.NewInt(1000), Value: uint256.NewInt(1000), Data: nil, - }, 21000, nil}, + }, 25200, nil}, {"EstimateWithVeryHighPrice", ethereum.CallMsg{ From: addr, diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index ac62b207e..63945a018 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -565,8 +565,8 @@ func (ethash *Ethash) Finalize(config *chain.Config, header *types.Header, state chain consensus.ChainHeaderReader, syscall consensus.SystemCall, ) (types.Transactions, types.Receipts, error) { // Apply fork changes on PrimordialPulse block - if cfg := chain.Config(); cfg.IsPrimordialPulseBlock(header.Number.Uint64()) { - pulse.PrimordialPulseFork(state, cfg.PulseChain) + if config.IsPrimordialPulseBlock(header.Number.Uint64()) { + pulse.PrimordialPulseFork(state, config.PulseChain) } // Accumulate any block and uncle rewards and commit the final state root