@@ -2,9 +2,10 @@ package jsonrpc
22
33import (
44 "context"
5- "github.com/ledgerwatch/erigon-lib/common/hexutil"
65 "math/big"
76
7+ "github.com/ledgerwatch/erigon-lib/common/hexutil"
8+
89 "github.com/holiman/uint256"
910
1011 "github.com/ledgerwatch/erigon-lib/common"
@@ -29,25 +30,28 @@ func (api *OtterscanAPIImpl) TraceTransaction(ctx context.Context, hash common.H
2930}
3031
3132type TraceEntry struct {
32- Type string `json:"type"`
33- Depth int `json:"depth"`
34- From common.Address `json:"from"`
35- To common.Address `json:"to"`
36- Value * hexutil.Big `json:"value"`
37- Input hexutility.Bytes `json:"input"`
33+ Type string `json:"type"`
34+ Depth int `json:"depth"`
35+ From common.Address `json:"from"`
36+ To common.Address `json:"to"`
37+ Value * hexutil.Big `json:"value"`
38+ Input hexutility.Bytes `json:"input"`
39+ Output hexutility.Bytes `json:"output"`
3840}
3941
4042type TransactionTracer struct {
4143 DefaultTracer
4244 ctx context.Context
4345 Results []* TraceEntry
4446 depth int // computed from CaptureStart, CaptureEnter, and CaptureExit calls
47+ stack []* TraceEntry
4548}
4649
4750func NewTransactionTracer (ctx context.Context ) * TransactionTracer {
4851 return & TransactionTracer {
4952 ctx : ctx ,
5053 Results : make ([]* TraceEntry , 0 ),
54+ stack : make ([]* TraceEntry , 0 ),
5155 }
5256}
5357
@@ -62,35 +66,31 @@ func (t *TransactionTracer) captureStartOrEnter(typ vm.OpCode, from, to common.A
6266 if value != nil {
6367 _value .Set (value .ToBig ())
6468 }
65- if typ == vm .CALL {
66- t .Results = append (t .Results , & TraceEntry {"CALL" , t .depth , from , to , (* hexutil .Big )(_value ), inputCopy })
67- return
68- }
69- if typ == vm .STATICCALL {
70- t .Results = append (t .Results , & TraceEntry {"STATICCALL" , t .depth , from , to , nil , inputCopy })
71- return
72- }
73- if typ == vm .DELEGATECALL {
74- t .Results = append (t .Results , & TraceEntry {"DELEGATECALL" , t .depth , from , to , nil , inputCopy })
75- return
76- }
77- if typ == vm .CALLCODE {
78- t .Results = append (t .Results , & TraceEntry {"CALLCODE" , t .depth , from , to , (* hexutil .Big )(_value ), inputCopy })
79- return
80- }
81- if typ == vm .CREATE {
82- t .Results = append (t .Results , & TraceEntry {"CREATE" , t .depth , from , to , (* hexutil .Big )(value .ToBig ()), inputCopy })
83- return
84- }
85- if typ == vm .CREATE2 {
86- t .Results = append (t .Results , & TraceEntry {"CREATE2" , t .depth , from , to , (* hexutil .Big )(value .ToBig ()), inputCopy })
87- return
88- }
8969
90- if typ == vm .SELFDESTRUCT {
70+ var entry * TraceEntry
71+ if typ == vm .CALL {
72+ entry = & TraceEntry {"CALL" , t .depth , from , to , (* hexutil .Big )(_value ), inputCopy , nil }
73+ } else if typ == vm .STATICCALL {
74+ entry = & TraceEntry {"STATICCALL" , t .depth , from , to , nil , inputCopy , nil }
75+ } else if typ == vm .DELEGATECALL {
76+ entry = & TraceEntry {"DELEGATECALL" , t .depth , from , to , nil , inputCopy , nil }
77+ } else if typ == vm .CALLCODE {
78+ entry = & TraceEntry {"CALLCODE" , t .depth , from , to , (* hexutil .Big )(_value ), inputCopy , nil }
79+ } else if typ == vm .CREATE {
80+ entry = & TraceEntry {"CREATE" , t .depth , from , to , (* hexutil .Big )(value .ToBig ()), inputCopy , nil }
81+ } else if typ == vm .CREATE2 {
82+ entry = & TraceEntry {"CREATE2" , t .depth , from , to , (* hexutil .Big )(value .ToBig ()), inputCopy , nil }
83+ } else if typ == vm .SELFDESTRUCT {
9184 last := t .Results [len (t .Results )- 1 ]
92- t .Results = append (t .Results , & TraceEntry {"SELFDESTRUCT" , last .Depth + 1 , from , to , (* hexutil .Big )(value .ToBig ()), nil })
85+ entry = & TraceEntry {"SELFDESTRUCT" , last .Depth + 1 , from , to , (* hexutil .Big )(value .ToBig ()), nil , nil }
86+ } else {
87+ // safeguard in case new CALL-like opcodes are introduced but not handled,
88+ // otherwise CaptureExit/stack will get out of sync
89+ entry = & TraceEntry {"UNKNOWN" , t .depth , from , to , (* hexutil .Big )(value .ToBig ()), inputCopy , nil }
9390 }
91+
92+ t .Results = append (t .Results , entry )
93+ t .stack = append (t .stack , entry )
9494}
9595
9696func (t * TransactionTracer ) CaptureStart (env * vm.EVM , from common.Address , to common.Address , precompile bool , create bool , input []byte , gas uint64 , value * uint256.Int , code []byte ) {
@@ -103,6 +103,22 @@ func (t *TransactionTracer) CaptureEnter(typ vm.OpCode, from common.Address, to
103103 t .captureStartOrEnter (typ , from , to , precompile , input , value )
104104}
105105
106- func (t * TransactionTracer ) CaptureExit (output []byte , usedGas uint64 , err error ) {
106+ func (t * TransactionTracer ) captureEndOrExit (output []byte , usedGas uint64 , err error ) {
107107 t .depth --
108+
109+ lastIdx := len (t .stack ) - 1
110+ pop := t .stack [lastIdx ]
111+ t .stack = t .stack [:lastIdx ]
112+
113+ outputCopy := make ([]byte , len (output ))
114+ copy (outputCopy , output )
115+ pop .Output = outputCopy
116+ }
117+
118+ func (t * TransactionTracer ) CaptureExit (output []byte , usedGas uint64 , err error ) {
119+ t .captureEndOrExit (output , usedGas , err )
120+ }
121+
122+ func (t * TransactionTracer ) CaptureEnd (output []byte , usedGas uint64 , err error ) {
123+ t .captureEndOrExit (output , usedGas , err )
108124}
0 commit comments