eth/gasestimator: check ErrGasLimitTooHigh conditions (#32348)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run

This PR makes 2 changes to how
[EIP-7825](https://github.com/ethereum/go-ethereum/pull/31824) behaves.

When `eth_estimateGas` or `eth_createAccessList` is called without any
gas limit in the payload, geth will choose the block's gas limit or the
`RPCGasCap`, which can be larger than the `maxTxGas`.

When this happens for `estimateGas`, the gas estimation just errors out
and ends, when it should continue doing binary search to find the lowest
possible gas limit.

This PR will: 
- Add a check to see if `hi` is larger than `maxTxGas` and cap it to
`maxTxGas` if it's larger. And add a special case handling for gas
estimation execute when it errs with `ErrGasLimitTooHigh`

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This commit is contained in:
Minhyuk Kim 2025-08-05 20:51:16 +09:00 committed by GitHub
parent e9dca3b181
commit 59405c40d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 0 deletions

View file

@ -62,6 +62,23 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
if call.GasLimit >= params.TxGas {
hi = call.GasLimit
}
// Cap the maximum gas allowance according to EIP-7825 if the estimation targets Osaka
if hi > params.MaxTxGas {
blockNumber, blockTime := opts.Header.Number, opts.Header.Time
if opts.BlockOverrides != nil {
if opts.BlockOverrides.Number != nil {
blockNumber = opts.BlockOverrides.Number.ToInt()
}
if opts.BlockOverrides.Time != nil {
blockTime = uint64(*opts.BlockOverrides.Time)
}
}
if opts.Config.IsOsaka(blockNumber, blockTime) {
hi = params.MaxTxGas
}
}
// Normalize the max fee per gas the call is willing to spend.
var feeCap *big.Int
if call.GasFeeCap != nil {
@ -209,6 +226,9 @@ func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit ui
if errors.Is(err, core.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
}
if errors.Is(err, core.ErrGasLimitTooHigh) {
return true, nil, nil // Special case, lower gas limit
}
return true, nil, err // Bail out
}
return result.Failed(), result, nil

View file

@ -31,6 +31,10 @@ import (
type precompileContract struct{}
func (p *precompileContract) Name() string {
panic("implement me")
}
func (p *precompileContract) RequiredGas(input []byte) uint64 { return 0 }
func (p *precompileContract) Run(input []byte) ([]byte, error) { return nil, nil }