fix: handle empty callstacks in call tracers (#1171)

This commit is contained in:
Ömer Faruk Irmak 2025-04-24 10:59:28 +03:00 committed by GitHub
parent d178b00fb2
commit 5e956fe264
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 13 additions and 9 deletions

View file

@ -18,7 +18,6 @@ package native
import ( import (
"encoding/json" "encoding/json"
"errors"
"math/big" "math/big"
"strconv" "strconv"
"strings" "strings"
@ -60,21 +59,21 @@ type callTracer struct {
func newCallTracer(ctx *tracers.Context) tracers.Tracer { func newCallTracer(ctx *tracers.Context) tracers.Tracer {
// First callframe contains tx context info // First callframe contains tx context info
// and is populated on start and end. // and is populated on start and end.
t := &callTracer{callstack: make([]callFrame, 1)} t := &callTracer{callstack: make([]callFrame, 0, 1)}
return t return t
} }
// CaptureStart implements the EVMLogger interface to initialize the tracing operation. // CaptureStart implements the EVMLogger interface to initialize the tracing operation.
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) { 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) {
t.env = env t.env = env
t.callstack[0] = callFrame{ t.callstack = append(t.callstack, callFrame{
Type: "CALL", Type: "CALL",
From: addrToHex(from), From: addrToHex(from),
To: addrToHex(to), To: addrToHex(to),
Input: bytesToHex(input), Input: bytesToHex(input),
Gas: uintToHex(gas), Gas: uintToHex(gas),
Value: bigToHex(value), Value: bigToHex(value),
} })
if create { if create {
t.callstack[0].Type = "CREATE" t.callstack[0].Type = "CREATE"
} }
@ -152,7 +151,10 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
// error arising from the encoding or forceful termination (via `Stop`). // error arising from the encoding or forceful termination (via `Stop`).
func (t *callTracer) GetResult() (json.RawMessage, error) { func (t *callTracer) GetResult() (json.RawMessage, error) {
if len(t.callstack) != 1 { if len(t.callstack) != 1 {
return nil, errors.New("incorrect number of top-level calls") // If the callstack is empty, return an empty JSON object instead of erroring
// Callstack can be empty due to an edge case where an L1 message is reverted even
// before entering the first call.
return json.RawMessage("{}"), nil
} }
res, err := json.Marshal(t.callstack[0]) res, err := json.Marshal(t.callstack[0])
if err != nil { if err != nil {

View file

@ -18,7 +18,6 @@ package native
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"math/big" "math/big"
"strings" "strings"
@ -115,7 +114,7 @@ type flatCallTracer struct {
// newFlatCallTracer returns a new flatCallTracer. // newFlatCallTracer returns a new flatCallTracer.
func newFlatCallTracer(ctx *tracers.Context) tracers.Tracer { func newFlatCallTracer(ctx *tracers.Context) tracers.Tracer {
t := &callTracer{callstack: make([]callFrame, 1)} t := &callTracer{callstack: make([]callFrame, 0, 1)}
return &flatCallTracer{callTracer: t, ctx: ctx} return &flatCallTracer{callTracer: t, ctx: ctx}
@ -133,7 +132,10 @@ func (t *flatCallTracer) CaptureEnter(typ vm.OpCode, from common.Address, to com
// error arising from the encoding or forceful termination (via `Stop`). // error arising from the encoding or forceful termination (via `Stop`).
func (t *flatCallTracer) GetResult() (json.RawMessage, error) { func (t *flatCallTracer) GetResult() (json.RawMessage, error) {
if len(t.callTracer.callstack) < 1 { if len(t.callTracer.callstack) < 1 {
return nil, errors.New("invalid number of calls") // If the callstack is empty, return an empty JSON list instead of erroring
// Callstack can be empty due to an edge case where an L1 message is reverted even
// before entering the first call.
return json.RawMessage("[]"), nil
} }
flat, err := flatFromNested(&t.callTracer.callstack[0], []int{}, true, t.ctx) flat, err := flatFromNested(&t.callTracer.callstack[0], []int{}, true, t.ctx)

View file

@ -24,7 +24,7 @@ import (
const ( const (
VersionMajor = 5 // Major version component of the current release VersionMajor = 5 // Major version component of the current release
VersionMinor = 8 // Minor version component of the current release VersionMinor = 8 // Minor version component of the current release
VersionPatch = 39 // Patch version component of the current release VersionPatch = 40 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string VersionMeta = "mainnet" // Version metadata to append to the version string
) )