diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 6889e98c7e..4a80942162 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -40,7 +40,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/gasestimator" "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" @@ -991,10 +990,10 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr return 0, err } // Construct the gas estimator option from the user input - opts := &gasestimator.Options{ + opts := &Options{ Config: b.ChainConfig(), Chain: chainContext, - Header: blockOverrides.MakeHeader(header), + Header: header, State: state, ErrorRatio: estimateGasErrorRatio, } @@ -1009,7 +1008,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr call := args.ToMessage(header.BaseFee, true, true) // Run the gas estimation and wrap any revertals into a custom return - estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap) + estimate, revert, err := Estimate(ctx, call, opts, gasCap, blockOverrides) if err != nil { if len(revert) > 0 { return 0, newRevertError(revert) diff --git a/eth/gasestimator/gasestimator.go b/internal/ethapi/gasestimator.go similarity index 93% rename from eth/gasestimator/gasestimator.go rename to internal/ethapi/gasestimator.go index d43057dda2..3e343f7773 100644 --- a/eth/gasestimator/gasestimator.go +++ b/internal/ethapi/gasestimator.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package gasestimator +package ethapi import ( "context" @@ -49,7 +49,7 @@ type Options struct { // Estimate returns the lowest possible gas limit that allows the transaction to // run successfully with the provided context options. It returns an error if the // transaction would always revert, or if there are unexpected failures. -func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uint64) (uint64, []byte, error) { +func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uint64, overrides *BlockOverrides) (uint64, []byte, error) { // Binary search the gas limit, as it may need to be higher than the amount used var ( lo uint64 // lowest-known gas limit where tx execution fails @@ -114,7 +114,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin // unused access list items). Ever so slightly wasteful, but safer overall. if len(call.Data) == 0 { if call.To != nil && opts.State.GetCodeSize(*call.To) == 0 { - failed, _, err := execute(ctx, call, opts, params.TxGas) + failed, _, err := execute(ctx, call, opts, params.TxGas, nil) if !failed && err == nil { return params.TxGas, nil, nil } @@ -122,7 +122,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin } // We first execute the transaction at the highest allowable gas limit, since if this fails we // can return error immediately. - failed, result, err := execute(ctx, call, opts, hi) + failed, result, err := execute(ctx, call, opts, hi, overrides) if err != nil { return 0, nil, err } @@ -144,7 +144,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin // check that gas amount and use as a limit for the binary search. optimisticGasLimit := (result.UsedGas + result.RefundedGas + params.CallStipend) * 64 / 63 if optimisticGasLimit < hi { - failed, _, err = execute(ctx, call, opts, optimisticGasLimit) + failed, _, err = execute(ctx, call, opts, optimisticGasLimit, nil) if err != nil { // This should not happen under normal conditions since if we make it this far the // transaction had run without error at least once before. @@ -175,7 +175,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin // range here is skewed to favor the low side. mid = lo * 2 } - failed, _, err = execute(ctx, call, opts, mid) + failed, _, err = execute(ctx, call, opts, mid, nil) if err != nil { // This should not happen under normal conditions since if we make it this far the // transaction had run without error at least once before. @@ -195,14 +195,14 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin // returns true if the transaction fails for a reason that might be related to // not enough gas. A non-nil error means execution failed due to reasons unrelated // to the gas limit. -func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit uint64) (bool, *core.ExecutionResult, error) { +func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit uint64, overrides *BlockOverrides) (bool, *core.ExecutionResult, error) { // Configure the call for this specific execution (and revert the change after) defer func(gas uint64) { call.GasLimit = gas }(call.GasLimit) call.GasLimit = gasLimit // Execute the call and separate execution faults caused by a lack of gas or // other non-fixable conditions - result, err := run(ctx, call, opts) + result, err := run(ctx, call, opts, overrides) if err != nil { if errors.Is(err, core.ErrIntrinsicGas) { return true, nil, nil // Special case, raise gas limit @@ -214,7 +214,7 @@ func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit ui // run assembles the EVM as defined by the consensus rules and runs the requested // call invocation. -func run(ctx context.Context, call *core.Message, opts *Options) (*core.ExecutionResult, error) { +func run(ctx context.Context, call *core.Message, opts *Options, overrides *BlockOverrides) (*core.ExecutionResult, error) { // Assemble the call and the call context var ( msgContext = core.NewEVMTxContext(call) @@ -222,6 +222,9 @@ func run(ctx context.Context, call *core.Message, opts *Options) (*core.Executio dirtyState = opts.State.Copy() ) + + overrides.Apply(&evmContext) + // Lower the basefee to 0 to avoid breaking EVM // invariants (basefee < feecap). if msgContext.GasPrice.Sign() == 0 {