From 1793a3be33cacd8610055a982d82bd062737a64b Mon Sep 17 00:00:00 2001 From: Aman Sanghi Date: Thu, 1 Aug 2024 15:45:57 +0530 Subject: [PATCH] Fix calldefault gas limit --- eth/tracers/api.go | 5 +++-- internal/ethapi/api.go | 15 +++++++++------ internal/ethapi/transaction_args.go | 17 +++++++++++------ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 94307f3f06..82ac3fde53 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -945,11 +945,12 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc config.BlockOverrides.Apply(&vmctx) } // Execute the trace - if err := args.CallDefaults(api.backend.RPCGasCap(), vmctx.BaseFee, api.backend.ChainConfig().ChainID); err != nil { + gasLimitNotSetByUser := args.Gas == nil + if err := args.CallDefaults(api.backend.RPCGasCap(), vmctx.BaseFee, api.backend.ChainConfig().ChainID, gasLimitNotSetByUser); err != nil { return nil, err } var ( - msg = args.ToMessage(vmctx.BaseFee, api.backend.RPCGasCap(), block.Header(), statedb, core.MessageEthcallMode) + msg = args.ToMessage(vmctx.BaseFee, api.backend.RPCGasCap(), block.Header(), statedb, core.MessageEthcallMode, api.backend.ChainConfig().ChainID, gasLimitNotSetByUser) tx = args.ToTransaction() traceConfig *TraceConfig ) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 2a95371033..b3e4629fc8 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1130,10 +1130,11 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S // Get a new instance of the EVM. var err error - if err = args.CallDefaults(globalGasCap, blockCtx.BaseFee, b.ChainConfig().ChainID); err != nil { + gasLimitNotSetByUser := args.Gas == nil + if err = args.CallDefaults(globalGasCap, blockCtx.BaseFee, b.ChainConfig().ChainID, gasLimitNotSetByUser); err != nil { return nil, err } - msg := args.ToMessage(blockCtx.BaseFee, globalGasCap, header, state, runMode) + msg := args.ToMessage(blockCtx.BaseFee, globalGasCap, header, state, runMode, b.ChainConfig().ChainID, gasLimitNotSetByUser) // Arbitrum: support NodeInterface.sol by swapping out the message if needed var res *core.ExecutionResult @@ -1295,16 +1296,17 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr ErrorRatio: gasestimator.EstimateGasErrorRatio, RunScheduledTxes: runScheduledTxes, } - if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil { + gasLimitNotSetByUser := args.Gas == nil + if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID, gasLimitNotSetByUser); err != nil { return 0, err } // Run the gas estimation andwrap any revertals into a custom return // Arbitrum: this also appropriately recursively calls another args.ToMessage with increased gasCap by posterCostInL2Gas amount - call := args.ToMessage(header.BaseFee, gasCap, header, state, core.MessageGasEstimationMode) + call := args.ToMessage(header.BaseFee, gasCap, header, state, core.MessageGasEstimationMode, b.ChainConfig().ChainID, gasLimitNotSetByUser) // Arbitrum: raise the gas cap to ignore L1 costs so that it's compute-only { - gasCap, err = args.L2OnlyGasCap(header.BaseFee, gasCap, header, state, core.MessageGasEstimationMode) + gasCap, err = args.L2OnlyGasCap(header.BaseFee, gasCap, header, state, core.MessageGasEstimationMode, b.ChainConfig().ChainID, gasLimitNotSetByUser) if err != nil { return 0, err } @@ -1723,6 +1725,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH } // Ensure any missing fields are filled, extract the recipient and input data + gasLimitNotSetByUser := args.Gas == nil if err := args.setDefaults(ctx, b, true); err != nil { return nil, 0, nil, err } @@ -1750,7 +1753,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH statedb := db.Copy() // Set the accesslist to the last al args.AccessList = &accessList - msg := args.ToMessage(header.BaseFee, b.RPCGasCap(), header, statedb, core.MessageEthcallMode) + msg := args.ToMessage(header.BaseFee, b.RPCGasCap(), header, statedb, core.MessageEthcallMode, b.ChainConfig().ChainID, gasLimitNotSetByUser) // Apply the transaction with the access list tracer tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles) diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 8f1d330e84..4563a72c7f 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -375,7 +375,7 @@ func (args *TransactionArgs) setBlobTxSidecar(ctx context.Context) error { // CallDefaults sanitizes the transaction arguments, often filling in zero values, // for the purpose of eth_call class of RPC methods. -func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int, chainID *big.Int) error { +func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int, chainID *big.Int, gasLimitNotSetByUser bool) error { // Reject invalid combinations of pre- and post-1559 fee styles if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") @@ -387,7 +387,7 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int, return fmt.Errorf("chainId does not match node's (have=%v, want=%v)", have, chainID) } } - if args.Gas == nil { + if gasLimitNotSetByUser { gas := globalGasCap if gas == 0 { gas = uint64(math.MaxUint64 / 2) @@ -427,7 +427,7 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int, } // Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called. -func (args *TransactionArgs) ToMessage(baseFee *big.Int, globalGasCap uint64, header *types.Header, state *state.StateDB, runMode core.MessageRunMode) *core.Message { +func (args *TransactionArgs) ToMessage(baseFee *big.Int, globalGasCap uint64, header *types.Header, state *state.StateDB, runMode core.MessageRunMode, chainID *big.Int, gasLimitNotSetByUser bool) *core.Message { var ( gasPrice *big.Int gasFeeCap *big.Int @@ -484,15 +484,20 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int, globalGasCap uint64, he // ToMessage recurses once to allow ArbOS to intercept the result for all callers // ArbOS uses this to modify globalGasCap so that the cap will ignore this tx's specific L1 data costs core.InterceptRPCGasCap(&globalGasCap, msg, header, state) - return args.ToMessage(baseFee, globalGasCap, header, nil, runMode) // we pass a nil to avoid another recursion + err := args.CallDefaults(globalGasCap, baseFee, chainID, gasLimitNotSetByUser) + // If we fail to call defaults, we should panic because it's a programming error since we've already called it once + if err != nil { + panic(fmt.Sprintf("CallDefaults failed: %v", err)) + } + return args.ToMessage(baseFee, globalGasCap, header, nil, runMode, chainID, gasLimitNotSetByUser) // we pass a nil to avoid another recursion } return msg } // Raises the vanilla gas cap by the tx's l1 data costs in l2 terms. This creates a new gas cap that after // data payments are made, equals the original vanilla cap for the remaining, L2-specific work the tx does. -func (args *TransactionArgs) L2OnlyGasCap(baseFee *big.Int, gasCap uint64, header *types.Header, state *state.StateDB, runMode core.MessageRunMode) (uint64, error) { - msg := args.ToMessage(baseFee, gasCap, header, nil, runMode) +func (args *TransactionArgs) L2OnlyGasCap(baseFee *big.Int, gasCap uint64, header *types.Header, state *state.StateDB, runMode core.MessageRunMode, chainID *big.Int, gasLimitNotSetByUser bool) (uint64, error) { + msg := args.ToMessage(baseFee, gasCap, header, nil, runMode, chainID, gasLimitNotSetByUser) core.InterceptRPCGasCap(&gasCap, msg, header, state) return gasCap, nil }