From ad9ad8efe8fee6ccb1bdb979e655a1bcb5773733 Mon Sep 17 00:00:00 2001 From: Webster Swift Date: Tue, 7 Jul 2026 12:58:08 +0300 Subject: [PATCH] feat: handle historical state unavailability in deposit balance verification --- .../event_waiting_confirmations.go | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/internal/taskmanager/event_waiting_confirmations.go b/internal/taskmanager/event_waiting_confirmations.go index a60c90c..904f853 100644 --- a/internal/taskmanager/event_waiting_confirmations.go +++ b/internal/taskmanager/event_waiting_confirmations.go @@ -3,6 +3,7 @@ package taskmanager import ( "context" "fmt" + "strings" "github.com/dv-net/dv-processing/internal/constants" "github.com/dv-net/dv-processing/internal/models" @@ -16,6 +17,16 @@ import ( "github.com/shopspring/decimal" ) +// historicalStateUnavailableSubstr matches the error returned by non-archive EVM +// nodes when asked for account state at a pruned block height. It reflects a node +// data-availability limitation, not evidence of a balance mismatch, so it must not +// block deposit webhook creation the way a real delta mismatch does. +const historicalStateUnavailableSubstr = "historical state" + +func isHistoricalStateUnavailableErr(err error) bool { + return err != nil && strings.Contains(err.Error(), historicalStateUnavailableSubstr) +} + const JobKindWebhookWaitingConfirmations = "waiting_confirmations" type WebhookWaitingConfirmationsArgs struct { @@ -88,11 +99,21 @@ func (s *WebhookWaitingConfirmationsWorker) verifyEVMDepositBalanceDelta( balanceBefore, err := s.bs.EProxy().AddressBalanceAt(ctx, job.Args.Address, assetIdentifier, job.Args.Blockchain, blockHeight-1) if err != nil { + if isHistoricalStateUnavailableErr(err) { + s.logger.Warnf("skip deposit balance delta verification: historical state unavailable: address=%s asset=%s block=%d: %s", + job.Args.Address, assetIdentifier, blockHeight-1, err.Error()) + return nil + } return fmt.Errorf("get balance before deposit block %d: %w", blockHeight-1, err) } balanceAfter, err := s.bs.EProxy().AddressBalanceAt(ctx, job.Args.Address, assetIdentifier, job.Args.Blockchain, blockHeight) if err != nil { + if isHistoricalStateUnavailableErr(err) { + s.logger.Warnf("skip deposit balance delta verification: historical state unavailable: address=%s asset=%s block=%d: %s", + job.Args.Address, assetIdentifier, blockHeight, err.Error()) + return nil + } return fmt.Errorf("get balance after deposit block %d: %w", blockHeight, err) }