diff --git a/core/vm/logger.go b/core/vm/logger.go index 8b5b81d60d..14ce81e434 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -31,6 +31,7 @@ type EVMLogger interface { // Transaction level CaptureTxStart(gasLimit uint64) CaptureTxEnd(restGas uint64) + CaptureSystemTxEnd(intrinsicGas uint64) // Top call frame CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) CaptureEnd(output []byte, gasUsed uint64, err error) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index b26b6b5c93..53f057ba84 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -927,6 +927,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex }() defer cancel() + var intrinsicGas uint64 = 0 // Run the transaction with tracing enabled. if posa, ok := api.backend.Engine().(consensus.PoSA); ok && message.From() == vmctx.Coinbase && posa.IsSystemContract(message.To()) && message.GasPrice().Cmp(big.NewInt(0)) == 0 { @@ -935,6 +936,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex statedb.SetBalance(consensus.SystemAddress, big.NewInt(0)) statedb.AddBalance(vmctx.Coinbase, balance) } + intrinsicGas, _ = core.IntrinsicGas(message.Data(), message.AccessList(), false, true, true) } // Call Prepare to clear out the statedb access list @@ -942,6 +944,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex if _, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())); err != nil { return nil, fmt.Errorf("tracing failed: %w", err) } + tracer.CaptureSystemTxEnd(intrinsicGas) return tracer.GetResult() } diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index 2af81a83c8..911998440a 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -212,6 +212,8 @@ func (t *jsTracer) CaptureTxStart(gasLimit uint64) { // transaction processing. func (t *jsTracer) CaptureTxEnd(restGas uint64) {} +func (t *jsTracer) CaptureSystemTxEnd(intrinsicGas uint64) {} + // CaptureStart implements the Tracer interface to initialize the tracing operation. func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { t.env = env diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index 766ee4e4b9..91a2428d79 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -172,6 +172,8 @@ func (*AccessListTracer) CaptureTxStart(gasLimit uint64) {} func (*AccessListTracer) CaptureTxEnd(restGas uint64) {} +func (*AccessListTracer) CaptureSystemTxEnd(intrinsicGas uint64) {} + // AccessList returns the current accesslist maintained by the tracer. func (a *AccessListTracer) AccessList() types.AccessList { return a.list.accessList() diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index 5034233a26..6ee34e397d 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -269,6 +269,10 @@ func (l *StructLogger) CaptureTxEnd(restGas uint64) { l.usedGas = l.gasLimit - restGas } +func (l *StructLogger) CaptureSystemTxEnd(intrinsicGas uint64) { + l.usedGas -= intrinsicGas +} + // StructLogs returns the captured log entries. func (l *StructLogger) StructLogs() []StructLog { return l.logs } @@ -398,6 +402,8 @@ func (*mdLogger) CaptureTxStart(gasLimit uint64) {} func (*mdLogger) CaptureTxEnd(restGas uint64) {} +func (*mdLogger) CaptureSystemTxEnd(intrinsicGas uint64) {} + // ExecutionResult groups all structured logs emitted by the EVM // while replaying a transaction in debug mode as well as transaction // execution status, the amount of gas used and the return value diff --git a/eth/tracers/logger/logger_json.go b/eth/tracers/logger/logger_json.go index 37f1371d05..5ec0d2c44b 100644 --- a/eth/tracers/logger/logger_json.go +++ b/eth/tracers/logger/logger_json.go @@ -100,3 +100,5 @@ func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {} func (l *JSONLogger) CaptureTxStart(gasLimit uint64) {} func (l *JSONLogger) CaptureTxEnd(restGas uint64) {} + +func (l *JSONLogger) CaptureSystemTxEnd(intrinsicGas uint64) {} diff --git a/eth/tracers/native/4byte.go b/eth/tracers/native/4byte.go index 949504fff8..0eb64ecb0c 100644 --- a/eth/tracers/native/4byte.go +++ b/eth/tracers/native/4byte.go @@ -131,6 +131,8 @@ func (*fourByteTracer) CaptureTxStart(gasLimit uint64) {} func (*fourByteTracer) CaptureTxEnd(restGas uint64) {} +func (*fourByteTracer) CaptureSystemTxEnd(intrinsicGas uint64) {} + // GetResult returns the json-encoded nested list of call traces, and any // error arising from the encoding or forceful termination (via `Stop`). func (t *fourByteTracer) GetResult() (json.RawMessage, error) { diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go index ed26a79c80..883eaae595 100644 --- a/eth/tracers/native/call.go +++ b/eth/tracers/native/call.go @@ -234,6 +234,10 @@ func (t *callTracer) CaptureTxEnd(restGas uint64) { } } +func (t *callTracer) CaptureSystemTxEnd(intrinsicGas uint64) { + t.callstack[0].GasUsed -= intrinsicGas +} + // GetResult returns the json-encoded nested list of call traces, and any // error arising from the encoding or forceful termination (via `Stop`). func (t *callTracer) GetResult() (json.RawMessage, error) { diff --git a/eth/tracers/native/mux.go b/eth/tracers/native/mux.go index 878e2dc9d6..4ccd865941 100644 --- a/eth/tracers/native/mux.go +++ b/eth/tracers/native/mux.go @@ -113,6 +113,12 @@ func (t *muxTracer) CaptureTxEnd(restGas uint64) { } } +func (t *muxTracer) CaptureSystemTxEnd(intrinsicGas uint64) { + for _, t := range t.tracers { + t.CaptureSystemTxEnd(intrinsicGas) + } +} + // GetResult returns an empty json object. func (t *muxTracer) GetResult() (json.RawMessage, error) { resObject := make(map[string]json.RawMessage) diff --git a/eth/tracers/native/noop.go b/eth/tracers/native/noop.go index c1035bd1b7..1fb87a795c 100644 --- a/eth/tracers/native/noop.go +++ b/eth/tracers/native/noop.go @@ -67,6 +67,8 @@ func (*noopTracer) CaptureTxStart(gasLimit uint64) {} func (*noopTracer) CaptureTxEnd(restGas uint64) {} +func (*noopTracer) CaptureSystemTxEnd(intrinsicGas uint64) {} + // GetResult returns an empty json object. func (t *noopTracer) GetResult() (json.RawMessage, error) { return json.RawMessage(`{}`), nil diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go index 6f32af09a9..7a22317a18 100644 --- a/eth/tracers/native/prestate.go +++ b/eth/tracers/native/prestate.go @@ -136,6 +136,8 @@ func (t *prestateTracer) CaptureTxStart(gasLimit uint64) { func (t *prestateTracer) CaptureTxEnd(restGas uint64) {} +func (t *prestateTracer) CaptureSystemTxEnd(intrinsicGas uint64) {} + // GetResult returns the json-encoded nested list of call traces, and any // error arising from the encoding or forceful termination (via `Stop`). func (t *prestateTracer) GetResult() (json.RawMessage, error) {