From f5e0fecc2e79487cf200fad70af561c2aff5226a Mon Sep 17 00:00:00 2001 From: William Morriss Date: Tue, 7 May 2024 17:31:09 -0700 Subject: [PATCH 1/2] restore eth_estimateGas behavior in the form of eth_necessaryGas, fix eth_estimateGas doc --- graphql/graphql.go | 4 ++-- internal/ethapi/api.go | 22 ++++++++++++++++++---- internal/ethapi/transaction_args.go | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/graphql/graphql.go b/graphql/graphql.go index f7cf164d3144..39addbefa8f5 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -1213,7 +1213,7 @@ func (b *Block) Call(ctx context.Context, args struct { func (b *Block) EstimateGas(ctx context.Context, args struct { Data ethapi.TransactionArgs }) (hexutil.Uint64, error) { - return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCGasCap()) + return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCGasCap(), 0) } type Pending struct { @@ -1277,7 +1277,7 @@ func (p *Pending) EstimateGas(ctx context.Context, args struct { Data ethapi.TransactionArgs }) (hexutil.Uint64, error) { latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) - return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, latestBlockNr, nil, p.r.backend.RPCGasCap()) + return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, latestBlockNr, nil, p.r.backend.RPCGasCap(), 0) } // Resolver is the top-level object in the GraphQL hierarchy. diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index d308cead627f..53c3f769c0b6 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1182,7 +1182,7 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO // successfully at block `blockNrOrHash`. It returns error if the transaction would revert, or if // there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil & // non-zero) and `gasCap` (if non-zero). -func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, gasCap uint64) (hexutil.Uint64, error) { +func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, gasCap uint64, errorRatio float64) (hexutil.Uint64, error) { // Retrieve the base state and mutate it with any overrides state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { @@ -1197,7 +1197,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr Chain: NewChainContext(ctx, b), Header: header, State: state, - ErrorRatio: estimateGasErrorRatio, + ErrorRatio: errorRatio, } if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil { return 0, err @@ -1214,7 +1214,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr return hexutil.Uint64(estimate), nil } -// EstimateGas returns the lowest possible gas limit that allows the transaction to run +// EstimateGas returns some gas limit that allows the transaction to run // successfully at block `blockNrOrHash`, or the latest block if `blockNrOrHash` is unspecified. It // returns error if the transaction would revert or if there are unexpected failures. The returned // value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap @@ -1225,7 +1225,21 @@ func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, b if blockNrOrHash != nil { bNrOrHash = *blockNrOrHash } - return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCGasCap()) + return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCGasCap(), estimateGasErrorRatio) +} + +// NecessaryGas returns the lowest gas limit that allows the transaction to run +// successfully at block `blockNrOrHash`, or the latest block if `blockNrOrHash` is unspecified. It +// returns error if the transaction would revert or if there are unexpected failures. The returned +// value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap +// configuration (if non-zero). +// Note: Required blob gas is not computed in this method. +func (s *BlockChainAPI) NecessaryGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) { + bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + if blockNrOrHash != nil { + bNrOrHash = *blockNrOrHash + } + return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCGasCap(), 0) } // RPCMarshalHeader converts the given header to the RPC output . diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index f199f9d91253..bfb43c03ae7a 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -160,7 +160,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGas BlobHashes: args.BlobHashes, } latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) - estimated, err := DoEstimateGas(ctx, b, callArgs, latestBlockNr, nil, b.RPCGasCap()) + estimated, err := DoEstimateGas(ctx, b, callArgs, latestBlockNr, nil, b.RPCGasCap(), 0) if err != nil { return err } From 50729ecb0b5fff3ed63e113695ed5e2ef6b0a8a9 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Tue, 7 May 2024 18:04:51 -0700 Subject: [PATCH 2/2] fix DoEstimateGas docs and document errorRatio parameter --- internal/ethapi/api.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 53c3f769c0b6..3c85ac415334 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1178,10 +1178,11 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO return result.Return(), result.Err } -// DoEstimateGas returns the lowest possible gas limit that allows the transaction to run +// DoEstimateGas returns some gas limit that allows the transaction to run // successfully at block `blockNrOrHash`. It returns error if the transaction would revert, or if // there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil & // non-zero) and `gasCap` (if non-zero). +// The errorRatio specifies how much larger than the minimum necessary gas the result can be. func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, gasCap uint64, errorRatio float64) (hexutil.Uint64, error) { // Retrieve the base state and mutate it with any overrides state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)