mirror of
https://github.com/luxfi/graph.git
synced 2026-09-24 00:26:07 +00:00
Deployed v1.2.10 to a six-chain explorer and watched one chain produce
aggregates while two others produced nothing at all — no result line, no error
line. Two distinct defects, both found by that silence.
1. The pass wrote O(swaps) rows per interval.
valueSwaps rewrote every swap's own amountUSD, one serialized INSERT OR
REPLACE each, every 30s. A chain with a real trade history never finished a
pass, so it never wrote its pool/factory aggregates either — while a quiet
chain beside it looked perfectly healthy. Volume is a per-pool rollup and
belongs on the pool: valueSwaps now READS the swap rows and writes none.
(Per-swap amountUSD stays "0". It is a separate gap, and the honest fix
values a swap at the price of its OWN block, not at today's.)
2. A V3 Swap emits int256, and the handler read it unsigned.
One leg of every V3 swap is negative — the token leaving the pool. Reading
it unsigned persisted ~2^256 in place of a small negative number. Nothing
had ever added those amounts up, so the corruption was invisible until the
volume rollup landed and reported $4.07e72 of trading on Zoo.
handleSwapV3 now uses decodeInt256, the same decoder the V4 handler already
used for the same reason. Rows the old build already wrote are healed on
read rather than by a re-index: a stored leg at or above 2^255 IS the
two's-complement encoding of a negative int256, and the V2 handler's
difference of two uint112 reserves can never reach that magnitude, so the
boundary is unambiguous.
Both were invisible for the same reason, so the third change is observability:
- Config.Label names the indexer ("cchain/amm") and every indexer log line
now carries it. One process runs seven of these; a line that does not say
whose it is cannot be acted on.
- Every revalue exit logs, including "read no balances", and the result line
reports valued/total pools and elapsed time. An indexer that reports
nothing was indistinguishable from one that was never scheduled.
- Each pass runs under a 60s budget, so a pass that cannot finish is
cancelled and says so instead of wedging its chain forever.
Tests pin all three: the wrapped-negative leg valuing identically to the signed
one, handleSwapV3 persisting "-2500", and revalue leaving swap rows untouched.
Co-authored-by: Hanzo Dev <[email protected]>