@@ -100,12 +100,22 @@ func (s *StructLog) ErrorString() string {
100
100
return ""
101
101
}
102
102
103
+ type wrappedLog struct {
104
+ parent * wrappedLog
105
+ error error
106
+ log StructLog
107
+ children []* wrappedLog
108
+ }
109
+
103
110
// StructLogger is an EVM state logger and implements EVMLogger.
104
111
//
105
112
// StructLogger can capture state based on the given Log configuration and also keeps
106
113
// a track record of modified storage which is used in reporting snapshots of the
107
114
// contract their storage.
108
115
type StructLogger struct {
116
+ current * wrappedLog
117
+ depth int
118
+
109
119
cfg Config
110
120
env * vm.EVM
111
121
@@ -142,6 +152,8 @@ func (l *StructLogger) Reset() {
142
152
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
143
153
func (l * StructLogger ) CaptureStart (env * vm.EVM , from common.Address , to common.Address , create bool , input []byte , gas uint64 , value * big.Int ) {
144
154
l .env = env
155
+ l .depth = 0
156
+ l .current = & wrappedLog {}
145
157
}
146
158
147
159
// CaptureState logs a new structured log message and pushes it out to the environment
@@ -160,6 +172,35 @@ func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, s
160
172
memory := scope .Memory
161
173
stack := scope .Stack
162
174
contract := scope .Contract
175
+ for ; l .depth > depth - 1 ; l .depth = l .depth - 1 {
176
+ i := l .depth - (depth - 1 )
177
+ if l .current .error == nil {
178
+ switch stack .Data ()[len (stack .Data ())- i ].Bytes32 ()[31 ] {
179
+ case 0x00 :
180
+ l .current .error = fmt .Errorf ("call failed" )
181
+ }
182
+ }
183
+ l .current = l .current .parent
184
+ }
185
+ if err != nil {
186
+ l .current .error = err
187
+ }
188
+ switch op {
189
+ case vm .CALL , vm .DELEGATECALL , vm .STATICCALL , vm .CALLCODE :
190
+ l .depth = l .depth + 1
191
+ wl := & wrappedLog {
192
+ parent : l .current ,
193
+ error : l .current .error ,
194
+ }
195
+ l .current .children = append (l .current .children , wl )
196
+ l .current = wl
197
+ case vm .REVERT :
198
+ l .current .error = vm .ErrExecutionReverted
199
+ return
200
+ default :
201
+ return
202
+ }
203
+
163
204
// Copy a snapshot of the current memory state to a new buffer
164
205
var mem []byte
165
206
if l .cfg .EnableMemory {
@@ -209,7 +250,7 @@ func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, s
209
250
}
210
251
// create a new snapshot of the EVM.
211
252
log := StructLog {pc , op , gas , cost , mem , memory .Len (), stck , rdata , storage , depth , l .env .StateDB .GetRefund (), err }
212
- l .logs = append ( l . logs , log )
253
+ l .current . log = log
213
254
}
214
255
215
256
// CaptureFault implements the EVMLogger interface to trace an execution fault
@@ -219,6 +260,17 @@ func (l *StructLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, s
219
260
220
261
// CaptureEnd is called after the call finishes to finalize the tracing.
221
262
func (l * StructLogger ) CaptureEnd (output []byte , gasUsed uint64 , err error ) {
263
+ for ; l .depth > 1 ; l .depth -- {
264
+ l .current = l .current .parent
265
+ }
266
+ l .current .log = StructLog {
267
+ Op : vm .CALL ,
268
+ GasCost : gasUsed ,
269
+ ReturnData : output ,
270
+ Depth : 0 ,
271
+ Err : err ,
272
+ }
273
+
222
274
l .output = output
223
275
l .err = err
224
276
if l .cfg .Debug {
@@ -269,8 +321,19 @@ func (l *StructLogger) CaptureTxEnd(restGas uint64) {
269
321
l .usedGas = l .gasLimit - restGas
270
322
}
271
323
324
+ // Depth first append for all children (stack max depth is 1024)
325
+ func (l * wrappedLog ) getLogs () []StructLog {
326
+ var logs []StructLog
327
+ l .log .Err = l .error
328
+ logs = append (logs , l .log )
329
+ for _ , child := range l .children {
330
+ logs = append (logs , child .getLogs ()... )
331
+ }
332
+ return logs
333
+ }
334
+
272
335
// StructLogs returns the captured log entries.
273
- func (l * StructLogger ) StructLogs () []StructLog { return l .logs }
336
+ func (l * StructLogger ) StructLogs () []StructLog { return l .current . getLogs () }
274
337
275
338
// Error returns the VM error captured by the trace.
276
339
func (l * StructLogger ) Error () error { return l .err }
0 commit comments