diff --git a/ethapi/api.go b/ethapi/api.go index 3149c6700..c0be58f20 100644 --- a/ethapi/api.go +++ b/ethapi/api.go @@ -2129,7 +2129,15 @@ func (api *PublicDebugAPI) TraceTransaction(ctx context.Context, hash common.Has // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // be tracer dependent. -func (api *PublicDebugAPI) traceTx(ctx context.Context, message evmcore.Message, txctx *tracers.Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { +func (api *PublicDebugAPI) traceTx(ctx context.Context, message evmcore.Message, txctx *tracers.Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (ret interface{}, reterr error) { + + defer func() { + if r := recover(); r != nil { + log.Error("debug trace transaction failed with panic:", r) + reterr = fmt.Errorf("debug trace transaction failed with panic: %v", r) + } + }() + // Assemble the structured logger or the JavaScript tracer var ( tracer vm.Tracer @@ -2202,17 +2210,27 @@ func (api *PublicDebugAPI) traceTx(ctx context.Context, message evmcore.Message, if config.Tracer != nil && strings.Compare(*config.Tracer, "callTracer") == 0 { if strings.Contains(err.Error(), "cannot read property 'toString' of undefined") { log.Debug("error when debug with callTracer", "err", err.Error()) - callTracer, _ := tracers.New(*config.Tracer, txctx) - callTracer.CaptureStart(vmenv, message.From(), *message.To(), false, message.Data(), message.Gas(), message.Value()) + callTracer, errTracer := tracers.New(*config.Tracer, txctx) + if errTracer != nil { + return nil, errTracer + } + if message == nil || vmenv == nil { + return nil, err + } + to := message.To() + if to == nil { + to = &common.Address{} + } + callTracer.CaptureStart(vmenv, message.From(), *to, false, message.Data(), message.Gas(), message.Value()) callTracer.CaptureEnd([]byte{}, message.Gas(), time.Duration(0), fmt.Errorf("execution reverted")) - result, err = callTracer.GetResult() + return callTracer.GetResult() } } } return result, err default: - panic(fmt.Sprintf("bad tracer type %T", tracer)) + return nil, fmt.Errorf("bad tracer type %T", tracer) } }