fix(indexer): stop a manipulated pool from minting prices

A price used to propagate from any pool with enough depth on the priced side,
which let a thin pool with one inflated side mint a price for its other token
and carry it across the graph. Depth is now measured on the side that is
already credibly priced, and a pool-priced side may claim at most 100x that
depth.

Guard rails around it, all in one place: prices travel at most 3 hops from a
GT/anchor seed, |tick| beyond 700k is a broken init rather than a market,
stored prices must land in a plausibility band, and a TVL above $1B is treated
as corrupt instead of as a whale.

Adds a log tail so pool stats follow chain events instead of polling, a
demand-gated frontpage, and a last-good fallback so a failed refresh serves
the previous stat rather than a hole.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
labrinyang
2026-07-22 23:59:56 +08:00
co-authored by Claude Opus 4.8
parent 3a392cb141
commit d73eaf873a
17 changed files with 1002 additions and 112 deletions
+6 -3
View File
@@ -8,6 +8,7 @@
// NOTE: GT has no UP33 dex entry — UP33 pool stats stay on the frontend's
// existing dexscreener path; this indexer only serves the Uniswap catalog.
import { GT, TUNE, log, sleep } from './config'
import { plausibleUsd } from './state'
import { poolRow, setTokenPrice, upsertStats } from './store'
const LISTS = [
@@ -60,15 +61,17 @@ function ingest(p: GtPool): boolean {
const h24 = a.transactions?.h24
const txns = h24 ? (h24.buys ?? 0) + (h24.sells ?? 0) : null
upsertStats(addr, num(a.volume_usd?.h24), txns, reserve, 'geckoterminal')
// token price seeds: ground truth while fresh; depth = half the pool's reserve
// Token price seeds — these are the CREDIBLE roots the whole pricing graph
// hangs off, and they're the one input the propagation rails can't second-
// guess, so an implausible GT quote is dropped rather than seeded.
const depth = (reserve ?? 0) / 2
if (depth > 0) {
const base = tokenOfId(p.relationships?.base_token?.data?.id)
const quote = tokenOfId(p.relationships?.quote_token?.data?.id)
const bp = num(a.base_token_price_usd)
const qp = num(a.quote_token_price_usd)
if (base && bp && bp > 0) setTokenPrice(base, bp, depth, 'gt')
if (quote && qp && qp > 0) setTokenPrice(quote, qp, depth, 'gt')
if (base && plausibleUsd(bp)) setTokenPrice(base, bp, depth, 'gt')
if (quote && plausibleUsd(qp)) setTokenPrice(quote, qp, depth, 'gt')
}
return true
}