diff --git a/pkg/beacon/default.go b/pkg/beacon/default.go index c18407b..43562d7 100644 --- a/pkg/beacon/default.go +++ b/pkg/beacon/default.go @@ -748,10 +748,18 @@ func (d *Default) ListFinalizedSlots(ctx context.Context) ([]phase0.Slot, error) return slots, errors.New("no finalized checkpoint available") } - latestSlot := phase0.Slot(uint64(finality.Finalized.Epoch) * uint64(sp.SlotsPerEpoch)) - + latestSlot := uint64(finality.Finalized.Epoch) * uint64(sp.SlotsPerEpoch) //nolint:gosec // HistoricalEpochCount is validated as positive in config. - for i, val := uint64(latestSlot), uint64(latestSlot)-uint64(sp.SlotsPerEpoch)*uint64(d.config.HistoricalEpochCount); i > val; i -= uint64(sp.SlotsPerEpoch) { + lookback := uint64(sp.SlotsPerEpoch) * uint64(d.config.HistoricalEpochCount) + + // Clamp the lower bound at 0 so short-lived chains (finalized epoch < + // HistoricalEpochCount) don't underflow uint64 and skip the loop entirely. + var earliest uint64 + if latestSlot > lookback { + earliest = latestSlot - lookback + } + + for i := latestSlot; i > earliest; i -= uint64(sp.SlotsPerEpoch) { slots = append(slots, phase0.Slot(i)) }