Skip to content

Commit 5e956fe

Browse files
authored
fix: handle empty callstacks in call tracers (#1171)
1 parent d178b00 commit 5e956fe

File tree

3 files changed

+13
-9
lines changed

3 files changed

+13
-9
lines changed

eth/tracers/native/call.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package native
1818

1919
import (
2020
"encoding/json"
21-
"errors"
2221
"math/big"
2322
"strconv"
2423
"strings"
@@ -60,21 +59,21 @@ type callTracer struct {
6059
func newCallTracer(ctx *tracers.Context) tracers.Tracer {
6160
// First callframe contains tx context info
6261
// and is populated on start and end.
63-
t := &callTracer{callstack: make([]callFrame, 1)}
62+
t := &callTracer{callstack: make([]callFrame, 0, 1)}
6463
return t
6564
}
6665

6766
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
6867
func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int, authorizationResults []types.AuthorizationResult) {
6968
t.env = env
70-
t.callstack[0] = callFrame{
69+
t.callstack = append(t.callstack, callFrame{
7170
Type: "CALL",
7271
From: addrToHex(from),
7372
To: addrToHex(to),
7473
Input: bytesToHex(input),
7574
Gas: uintToHex(gas),
7675
Value: bigToHex(value),
77-
}
76+
})
7877
if create {
7978
t.callstack[0].Type = "CREATE"
8079
}
@@ -152,7 +151,10 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
152151
// error arising from the encoding or forceful termination (via `Stop`).
153152
func (t *callTracer) GetResult() (json.RawMessage, error) {
154153
if len(t.callstack) != 1 {
155-
return nil, errors.New("incorrect number of top-level calls")
154+
// If the callstack is empty, return an empty JSON object instead of erroring
155+
// Callstack can be empty due to an edge case where an L1 message is reverted even
156+
// before entering the first call.
157+
return json.RawMessage("{}"), nil
156158
}
157159
res, err := json.Marshal(t.callstack[0])
158160
if err != nil {

eth/tracers/native/call_flat.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package native
1818

1919
import (
2020
"encoding/json"
21-
"errors"
2221
"fmt"
2322
"math/big"
2423
"strings"
@@ -115,7 +114,7 @@ type flatCallTracer struct {
115114

116115
// newFlatCallTracer returns a new flatCallTracer.
117116
func newFlatCallTracer(ctx *tracers.Context) tracers.Tracer {
118-
t := &callTracer{callstack: make([]callFrame, 1)}
117+
t := &callTracer{callstack: make([]callFrame, 0, 1)}
119118

120119
return &flatCallTracer{callTracer: t, ctx: ctx}
121120

@@ -133,7 +132,10 @@ func (t *flatCallTracer) CaptureEnter(typ vm.OpCode, from common.Address, to com
133132
// error arising from the encoding or forceful termination (via `Stop`).
134133
func (t *flatCallTracer) GetResult() (json.RawMessage, error) {
135134
if len(t.callTracer.callstack) < 1 {
136-
return nil, errors.New("invalid number of calls")
135+
// If the callstack is empty, return an empty JSON list instead of erroring
136+
// Callstack can be empty due to an edge case where an L1 message is reverted even
137+
// before entering the first call.
138+
return json.RawMessage("[]"), nil
137139
}
138140

139141
flat, err := flatFromNested(&t.callTracer.callstack[0], []int{}, true, t.ctx)

params/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
const (
2525
VersionMajor = 5 // Major version component of the current release
2626
VersionMinor = 8 // Minor version component of the current release
27-
VersionPatch = 39 // Patch version component of the current release
27+
VersionPatch = 40 // Patch version component of the current release
2828
VersionMeta = "mainnet" // Version metadata to append to the version string
2929
)
3030

0 commit comments

Comments
 (0)