diff --git a/turbo/jsonrpc/eth_api.go b/turbo/jsonrpc/eth_api.go index 7a7d9e465e1..b01671e34f6 100644 --- a/turbo/jsonrpc/eth_api.go +++ b/turbo/jsonrpc/eth_api.go @@ -90,7 +90,7 @@ type EthAPI interface { // Sending related (see ./eth_call.go) Call(ctx context.Context, args ethapi2.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *ethapi2.StateOverrides) (hexutility.Bytes, error) - EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) + EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs) (hexutil.Uint64, error) SendRawTransaction(ctx context.Context, encodedTx hexutility.Bytes) (common.Hash, error) SendTransaction(_ context.Context, txObject interface{}) (common.Hash, error) Sign(ctx context.Context, _ common.Address, _ hexutility.Bytes) (hexutility.Bytes, error) diff --git a/turbo/jsonrpc/eth_call.go b/turbo/jsonrpc/eth_call.go index fc0372949c6..c011c098da8 100644 --- a/turbo/jsonrpc/eth_call.go +++ b/turbo/jsonrpc/eth_call.go @@ -111,7 +111,7 @@ func headerByNumberOrHash(ctx context.Context, tx kv.Tx, blockNrOrHash rpc.Block } // EstimateGas implements eth_estimateGas. Returns an estimate of how much gas is necessary to allow the transaction to complete. The transaction will not be added to the blockchain. -func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) { +func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs) (hexutil.Uint64, error) { var args ethapi2.CallArgs // if we actually get CallArgs here, we use them if argsOrNil != nil { @@ -135,36 +135,39 @@ func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs args.From = new(libcommon.Address) } - bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) - if blockNrOrHash != nil { - bNrOrHash = *blockNrOrHash + chainConfig, err := api.chainConfig(ctx, dbtx) + if err != nil { + return 0, err } - // Determine the highest gas limit can be used during the estimation. - if args.Gas != nil && uint64(*args.Gas) >= params.TxGas { - hi = uint64(*args.Gas) - } else { - // Retrieve the block to act as the gas ceiling - h, err := headerByNumberOrHash(ctx, dbtx, bNrOrHash, api) + latestCanBlockNumber, latestCanHash, isLatest, err := rpchelper.GetCanonicalBlockNumber(latestNumOrHash, dbtx, api.filters) // DoCall cannot be executed on non-canonical blocks + if err != nil { + return 0, err + } + + // try and get the block from the lru cache first then try DB before failing + block := api.tryBlockFromLru(latestCanHash) + if block == nil { + block, err = api.blockWithSenders(ctx, dbtx, latestCanHash, latestCanBlockNumber) if err != nil { return 0, err } - if h == nil { - // if a block number was supplied and there is no header return 0 - if blockNrOrHash != nil { - return 0, nil - } + } + if block == nil { + return 0, fmt.Errorf("could not find latest block in cache or db") + } - // block number not supplied, so we haven't found a pending block, read the latest block instead - h, err = headerByNumberOrHash(ctx, dbtx, latestNumOrHash, api) - if err != nil { - return 0, err - } - if h == nil { - return 0, nil - } - } - hi = h.GasLimit + stateReader, err := rpchelper.CreateStateReaderFromBlockNumber(ctx, dbtx, latestCanBlockNumber, isLatest, 0, api.stateCache, chainConfig.ChainName) + if err != nil { + return 0, err + } + header := block.HeaderNoCopy() + + // Determine the highest gas limit can be used during the estimation. + if args.Gas != nil && uint64(*args.Gas) >= params.TxGas { + hi = uint64(*args.Gas) + } else { + hi = header.GasLimit } var feeCap *big.Int @@ -174,6 +177,8 @@ func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs feeCap = args.GasPrice.ToInt() } else if args.MaxFeePerGas != nil { feeCap = args.MaxFeePerGas.ToInt() + } else if header.BaseFee != nil { + feeCap = new(big.Int).Set(header.BaseFee) } else { feeCap = libcommon.Big0 } @@ -218,35 +223,8 @@ func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs } gasCap = hi - chainConfig, err := api.chainConfig(ctx, dbtx) - if err != nil { - return 0, err - } engine := api.engine() - latestCanBlockNumber, latestCanHash, isLatest, err := rpchelper.GetCanonicalBlockNumber(latestNumOrHash, dbtx, api.filters) // DoCall cannot be executed on non-canonical blocks - if err != nil { - return 0, err - } - - // try and get the block from the lru cache first then try DB before failing - block := api.tryBlockFromLru(latestCanHash) - if block == nil { - block, err = api.blockWithSenders(ctx, dbtx, latestCanHash, latestCanBlockNumber) - if err != nil { - return 0, err - } - } - if block == nil { - return 0, fmt.Errorf("could not find latest block in cache or db") - } - - stateReader, err := rpchelper.CreateStateReaderFromBlockNumber(ctx, dbtx, latestCanBlockNumber, isLatest, 0, api.stateCache, chainConfig.ChainName) - if err != nil { - return 0, err - } - header := block.HeaderNoCopy() - caller, err := transactions.NewReusableCaller(engine, stateReader, nil, header, args, api.GasCap, latestNumOrHash, dbtx, api._blockReader, chainConfig, api.evmCallTimeout) if err != nil { return 0, err diff --git a/turbo/jsonrpc/eth_call_test.go b/turbo/jsonrpc/eth_call_test.go index 1048dd8101d..da04c32b7af 100644 --- a/turbo/jsonrpc/eth_call_test.go +++ b/turbo/jsonrpc/eth_call_test.go @@ -49,7 +49,7 @@ func TestEstimateGas(t *testing.T) { if _, err := api.EstimateGas(context.Background(), ðapi.CallArgs{ From: &from, To: &to, - }, nil); err != nil { + }); err != nil { t.Errorf("calling EstimateGas: %v", err) } }