11package main
22
33import (
4+ "encoding/json"
45 "fmt"
6+ "github.com/ethereum/go-ethereum/eth/tracers"
57 "math/big"
68
79 "github.com/ethereum/go-ethereum/common"
@@ -12,6 +14,7 @@ import (
1214 "github.com/ethereum/go-ethereum/core/types"
1315 "github.com/ethereum/go-ethereum/core/vm"
1416 "github.com/ethereum/go-ethereum/eth/tracers/logger"
17+ _ "github.com/ethereum/go-ethereum/eth/tracers/native"
1518 "github.com/ethereum/go-ethereum/params"
1619 "github.com/imdario/mergo"
1720)
@@ -21,10 +24,11 @@ import (
2124// while replaying a transaction in debug mode as well as transaction
2225// execution status, the amount of gas used and the return value
2326type ExecutionResult struct {
24- Gas uint64 `json:"gas"`
25- Failed bool `json:"failed"`
26- ReturnValue string `json:"returnValue"`
27- StructLogs []StructLogRes `json:"structLogs"`
27+ Gas uint64 `json:"gas"`
28+ Failed bool `json:"failed"`
29+ ReturnValue string `json:"returnValue"`
30+ StructLogs []StructLogRes `json:"structLogs"`
31+ Prestate json.RawMessage `json:"prestate"`
2832}
2933
3034// StructLogRes stores a structured log emitted by the EVM while replaying a
@@ -236,22 +240,92 @@ func Trace(config TraceConfig) ([]*ExecutionResult, error) {
236240 // Run the transactions with tracing enabled.
237241 executionResults := make ([]* ExecutionResult , len (config .Transactions ))
238242 for i , message := range messages {
239- tracer := logger .NewStructLogger (config .LoggerConfig )
240- evm := vm .NewEVM (blockCtx , core .NewEVMTxContext (& message ), stateDB , & chainConfig , vm.Config {Debug : true , Tracer : tracer , NoBaseFee : true })
243+ txContext := core .NewEVMTxContext (& message )
244+ prestateTracer , err := tracers .DefaultDirectory .New ("prestateTracer" , new (tracers.Context ), nil )
245+ if err != nil {
246+ return nil , fmt .Errorf ("Failed to create prestateTracer: %w" , err )
247+ }
248+ structLogger := logger .NewStructLogger (config .LoggerConfig )
249+ tracer := NewMuxTracer (
250+ structLogger ,
251+ prestateTracer ,
252+ )
253+ evm := vm .NewEVM (blockCtx , txContext , stateDB , & chainConfig , vm.Config {Debug : true , Tracer : tracer , NoBaseFee : true })
241254
242255 result , err := core .ApplyMessage (evm , & message , new (core.GasPool ).AddGas (message .GasLimit ))
243256 if err != nil {
244257 return nil , fmt .Errorf ("Failed to apply config.Transactions[%d]: %w" , i , err )
245258 }
246259 stateDB .Finalise (true )
247260
261+ prestate , err := prestateTracer .GetResult ()
262+ if err != nil {
263+ return nil , fmt .Errorf ("Failed to get prestateTracer result: %w" , err )
264+ }
248265 executionResults [i ] = & ExecutionResult {
249266 Gas : result .UsedGas ,
250267 Failed : result .Failed (),
251268 ReturnValue : fmt .Sprintf ("%x" , result .ReturnData ),
252- StructLogs : FormatLogs (tracer .StructLogs ()),
269+ StructLogs : FormatLogs (structLogger .StructLogs ()),
270+ Prestate : prestate ,
253271 }
254272 }
255273
256274 return executionResults , nil
257275}
276+
277+ type MuxTracer struct {
278+ tracers []vm.EVMLogger
279+ }
280+
281+ func NewMuxTracer (tracers ... vm.EVMLogger ) * MuxTracer {
282+ return & MuxTracer {tracers }
283+ }
284+
285+ func (t * MuxTracer ) CaptureTxStart (gasLimit uint64 ) {
286+ for _ , tracer := range t .tracers {
287+ tracer .CaptureTxStart (gasLimit )
288+ }
289+ }
290+
291+ func (t * MuxTracer ) CaptureTxEnd (restGas uint64 ) {
292+ for _ , tracer := range t .tracers {
293+ tracer .CaptureTxEnd (restGas )
294+ }
295+ }
296+
297+ func (t * MuxTracer ) CaptureStart (env * vm.EVM , from common.Address , to common.Address , create bool , input []byte , gas uint64 , value * big.Int ) {
298+ for _ , tracer := range t .tracers {
299+ tracer .CaptureStart (env , from , to , create , input , gas , value )
300+ }
301+ }
302+
303+ func (t * MuxTracer ) CaptureEnd (output []byte , gasUsed uint64 , err error ) {
304+ for _ , tracer := range t .tracers {
305+ tracer .CaptureEnd (output , gasUsed , err )
306+ }
307+ }
308+
309+ func (t * MuxTracer ) CaptureEnter (typ vm.OpCode , from common.Address , to common.Address , input []byte , gas uint64 , value * big.Int ) {
310+ for _ , tracer := range t .tracers {
311+ tracer .CaptureEnter (typ , from , to , input , gas , value )
312+ }
313+ }
314+
315+ func (t * MuxTracer ) CaptureExit (output []byte , gasUsed uint64 , err error ) {
316+ for _ , tracer := range t .tracers {
317+ tracer .CaptureExit (output , gasUsed , err )
318+ }
319+ }
320+
321+ func (t * MuxTracer ) CaptureState (pc uint64 , op vm.OpCode , gas , cost uint64 , scope * vm.ScopeContext , rData []byte , depth int , err error ) {
322+ for _ , tracer := range t .tracers {
323+ tracer .CaptureState (pc , op , gas , cost , scope , rData , depth , err )
324+ }
325+ }
326+
327+ func (t * MuxTracer ) CaptureFault (pc uint64 , op vm.OpCode , gas , cost uint64 , scope * vm.ScopeContext , depth int , err error ) {
328+ for _ , tracer := range t .tracers {
329+ tracer .CaptureFault (pc , op , gas , cost , scope , depth , err )
330+ }
331+ }
0 commit comments