From dccb2f36cda220c9250c3d17d1757ce29e2f7ce4 Mon Sep 17 00:00:00 2001 From: Matthieu Vachon Date: Wed, 1 May 2024 13:27:39 -0400 Subject: [PATCH] Fixed the rare case where a tx receipt is `nil` I think this cannot happen in the wild while syncing block, otherwise it would mean the transaction would have no receipt which is impossible. However in testing conditions or when doing "speculative exeuction", it's possible to get that condition. This is just to better deal with a potential `nil pointer exception`. --- eth/tracers/firehose.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/eth/tracers/firehose.go b/eth/tracers/firehose.go index 42f365ead1..3183f45bfb 100644 --- a/eth/tracers/firehose.go +++ b/eth/tracers/firehose.go @@ -281,6 +281,8 @@ func (f *Firehose) resetBlock() { // resetTransaction resets the transaction state and the call state in one shot func (f *Firehose) resetTransaction() { + firehoseDebug("resetting transaction state") + f.transaction = nil f.evm = nil f.transactionLogIndex = 0 @@ -683,8 +685,6 @@ func (f *Firehose) assignOrdinalAndIndexToReceiptLogs() { trx := f.transaction - receiptsLogs := trx.Receipt.Logs - callLogs := []*pbeth.Log{} for _, call := range trx.Calls { firehoseTrace("checking call (reverted=%t logs=%d)", call.StateReverted, len(call.Logs)) @@ -699,6 +699,24 @@ func (f *Firehose) assignOrdinalAndIndexToReceiptLogs() { return cmp.Compare(i.Ordinal, j.Ordinal) }) + // When a transaction failed the receipt can be nil, so we need to deal with this + var receiptsLogs []*pbeth.Log + if trx.Receipt == nil { + if len(callLogs) == 0 { + // No logs in the transaction (nor in calls), nothing to do + return + } + + panic(fmt.Errorf( + "mismatch between Firehose call logs and Ethereum transaction %s receipt logs at block #%d, the transaction has no receipt (failed) so there is no logs but it exists %d Firehose call logs", + hex.EncodeToString(trx.Hash), + f.block.Number, + len(callLogs), + )) + } else { + receiptsLogs = trx.Receipt.Logs + } + if len(callLogs) != len(receiptsLogs) { panic(fmt.Errorf( "mismatch between Firehose call logs and Ethereum transaction %s receipt logs at block #%d, transaction receipt has %d logs but there is %d Firehose call logs",