Skip to content
Prices—
Free LP cash—
Net LP equity—
Queue—
Open positions—
Overflow—
Mint rate—/$
Relayer—/min
Head block—

methodology_

Every number on screen, its formula and where it is read from. Rendered from metrics.ts, the same file the code computes from. 67 of 74 metrics are live; the rest say why not.

Protocol solvency

MetricFormulaSourceGrainStatus
TreasuryExchange.treasury()
Cross-checked against the Exchange's HyperCore spot USDC (Alchemy /info spotClearinghouseState); the delta is shown.
eth_call via Multicall3live, 5 slive
HyperCore spot USDCspotClearinghouseState(user = Exchange).balances[USDC].totalAlchemy /infolive, 5 slive
Free LP cashExchange.lpBankrollAvailable()
Zero whenever anything is queued, by invariant.
eth_calllive, 5 slive
Net LP equitylpBankrollAvailable() + sideBucket() − totalQueued()
Can go negative. The single solvency number.
eth_calllive, 5 slive
LP utilisationtotalLockedMargin() / treasury()eth_calllive, 5 slive
Worst-case 1% moveΣ over markets of |net exposure| × 1%, where net exposure = Σ long notional − Σ short notional of the open set
Raw PnL before deadband, impact haircut and 2% fee, so it overstates what the LP would actually pay. Positions whose bust is crossed by the move are not netted out.
positions table (open set) + live midlive, 5 slive
Net house exposureΣ long notional − Σ short notional per market (notional = margin × leverage). The LP is short this.positions table (open set)per ingestlive
QueuetotalQueued(); length = Σ Enqueued − Σ Harvested with remaining = 0; oldest entry age from Enqueued.tseth_call + queue_eventslivelive
Loss inflowΣ lpGain (close mint event, word 2) + Σ margin of liquidated positions (PaperMinted.lossBasis)
lpGain on closes is net of the 2% fee (loss − fee); the liquidation term is gross margin, as the spec defines it.
positions tablehourly / trailing 1 hlive
Staker sweepΣ StakerLpExcessDistributed.amount (word 1)flows tablehourly / cumulativelive
Cap pin ratioshare of snapshots since launch with trackedLpUsd ≥ 0.98 × $5Msnapshots (archive eth_call every 300 blocks ≈ 5 min)since launchlive
House edge realised(Σ impact haircut + Σ win fees + Σ loss fees + Σ liquidation fees) / Σ |raw PnL|; haircut = pnlAfterDeadband − pnlAfterImpact on winspositions tablerangelive
Deadband killscount of closes where exit beat entry and pnlAfterDeadband ≤ 0positions tablerangelive
Treasury waterfallΣ Swept − Σ CoreWithdrawal vs Δ treasury since the first deposit; residual shown
Shown in QA on Day 1; the Flows page chart is Day 3.
flows + snapshotssince first depositlive
Treasury decompositiontreasury = totalBalances + totalLockedMargin + lpBankrollAvailable + sideBucket + stakerFeeAccumulator + devFeeAccumulator + residual; totalQueued drawn as a negative bandsnapshots (archive eth_call every 300 blocks)5 min since launchlive
Loss recyclercumulative Σ gross loss vs cumulative Σ StakerLpExcessDistributed vs trackedLpUsd, hourlyhourly rollup + snapshotshourly since launchlive
Hourly deposits vs withdrawalsΣ Swept.amount and Σ CoreWithdrawal.amount per UTC hourhourly rolluphourlylive
Withdrawal pressureΣ withdrawals / Σ deposits over the trailing 1 h and 24 hhourly rolluptrailinglive
LP overflow stateon if trackedLpUsd ≥ 0.98 × $5M; regime start = first hour of the current run of hours with (sweep > 0) == on; last sweep from StakerLpExcessDistributedeth_call + flows + hourlylivelive

Positions and risk

MetricFormulaSourceGrainStatus
Open positionsPositionOpened ids with no PositionClosed or Liquidated
Reconciled against Exchange.positions(id) (struct word 8 = open flag) in QA.
positions tableper ingestlive
Notionalmargin × leveragePositionOpenedper positionlive
Zero-equity priceentry × (1 − 1/lev) long; entry × (1 + 1/lev) shortPositionOpenedper positionlive
Bust price (fitted)entry × (1 ∓ (a/lev − b)); a, b by least squares of |Liquidated.bustPrice − entry| / entry on 1/lev over all liquidations
The fitted a and b, row count and residual are published on this page.
positions table (liquidations)refit on request, cachedlive
Distance to bust|mid − bust| / mid in bps, and in USD of adverse moveopen set + live midlivelive
Unrealised PnLnotional × (mid − entry) / entry × dir, before haircutopen set + live midlivepending: Take-home after deadband, impact and fee needs the deadband and impact curve constants, which are not yet fitted. Scheduled for Day 2 of the build plan (§9).
Liquidation map and laddermap: each open position as a wall at its fitted bust price from open block to now; confirmed liquidations at (close_ts, Liquidated.price); depth profile by 2 bp bucket on the same price axis; longs below mid, shorts above
Price path is 1m candles from Papertrade's own entry and exit prices (the BBO the Exchange settled at); minutes with no trade are gaps. Checked against Hyperliquid 1m closes: mean |diff| 0.28 bp.
open set + live mid + Liquidated + 1m candles from settlement printslive, 5 slive
Cascadefor a move of ±X bps: Σ notional and Σ margin of positions whose fitted bust is crossed; PAPER = margin × current mint rate; trackedLp after = trackedLp + margin, swept above $5M
Static: ignores fees taken out of margin (2%) and second-round effects. The mint rate is held at today's rate across the move.
open set + live statelivelive
Leverage distributionbuckets 1–10, 10–50, 50–100, 100–500, 500–1000 by count and notionalpositions tablerangelive
Survival curveKaplan–Meier of lifetime by leverage bucket; event = liquidation, censor = close or still openpositions tablesince launchlive
Realised liquidation probabilityliquidations / positions closed, by leverage bucket and marketpositions tablerangelive
MAE / MFE from printsfor a random sample of 1,200 closed positions held 30 s to 2 h: worst (MAE) and best (MFE) excursion from entry in bp, measured on every other settlement print in the same market between open and close
Prints are the exact BBO the Exchange settled at, but minutes with no other trade are invisible, so excursions are lower bounds.
positions (entry and exit prints)5 min, sampledlive
OI vs capsopen long and short notional per market vs latest MarketOiCapsUpdated capsopen set + admin_eventslivepending: Cap units (uint128) not yet confirmed against open notional. Scheduled for Day 2 of the build plan (§9).
Papertrade share of HyperliquidPT open notional / HL perp OI; PT hourly notional / HL hourly volumepositions + Hyperliquid public API metaAndAssetCtxslivepending: Scheduled for Day 2 of the build plan (§9).
Outcome funnelclosed positions split into wins (pnlAfterImpact > 0), losses, liquidationspositionssince launchlive
Median hold by outcomemedian(close_ts − open_ts) for wins, losses and liquidationspositionssince launchlive
Open interest historyopen notional at each hour end by market and side: baseline open set at the rollup start plus running Σ opened − Σ closedhourly rolluphourlylive

Traders

MetricFormulaSourceGrainStatus
Realised PnL per walletΣ (pnlAfterImpact − fee) on wins + Σ pnlAfterImpact on losing closes − Σ margin on liquidationspositions tablesince launchlive
VolumeΣ notional openedpositions tablerangelive
Trades, win rate, liquidationscount of closed positions; wins = closes with pnlAfterImpact > 0; liquidations = Liquidated countpositions tablesince launchlive
Cost per PAPERUSDC lost (loss inflow) / PAPER mintedpositions tableper wallet, protocol-wide per hourlive
Revenge indexshare of liquidations followed by a new open from the same wallet within 60 spositions tableper walletlive
Martingale scoreslope of margin size within a wallet's consecutive losing sequencepositions tableper walletpending: Scheduled for Day 3 of the build plan (§9).
Long biaslong notional / total notionalpositions tableper walletlive
Time-of-day heatmapopens and liquidations by UTC hour × weekdaypositions tablerangelive
Cohortsfirst-deposit day × days since; retention, net PnL, deposits vs withdrawalspositions + flowsnightlylive
Concentrationtop 10/50/100 share of volume, losses, PAPER; Lorenz curve and Ginipositions tablerangelive
Exit-after-winwithdrawals within 10 minutes of a profitable closepositions + flowsrangelive
HyperCore footprintclearinghouseState, spotClearinghouseState, openOrders for a walletAlchemy /infolivepending: Scheduled for Day 2 of the build plan (§9).
Suspicious closeswins with move < 5 bps at leverage ≥ 500x, count per wallet; shown as a distribution
A distribution, never an accusation.
positions tablerangepending: Scheduled for Day 3 of the build plan (§9).
New wallets per hourcount of wallets whose first PositionOpened falls in the hourhourly rolluphourlylive
Net flow per walletΣ deposits − Σ withdrawals per wallet, bucketed on a log scaleflowssince first depositlive
Top stakers: lost vs earnedper wallet: stakedBalance(address) live; rewards = Σ Claimed + pendingReward(address); trading PnL as realised PnL; net cash = Σ CoreWithdrawal − Σ Swept + pendingReward; paid per PAPER = Σ lpGain ÷ Σ paperMinted; income/day = share of staked × trailing-24h Distributed
Value at a reference price is a manual input; PAPER has no market.
staking_events, positions, flows, eth_call (Multicall3)5 minlive
Cost per PAPER by first-trade cohortwallets grouped by the UTC day of their first PositionOpened: Σ lpGain ÷ Σ paperMinted; payback = Σ Claimed ÷ Σ lpGainpositions, staking_events5 minlive

PAPER and stakers

MetricFormulaSourceGrainStatus
Mint rater(H) = 100 × (S / (S + H))², S = tailDecayScaleUsd() = $120M, H = tailProgressUsd(); 100 flat while trackedLpUsd < lpFlatThresholdUsd() = $2Meth_calllivelive
Realised PAPER per $Σ paperMinted / Σ tailDelta per hour, from both mint eventspositions tablehourlylive
Minted per hour by sourceΣ paperMinted, closes vs liquidationspositions tablehourlylive
Supply reconciliationΣ mints from both events vs PaperToken.totalSupply(); residual shownpositions + eth_calllivelive
Staked sharePaperStaking.totalStaked() / PaperToken.totalSupply()eth_calllivelive
Stakers countdistinct Staked addresses with positive stakedBalancestaking_events + eth_callnightlypending: Scheduled for Day 2 of the build plan (§9).
Staker USDC yieldtrailing 24 h Σ Distributed.amount × 365 / totalStaked, as USDC per 1M PAPER per yearstaking_events + eth_calltrailing 24 hlive
Implied PAPER valueannualised staker USDC / totalStaked / discount rate, at 20%, 50%, 100%derivedtrailing 24 hlive
Fee split checkcumulative staker fees vs dev fees, expected 1:1PositionsClosed, Liquidatedsince launchlive
Redemption probePaperTokenomics.quoteRedemption(1e18)
Undocumented path. Currently reverts with selector 0x32aa90b0.
eth_calllivelive
Staker income, overflow vs fee shareper UTC day: Σ Distributed.amount; overflow = Σ StakerLpExcessDistributed.amount; fee share = Σ StakerFeesClaimed.amount
Distributed is the push to PaperStaking; a day's fee share and overflow sum to it within the hour they were pushed.
hourly rollupdailylive
Staker takeΣ staker USDC ÷ Σ notional opened × 10,000, per UTC day and trailing 24 hhourly rollupdailylive

Operations

MetricFormulaSourceGrainStatus
Relayer batchescount of BatchExecuted in blocks whose timestamp is within the last 60 s of headeth_getLogs + block headerslive, 5 slive
Keepersliquidations per block, blocks from bust crossing to Liquidated, harvest callspositions + candlesrangelive
Protocol changesInstrumentAdded, MarketOiCapsUpdated, ERC1967 Upgraded; implementation slot polled hourlyadmin_events + eth_getStorageAtper ingestlive

Valuation inputs

MetricFormulaSourceGrainStatus
Tail minted so far12B × H / (S + H)derived from tailProgressUsd()livelive
Flat-region minted (F)totalSupply − tail minted; cross-checked by Σ paper where trackedLpBefore < $2Meth_call + positionslivelive
Curve ceiling (conditional)F + 100 × S = F + 12B
Conditional: F grows again if trackedLp drops below $2M.
derivedlivelive
Mint cost now1 / r(H)derivedlivelive
Net house PnLΣ lpGain − Σ lpLoss per period (gross losses minus wins paid)positions tablehourlylive
Valuation calculator12-month staker income = daily volume × take × 365; per PAPER = income × multiple ÷ totalStaked; FDV on the conditional ceiling
Model, not a price. Measured defaults are the trailing 24 h.
hourly rollup + eth_call; user inputslivelive

Unconfirmed fields and the unnamed event

  • PositionOpened: debtFunded name inferred (false on all samples)
  • PositionClosed: debtFunded name inferred
  • PositionsClosed: marginReturned, newBalance names inferred
  • Liquidated: debtFunded name inferred
  • Harvested: remaining name inferred
  • StakerFeesClaimed: field names inferred
  • StakerLpExcessDistributed: field 1 = amount per spec; fields 2,3 names inferred (2 == 1 and 3 == 0 on samples)
  • DevFeesClaimed: field names inferred
  • MarketOiCapsUpdated: cap names inferred
  • Unstaked: found 15 Oct: topic0 0x0f5bb821… on PaperStaking hashes to this signature; not in spec v2
  • BatchExecuted: word 4 unnamed
  • 0x620c26bf… on PaperTokenomics fires once per close group (one per user per batch, after all of that group’s PositionClosed events). Words: lpLoss, lpGain, trackedLpBefore, trackedLpAfter, tailDelta, paperMinted. PAPER is allocated to the group’s positions in proportion to each position’s loss (−pnlAfterImpact − fee).
  • On winning closes, trackedLpBefore equals trackedLpAfter in the event; the win has already been deducted when the event is emitted.
  • 0x0bb3f42f… on Exchange: two words, no indexed fields, name not recovered. Not used.

Decisions log

# Decisions

Spec items that were ambiguous but did not change the data model. Each was decided here and the build continued (kickoff rule 9).

D-001 · ABI source. The companion `papertrade-events.json` was not supplied. `abi/papertrade-events.json` was rebuilt from the signatures in SPEC §3. Every event's keccak topic0 was matched against logs on chain, and every indexed and data word count was checked against a live sample (`scripts/recon/build-abi.mts`, `scripts/recon/idx.mts`). No signature was invented. Field names the spec does not give are marked "inferred" in the file.

D-002 · Unstake event. The spec says no unstake event exists. Topic0 `0x0f5bb821…` on PaperStaking hashes to `Unstaked(address,uint256)`, so it is indexed as `unstaked`.

D-003 · The close mint event is per group, not per position. The unnamed `0x620c26bf…` event fires once per user per close batch, after that group's PositionClosed events. Its lpGain equals Σ(−pnlAfterImpact − fee) over the group's losing closes, and its lpLoss equals Σ pnlAfterImpact over the group's wins. Each position stores its own lp_gain and lp_loss, computed from PositionClosed. The group's paperMinted and tailDelta are split across positions by loss share. The backfill found 3 groups out of 473,308 where the sums disagree by more than $0.0001, all at launch, and 0 unmatched groups.

D-004 · Storage. USD and PAPER amounts are stored as float8 decoded from 1e18 integers, and wallets are interned to int4 ids, to keep inside Neon's free 0.5 GB. Exact integer checks (the PnL formula, supply) run against chain in `scripts/qa.ts`, not against the DB.

D-005 · Timestamps. The backfill stores exact timestamps every 300 blocks (`blocks`) and interpolates linearly in between; HyperEVM runs at about 1.015 blocks/s, so the error is a few seconds at most. Live catch-up uses exact block timestamps.

D-006 · Topics not indexed on Day 1: CallExecuted, NonceUsed, PaperToken Transfer, PositionsClosed, SweepRequested, StakingRewardCredited, BatchExecuted. None feeds a Day 1 panel. The top strip's relayer count reads BatchExecuted live from chain. The fee split check needs PositionsClosed and is marked pending.

D-007 · Snapshot cadence. Every 300 blocks (about 5 minutes) instead of the spec's 500, so the "cap pin ratio" means what §4 says it means (share of 5-minute snapshots).

D-008 · Vercel cron. The project is on the Hobby plan, which allows only daily crons, so a one-minute cron is not available. Live ingest has three parts: (a) every API request that reads the DB schedules a catch-up through `after()` when the cursor is more than 8 s old, guarded by a 55 s lease in the `cursor` table; (b) `/api/catchup` protected by `CRON_SECRET`, on a daily Vercel cron and callable from any external minute scheduler; (c) the Alchemy Notify webhook on Day 2. On the Pro plan, set the cron in `vercel.json` to `* * * * *`.

D-009 · Bust price. Fitted per side as |bust − entry| / entry = a/lev − b over all liquidations (73,709 at QA): long a = 1.00043, b = 4.785 bps, R² 0.9999993 (43,266 rows); short a = 0.99945, b = 4.782 bps, R² 0.9999972 (30,443 rows). The live fit is recomputed every 10 minutes and shown on the Ladder page.

D-010 · Reconciliation deltas against the spec's §1 table. Archive reads at block 48,549,415 reproduce treasury $61.45M, balances $44.98M, locked margin $11.65M, LP $4.82M, tail $154.35M, supply 7.408B and staked 7.352B. Differences:
- nextPositionId − 1 = 662,267, against the spec's 662,279.
- Accrued fees not yet pushed read staker $81 and dev $73, against the spec's $95.4k and $87.4k. These accumulators are pushed often, so the spec's read was probably taken at a different moment.
- Queue: 3 Enqueued events totalling $22.87 at 1e18 scaling, against the spec's "$22.9k". All other amounts on this event family are consistent with 1e18 scaling.
- §5.1 "stakers' cumulative sweep $150M+": Σ StakerLpExcessDistributed since launch is $37.9M. The $154M figure is the tail high-water mark (gross losses past $2M), not the sweep. The Loop shows $37.9M.
- §1 "Treasury … down from $137.9M pre-launch": treasury() was $0 at the block before the first deposit (47,920,889). The waterfall reconciles Σ Swept − Σ CoreWithdrawal to Δ treasury with a residual of −$101 (0.0002%).

D-011 · Loss inflow follows §4: Σ lpGain + Σ liquidated margin. lpGain on closes is already net of the 2% fee while the liquidation term is gross; this is stated on the methodology page.

D-012 · OI caps. MarketOiCapsUpdated fires about 90 times per 2,000 blocks, so the caps are dynamic. Their units are not confirmed (raw ÷ 1e18 gives about 2,289 for BTC long), so "OI vs caps" stays pending until the units are matched to open notional.

D-013 · Next.js 15 is kept as the spec asks. `npm audit` flags the PostCSS bundled inside Next for build-time CSS stringify and source-map issues. The app only processes its own CSS, so this is not reachable at runtime. Next 16 fixes it and is a later upgrade.

D-014 · Local development without DATABASE_URL uses an embedded Postgres (PGlite socket server on port 5433, `.localdb/`). Production uses Neon through the Vercel Marketplace.

D-015 · Distributed word order. §4 says "Σ Distributed.amount" without naming the word. On chain, word 2 equals StakerFeesClaimed.amount + StakerLpExcessDistributed.amount in the same tx (checked on tx 0x5c12f925…: 4,772.90 + 145,066.0 = 149,838.9). Word 1 tracks rewardReserve after the push. Word 2 is therefore the USDC amount. Lifetime: $40.89M = $37.90M LP sweep + $2.98M fees.

D-016 · Struct layout of Exchange.positions(uint256), confirmed on 100 random ids at a pinned block: [owner, instrumentId, entryPrice, margin 1e18, leverage, openTimestamp, isLong, unknown, isOpen]. Word 7 matches isLong in only 52 of 100, so it is something else; not used.

D-017 · Lint. `@typescript-eslint/no-explicit-any` is off. JSON-RPC payloads and decoded logs are untyped at the boundary, and `tsc --strict` still runs on every build. `scripts/` is excluded from the Next type-check and run with tsx.

D-018 · Live-edge reconciliation (OPEN ISSUE). Reconciliation is exact (margin Δ $0.00, supply Δ 0.16 PAPER, waterfall $0.00) for any block 200 or more behind the cursor. Within the last ~200 blocks after a catch-up, sums disagree even though every open and close id is present, and the gap heals on later passes. The working hypothesis is a lagging RPC node or partially indexed recent blocks. Mitigation for now: catch-up stays 20 blocks behind head and re-scans the last 300 blocks on every pass. QA should pin at least 200 blocks behind the cursor (QA_LAG=200) until the root cause is found.

D-019 · Hourly rollup and insight cache (15 Oct, depth pass). Request handlers never scan raw events: `hourly` (one row per UTC hour, 40 measures) is materialised by `refreshHourly`, called from the catch-up for the hours it touched; `kv` holds the heavy aggregates (concentration, survival, cohorts, fee split, flows) as JSON, refreshed by the catch-up when older than 5 minutes. Cold computation is about 20 s; serving is one row read.

D-020 · No `Upgraded` events. None of the five proxies has emitted ERC1967 `Upgraded(address)` since deployment, so the protocol-changes feed shows InstrumentAdded only. Upgrade detection relies on polling the implementation slot and diffing against the launch-block value (parameters panel).

D-021 · Time-series charts start at launch. Pre-launch hours (the $137.9M of deposits between 6 and 10 Oct) are excluded from every hourly chart so the axis is not dominated by one bar; lifetime totals that need them (waterfall, net flow since first deposit) read the full `flows` table.

D-022 · `Distributed` on PaperStaking: word 2 is the USDC amount (see D-015). Hourly `staker_usdc` sums it; the fee share vs LP sweep split in the staker chart uses `StakerFeesClaimed` and `StakerLpExcessDistributed` from the same hours.

D-023 · Liquidation map (15 Oct). The Ladder hero is a time × price map: every open position is a wall at its fitted bust price from the block it opened to now (width and opacity by notional), confirmed liquidations are dots at (close time, liquidation price), the price path is Hyperliquid 1-minute closes joined to the live BBO mid. A depth profile on the same price axis (2 bp buckets, longs left, shorts right) replaces the earlier stand-alone ladder, and the top eight buckets are labelled. Default view: ±1% of mid, 6 h, notional ≥ $100k; the "$10k+" chip is the floor the liquidation feed is capped at (8,000 rows). The §4 bucket scheme (1 bp near mid, 5 bp, 25 bp) is kept in the CSV/table view; on a linear price axis uniform 2 bp buckets draw more honestly.

D-024 · 26 Oct, pre-launch pass. The indexer had fallen 690k blocks behind because the request-triggered catch-up moved 6,000 blocks per page view and the Hobby cron runs once a day; it now moves 30,000 blocks per pass (routes that trigger it declare maxDuration 60). The gap was closed with the backfill script. Neon's free project limit was hit at 468 MB; the installation moved to the Launch plan (usage-based, $0.35 per GB-month storage). Two recon-only indexes on `positions` were dropped (open_block, (close_type, close_block)).

D-025 · Local Node connects to Neon only with `--no-network-family-autoselection`: Node 24's happy-eyeballs aborts the ~430 ms IPv4 connect. Scripts and the local dev server set NODE_OPTIONS accordingly; Vercel is unaffected.

D-026 · Upsert ordering. Concurrent backfill windows deadlocked on `wallets` and `positions`; every chunk is now sorted (addresses, then position ids) so transactions take row locks in one order. Concurrency 2.

D-027 · HyperCore preview. Alchemy's docs mark the market-data reads (candles, asset contexts, mids) "documented but not yet callable"; the HyperCore JSON-RPC host returns 401 for this key. Candles and 24h change stay on Hyperliquid's public API, labelled. The `/info` subset on the EVM host (spotClearinghouseState, clearinghouseState) keeps working.

D-028 · Revenue page. Adds the narrative layer: staker income per UTC day split into fee share (StakerFeesClaimed) and overflow (StakerLpExcessDistributed), take in bp of volume, the live overflow regime, the top-25 stakers' trading PnL vs staking rewards (live stakedBalance and pendingReward via Multicall3), cost per PAPER by first-trade cohort, OI history by side from the hourly rollup, and a valuation calculator with measured defaults. The reference price ($0.0263, Paragon's 19 Oct settlement) is a manual input and says so.

D-029 · Performance after the gap (2.1M positions). `positions` gained `open_ts` and `close_ts` indexes; trailing-window and recent-liquidation queries use them. Lifetime totals read the hourly rollup instead of scanning positions. Launch-block parameter reads are cached in `kv` for a day. The heavy aggregates are split into six `kv` keys (insightsA/B/C, flowsInsights, house, cohortCost) and the catch-up refreshes the stalest one per pass, so no single pass approaches the 60 s function limit.

D-030 · 61 close-mint events (150k PAPER in total, blocks 49.19M–49.56M) had no PositionClosed from the same user in the same transaction; they sit in `close_mints_unmatched` and count toward supply reconciliation (residual 99 PAPER, 0.000001%). Not yet investigated; most likely closes executed through a different path than the relayer batch.

D-031 · QA at block 49,562,444 (26 Oct): waterfall residual $0.00; Σ mints vs totalSupply 99.31 PAPER; open set Σ margin equals totalLockedMargin to $0.00 over 1,333 positions; 100/100 random positions match `positions(id)`; losses formula exact in wei 525/525; fee 2% 524/525 losses (one rounding), 463/463 wins; ladder next-hour precision 70.5%, recall 100%.

D-032 · Cost per PAPER is shown as net trading loss (losses minus wins) ÷ PAPER minted, which is what a wallet actually paid in cash; gross losses ÷ PAPER (what minted) is in the CSV. The net figure reproduces the 22 Oct thread's $0.0064 for the top 10 (dashboard: $0.0065).

D-033 · Silent upgrade on 21 Oct. The Exchange and PaperTokenomics implementations changed in block 49,169,385 (21 Oct 22:00:02 UTC), two days after the non-transferability post. No `Upgraded` event was emitted; the implementation-slot poll (parameters panel) caught it and the block was found by bisecting `eth_getStorageAt`. Checked after the upgrade: close fee still 2.000% of loss and of pnlAfterImpact; realised mint rate 9.81 PAPER/$ equals r(H) = 100 × (120M / (120M + 263M))², so the curve parameters and formula are unchanged. Two things did change: (a) 61 close-mint events since block 49,190,341 have no PositionClosed in the same transaction, carry round `lpGain` amounts ($500, $1,000), tailDelta 0 and a trackedLp increase equal to the amount, consistent with a direct "pay USDC, mint PAPER" path (150k PAPER so far; not yet confirmed from traces); (b) the mean pnlAfterImpact / pnlAfterDeadband ratio on winning closes fell from 0.553 to 0.473, which may be a heavier impact haircut or a different mix of moves; shown as observed, not explained.

D-034 · Candle source switched to settlement prints (26 Oct). The price path on the Ladder, the 24 h change in the strip and the MAE/MFE approximation now come from Papertrade's own prints: every PositionOpened entry and every PositionClosed / Liquidated exit, which are the exact HyperCore BBO prices the Exchange settled at (indexed from HyperEVM logs via Alchemy). Checked against Hyperliquid's public 1-minute closes: 1,434 of 1,440 minutes covered, mean |diff| 0.28 bp. Hyperliquid's public API is kept only as a fallback when a window has no prints, and the response carries its source. The print queries filter on the open_ts / close_ts indexes.

D-035 · QA at block 49,569,232 (26 Oct, after the prints switch): waterfall residual $0.00; Σ mints vs totalSupply 99.31 PAPER; open set equals totalLockedMargin to $0.00 over 1,379 positions; 100/100 positions match `positions(id)`; losses formula exact in wei 542/542; fee 2% 542/542 and 443/443; ladder next-hour precision 71.4%, recall 100%. MAE/MFE from prints on 1,199 sampled positions: wins close at a median MAE of 0 bp and MFE 6.9 bp; losses MAE 4.0 bp; liquidations MAE 6.6 bp with a median MFE of 2.8 bp, i.e. most liquidated positions had a small profitable exit they did not take.

D-036 · Rebrand to PAPERNOMICS (27 Oct). paperscope.xyz and papertrail.xyz were both taken by the time of launch; papernomics.xyz was free ($1.99 first year, $13/year after) and fits the Revenue angle. The product, wordmark, page titles, CSV filenames and article brief use the new name; the Vercel project, repo folder and internal identifiers keep `paperscope`. The purchase itself had to be made by the author: Vercel's CLI refuses domain purchases from agents by policy.

Disclosure

Unofficial and unaffiliated with Papertrade. The contracts are unverified and upgradeable, so any upgrade can change the meaning of a field; PAPERNOMICS polls the implementation slots and flags changes. BTC and ETH candles and 24-hour changes are rebuilt from Papertrade's own settlement prints (every open, close and liquidation price, indexed through Alchemy); Hyperliquid's public API is used only as a fallback if that read fails. Price manipulation of the BBO is acknowledged in the protocol's own docs; any suspicious-close panel is a distribution, never an accusation. Nothing here is financial advice.