Tracing

Tracing can give detailed insights into the execution of EVM contracts. w3vm.VM supports tracing via go‑ethereum’s tracing.Hooks.

Usage

A tracing.Hooks can be passed to VM.Apply, VM.ApplyTx, and VM.Call. These methods can also be called with multiple hooks at the same time.

Example: Trace Calls and OpCodes of an Execution

w3vm contains a powerful call an opcode tracer hooks.CallTracer that can be used gain detailed insights into the execution of EVM contracts (Playground):

callTracer := hooks.NewCallTracer(os.Stdout, &hooks.CallTracerOptions{
    ShowStaticcall: true,
    DecodeABI:      true,
})
vm.ApplyTx(tx, callTracer)

Example Call Trace

Example: Generate an Access List

Access list tracing using go-ethereum’s logger.AccessListTracer (Playground):

// setup access list tracer
signer := types.MakeSigner(params.MainnetChainConfig, header.Number, header.Time)
from, _ := signer.Sender(tx)
accessListTracer := logger.NewAccessListTracer(
    nil,
    from, *tx.To(),
    gethVm.ActivePrecompiles(params.MainnetChainConfig.Rules(header.Number, header.Difficulty.Sign() == 0, header.Time)),
)
 
if _, err := vm.ApplyTx(tx, accessListTracer.Hooks()); err != nil {
    // ...
}
fmt.Println("Access List:", accessListTracer.AccessList())

Example: Trace the Execution of all OpCodes in a Block

Trace the execution of all op’s in a block (Playground):

// setup block op's tracer
var opCount [256]uint64
tracer := &tracing.Hooks{
    OnOpcode: func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
        opCount[op]++
    },
}
 
for _, tx := range block.Transactions() {
    vm.ApplyTx(tx, tracer)
}