celo-org / celo-org/mondeto

Subgraph paging silently truncates at MAX_SKIP, overstating the net gain of the holders it drops

Open
#243 1 comment 0 reactions 1 assignee Claimed by @GigaHierz View on GitHub
bug priority:low size:S
Dominant language
TypeScript
Stars
1
Forks
2
Avg merge
6d 8h
Merged PRs (30d)
10

Description

## Problem

`fetchOwnerStatsAtBlock` / the paging loop in `apps/web/src/lib/subgraph.ts:172` bounds itself with `for (let skip = 0; skip <= MAX_SKIP; skip += PAGE)` where `MAX_SKIP = 5000`. It exits either because a short page ended the data (correct) or because the cap bound (silent truncation) — and the two are indistinguishable from the outside. There are zero `logger` calls in the loop.

The admin's equivalent loops until a short page with no cap.

## Why the direction of the error is bad

Rows are ordered by `pixelCount` desc, so truncation drops the **smallest** holders. On the campaign board those rows are read at two pinned blocks and diffed. A wallet missing from the **start** read is treated as absent ⇒ 0, so its net gain is computed as `pixelCount(end) − 0` — **overstating** the gain of exactly the wallets that got dropped.

Harmless at today's holder counts. It becomes a wrong-ranking bug, silently, at the point the map gets popular enough to matter — and the failure is invisible because nothing records that the cap bound.

## Suggested fix

One line: when the loop exits on the cap rather than on a short page, `logger.warn('owner stats paging hit the cap', { mapId, block, rows: rows.length })`. That converts a silent wrong answer into a searchable signal.

Raising or removing `MAX_SKIP` is a separate call — the cap presumably exists to bound request cost — but whichever way that goes, it should be observable when it binds.

## Acceptance

A paging run that hits `MAX_SKIP` emits a warning naming the map and block. A run that ends on a short page does not.

Refs #224

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.