diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 7a6a5f7efb..26fee31528 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -928,7 +928,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc config.BlockOverrides.Apply(&vmctx) } // Execute the trace - msg, err := args.ToMessage(api.backend.RPCGasCap(), block.Header(), statedb) + msg, err := args.ToMessage(api.backend.RPCGasCap(), block.Header(), statedb, types.MessageEthcallMode) if err != nil { return nil, err } diff --git a/graphql/graphql.go b/graphql/graphql.go index 255d9870e4..8f73f0cad8 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -1072,7 +1072,7 @@ func (b *Block) Call(ctx context.Context, args struct { return nil, err } } - result, err := ethapi.DoCall(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCEVMTimeout(), b.r.backend.RPCGasCap(), false) + result, err := ethapi.DoCall(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCEVMTimeout(), b.r.backend.RPCGasCap(), types.MessageEthcallMode) if err != nil { return nil, err } @@ -1142,7 +1142,7 @@ func (p *Pending) Call(ctx context.Context, args struct { Data ethapi.TransactionArgs }) (*CallResult, error) { pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) - result, err := ethapi.DoCall(ctx, p.r.backend, args.Data, pendingBlockNr, nil, p.r.backend.RPCEVMTimeout(), p.r.backend.RPCGasCap(), false) + result, err := ethapi.DoCall(ctx, p.r.backend, args.Data, pendingBlockNr, nil, p.r.backend.RPCEVMTimeout(), p.r.backend.RPCGasCap(), types.MessageEthcallMode) if err != nil { return nil, err } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index eccef0c991..9cceb6e834 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -959,7 +959,7 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) { } } -func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64, gasEstimation bool) (*core.ExecutionResult, error) { +func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64, runMode types.MessageRunMode) (*core.ExecutionResult, error) { defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) @@ -982,27 +982,17 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash defer cancel() // Get a new instance of the EVM. - msg, err := args.ToMessage(globalGasCap, header, state) + msg, err := args.ToMessage(globalGasCap, header, state, runMode) if err != nil { return nil, err } - // Arbitrum: mark the reason for this call - var txRunMode types.MessageRunMode - if gasEstimation { - txRunMode = types.MessageGasEstimationMode - } else { - txRunMode = types.MessageEthcallMode - } - msg.TxRunMode = txRunMode - // Arbitrum: support NodeInterface.sol by swapping out the message if needed var res *core.ExecutionResult msg, res, err = core.InterceptRPCMessage(msg, ctx, state, header, b) if err != nil || res != nil { return res, err } - msg.TxRunMode = txRunMode evm, vmError, err := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}) if err != nil { @@ -1032,7 +1022,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash // Arbitrum: a tx can schedule another (see retryables) scheduled := result.ScheduledTxes - for gasEstimation && len(scheduled) > 0 { + for runMode == types.MessageGasEstimationMode && len(scheduled) > 0 { // make a new EVM for the scheduled Tx (an EVM must never be reused) evm, vmError, err := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}) if err != nil { @@ -1109,7 +1099,7 @@ func (e *revertError) ErrorData() interface{} { // Note, this function doesn't make and changes in the state/blockchain and is // useful to execute and retrieve values. func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) { - result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap(), false) + result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap(), types.MessageEthcallMode) if err != nil { if client := fallbackClientFor(s.b, err); client != nil { var res hexutil.Bytes @@ -1213,7 +1203,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr executable := func(gas uint64) (bool, *core.ExecutionResult, error) { args.Gas = (*hexutil.Uint64)(&gas) - result, err := DoCall(ctx, b, args, blockNrOrHash, nil, 0, vanillaGasCap, true) + result, err := DoCall(ctx, b, args, blockNrOrHash, nil, 0, vanillaGasCap, types.MessageGasEstimationMode) if err != nil { if errors.Is(err, core.ErrIntrinsicGas) { return true, nil, nil // Special case, raise gas limit @@ -1657,7 +1647,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, err := args.ToMessage(b.RPCGasCap(), header, statedb) + msg, err := args.ToMessage(b.RPCGasCap(), header, statedb, types.MessageEthcallMode) if err != nil { return nil, 0, nil, err } diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 93466c3a68..987d28e4c9 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -201,7 +201,7 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ // ToMessage converts the transaction arguments to the Message type used by the // core evm. This method is used in calls and traces that do not require a real // live transaction. -func (args *TransactionArgs) ToMessage(globalGasCap uint64, header *types.Header, state *state.StateDB) (types.Message, error) { +func (args *TransactionArgs) ToMessage(globalGasCap uint64, header *types.Header, state *state.StateDB, runMode types.MessageRunMode) (types.Message, error) { baseFee := header.BaseFee // Reject invalid combinations of pre- and post-1559 fee styles @@ -268,13 +268,14 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, header *types.Header accessList = *args.AccessList } msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true) + msg.TxRunMode = runMode // Arbitrum: raise the gas cap to ignore L1 costs so that it's compute-only if core.InterceptRPCGasCap != nil && state != nil { // 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(globalGasCap, header, nil) // we pass a nil to avoid another recursion + return args.ToMessage(globalGasCap, header, nil, runMode) // we pass a nil to avoid another recursion } return msg, nil } @@ -282,11 +283,10 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, header *types.Header // 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(gasCap uint64, header *types.Header, state *state.StateDB, runMode types.MessageRunMode) (uint64, error) { - msg, err := args.ToMessage(gasCap, header, nil) + msg, err := args.ToMessage(gasCap, header, nil, runMode) if err != nil { return 0, err } - msg.TxRunMode = runMode core.InterceptRPCGasCap(&gasCap, msg, header, state) return gasCap, nil }