Skip to content
SquvaTerminal

Methodology · version 2026.10.1

How the numbers are made.

Every figure in a report is computed by deterministic code from public chain data pinned to one block. This page states the formulas, the classification rules and what each module cannot know. A report carries the methodology version it was built with; changing a rule changes the version.

What is covered

Scope and sources

SquvaTerminal scans tokens on Robinhood Chain (chain id 4663) that were launched through the Pons V2 factory. A token is accepted only if the factory's own record says it exists, and the token, its bonding curve and the factory all point at each other. Everything else is answered with “unsupported” and the reason.

  • Two venues are decoded: the launch's bonding curve and, after graduation, the single Uniswap v4 pool the factory creates for it (pool key fixed by the launch, hooks = the Pons meme hook).
  • Contract addresses come from the protocol's documentation, the factory's on-chain pointers and Uniswap's deployment list. pnpm verify:config re-checks each one against the chain and Sourcify; the result is on the status page.
  • The endpoint's eth_chainId is confirmed before anything is read. An endpoint that reports another chain is never used, and no other network is substituted.
  • Token names, symbols, descriptions and links are written by whoever launched the token. They are shown as plain text, never executed, never fetched.

One block

The snapshot

A report describes the chain at one block. The scanner first brings every log stream up to head − FINALITY_BLOCKS, then pins that block, stores its hash and timestamp, and immediately reads the state the report needs at exactly that block:totalSupply(), the factory's launch record, the curve reserves or the pool's price, and balanceOf() for the largest holders.

  • The public node keeps about 3,000 blocks of state. That is why state is read right after pinning, and why a simulation requested later runs at a newer block and says so.
  • Each report records how final its block was when pinned (sequencer-confirmed, safe, or finalized on Ethereum). The Overview re-checks the stored block hash against the chain; a different hash means the snapshot was reorganised.
  • Block timestamps come from block headers. Logs on this chain carry no usable timestamp, and none is interpolated.
  • Reloading a report shows the stored snapshot. It never re-reads the chain to “refresh” numbers in place.

Getting the data

Indexing

For each token five log streams are read from its launch block: the token's Transfer events, every event of its bonding curve, the factory's events for the token, and (after graduation) the pool's Swap events and the hook's HookFeeCollected events.

  • Windows. eth_getLogs is walked in block windows of at most 10,000,000 blocks. A “too many logs” answer (more than 10,000) or a provider timeout halves the window; quiet windows let it grow back.
  • Checkpoints. Each window's rows and its checkpoint are written in one database transaction. A crash or restart resumes at the next unwritten block.
  • Idempotent writes. Rows are keyed by chain, token, block and log index. Re-ingesting a range overwrites; it cannot duplicate.
  • Reorganisations. Every checkpoint stores the hash of its last block. If the chain no longer has that hash, the stream rolls back to the newest block whose stored hash still matches, deletes what came after (including derived trades) and re-indexes.
  • Bounded work. A stream stops at a configured number of logs. A capped stream makes the report partial; an incomplete holder set is never presented as complete.
  • Rate limits. Requests pass through a token bucket and are retried with backoff on 429, timeouts and server errors.

Agent 01

Holder Map

Balances are rebuilt by replaying every Transfer since the launch block. The zero address is the counterparty of supply changes, not a holder.

balance(a)  = Σ value of Transfer(to = a) − Σ value of Transfer(from = a)      up to the snapshot block
supply      = Σ Transfer(from = 0x0) − Σ Transfer(to = 0x0)
check 1     : supply = totalSupply() at the snapshot block
check 2     : balance(a) = balanceOf(a) at the snapshot block, for the 200 largest balances

A failed check, a negative rebuilt balance or a capped Transfer stream makes the module partial and is reported as a finding. Mismatches are shown, never smoothed over.

Classification rules

ClassRule and sourceConfidenceExcluded
Bonding curveThe curve address in the factory's launch record of this token.verifiedyes
Pool managerUniswap v4 PoolManager from Uniswap's deployment list and the factory's poolManager(). It holds the liquidity of every v4 pool.verifiedyes
Protocol contractPons locker, buyback vault, hook, factory, escrow, routers and Uniswap periphery, from the verified configuration.verifiedyes
Burn address0x…dEaD. By convention nobody holds its key; tokens there still count in totalSupply().conventionyes
Contracteth_getCode at the snapshot block returned code. The contract is not identified. A contract is not automatically a team wallet.observedno
Wallet (EIP-7702)Code is an EIP-7702 delegation designator: a key-controlled account.observedno
Walleteth_getCode returned no code.observedno
Not checkedOutside the 200 largest balances, or the endpoint could not serve the block.uncheckedno

Labels are added only from protocol events of the launch: the creator (factory record), wallets the creator exempted from the launch snipe tax (SnipeTaxExempted), and buyers who paid that tax (SnipeTaxCharged). An exemption shows that the creator named an address, not who controls it. Shared funding or timing is never treated as shared ownership.

Concentration

before(N)          = Σ top N balances of all addresses            / totalSupply
after(N)           = Σ top N balances of non-excluded addresses   / totalSupply
after-of-eligible  = Σ top N balances of non-excluded addresses   / Σ balances of non-excluded addresses
N ∈ { 1, 5, 10, 20, 50 }

Dust. A balance below 1 billionth of total supply is dust. Dust wallets count as holders and stay in every balance figure, but are reported in their own bucket rather than as wallets in profit or underwater.

Agent 02

Book Rebuilder

A Transfer alone never establishes a purchase or a sale. A wallet is credited with a trade only when a protocol swap event in the same transaction says quote changed hands and the wallet's own net token flow in that transaction accounts for the tokens.

Reading swaps

  • Bonding curve. CurveBuy.quoteIn is everything the buyer spent (price plus fee, creator tax and snipe tax): that is the cost. CurveSell.quoteOut is what the seller was paid after fee and tax: those are the proceeds.
  • Uniswap v4 pool. Swap gives the pool-level amounts; the HookFeeCollected that follows it gives the hook fee and creator tax and the asset they were charged in. Fees in the quote asset are added to a buyer's cost or taken off a seller's proceeds; fees in the token reduce the tokens a buyer receives.
  • The hook's own swaps (fee conversion, buyback) are protocol-internal and are never wallet trades.

Attributing a swap transaction

  • Mints, burns and sends to burn addresses are booked as their own legs.
  • The remaining net token flows are matched side by side: buy events against addresses that ended with more tokens, sell events against addresses that ended with fewer. Routers and other pass-through contracts net to zero and drop out, so a routed trade is counted once.
  • Flows equal the swapped tokens: curve events name their wallet and are used one by one when the flows agree exactly; otherwise a single counterparty takes the trade; a counterparty holding at least 95% takes the whole quote amount and the rest are side transfers; anything else is split pro rata by tokens.
  • One counterparty moved more than the swaps did: the swapped part is the trade, the excess arrived outside the decoded swap and has unknown cost.
  • Counterparties moved less than the swaps did (the rest went to protocol or burn addresses): they take the whole quote amount when they hold the primary share, else their pro-rata part.
  • No wallet's balance changed: the transaction is neutral and changes no position.
  • A side that cannot be matched leaves the transaction unattributed. Its token movements are booked as transfers and the transaction is counted and listed.

Lots

method            : FIFO; integer arithmetic in base units
buy               → new lot { qty, cost = quote paid incl. fees }
transfer in       → new lot { qty, cost = unknown }          (never zero)
sell(qty, P)      → consume oldest lots; per consumed slice s:
                      proceeds(s) = P · qty(s) / qty          (remainder to the last slice)
                      known-cost slice   → realised += proceeds(s) − cost(s)
                      unknown-cost slice → proceeds recorded, result unknown
transfer out/burn → consume oldest lots; nothing realised; the cost leaves and is not carried to the receiver
partial lot       : cost(taken) = floor(cost · taken / qty); the remainder stays in the lot
  • Transfers are transfers. Basis is never carried from one address to another: a transfer does not show that both addresses belong to one owner.
  • Gas is not part of cost or proceeds. Logs do not say who paid it, and it is not estimated.
  • Router fees outside the swap are not included. Some front ends keep a share of the ETH sent before swapping (about 1% in sampled transactions); that amount never reaches the venue, is not in its events, and so is not in the cost basis. A buyer who used such a router paid slightly more than the cost shown.
  • Every wallet's open lots must add up to its Transfer-derived balance; a mismatch is reported as an accounting anomaly.

Agent 03

Profit Lens

reference price P   = curve:  quoteReserve / tokenReserve      (getReserves() at the snapshot block)
                      pool :  from sqrtPriceX96                 (StateView.getSlot0 at the snapshot block)
realised (known)    = Σ proceeds of known-cost slices − Σ their cost
unrealised          = knownQty · P − remaining basis
wallet status       = profit | underwater | breakeven     only if the whole balance has a known basis
                      breakeven when |value − basis| ≤ 0.50% of basis
                      unknown otherwise (any unknown-cost quantity, or no reference price)
  • One currency. A Pons token trades against one pair asset on both venues, so cost, proceeds and value are all in that asset. Nothing is converted to dollars or to another asset: that would need a timestamped price for every trade.
  • Two distributions. By wallet count (denominator: non-excluded wallets with a position; dust and excluded addresses listed beside it) and by token balance (each open lot classified on its own; denominator: balance held by non-excluded addresses).
  • Reference is not exit. The reference price is the spot price for an infinitesimal trade. It values a position; it does not say the position can be sold there. The Exit Check measures that separately.
  • With no venue open at the snapshot block there is no reference price: unrealised P&L is unavailable, realised results are still stated.

Agent 04

Exit Check

A read-only simulation through eth_simulateV1 at the snapshot block, for the 3 largest non-excluded holders, at 1%, 25%, 100% of balance. Nothing is broadcast, no key is involved, and nobody is asked to approve or sign.

  • Curve route: token.approve(curve), then curve.sell(amount, 0, wallet).
  • Pool route: token.approve(Permit2), Permit2.approve(router), then one exact-input swap through Uniswap's Universal Router. Uniswap's V4Quoter is asked for the same sale and shown beside it.
  • Assumptions, disclosed with every result: the approvals are simulated; the minimum output is zero; validation is off, so gas affordability is checked separately against the wallet's native balance; gas is execution gas only.
reference value  = amount · P
proceeds         = quote that reached the wallet in the simulation
below reference  = 1 − proceeds / reference value          (price impact + fees + creator tax)
price impact     = 1 − gross quote out of the venue / reference value

Result classes

ExecutedThe simulated sale executed and paid out.
AllowanceThe sale reverted for lack of allowance. That is a missing approval, not a restriction on selling.
BalanceThe sale reverted because the wallet does not hold the amount at this block.
No routeNo supported venue accepts this sale at this block (the curve is closed or the pool does not exist yet).
LiquidityThe venue cannot pay out for this size: its liquidity is insufficient.
SlippageThe sale reverted on its minimum-output bound.
Payout refusedThe venue could not pay the quote asset to this address: it is a contract that does not accept native ETH. That is a property of the holding contract, not a restriction on selling the token.
Token restrictionThe token contract itself refused to move this balance. This is an observed restriction at this block.
Venue revertThe venue rejected the call for a reason unrelated to the token (invalid amount, deadline, arithmetic).
ProviderThe RPC provider could not run the simulation. Nothing is known about the sale.
UnclassifiedThe sale reverted with data this build cannot name. The raw revert data is shown; it is not classified as a restriction.
  • An allowance failure is not proof of a honeypot. A successful quote is not proof that a sale executes. One executed simulation does not guarantee future trading.
  • A revert the table cannot name is retested with a plain transfer of the same amount. Only if that also reverts is the result called a token restriction.
  • An executed simulation is never reported as “safe”.

Agent 05

Cross-Token Record

The universe is the set of tokens scanned on this instance, each at its latest report. A wallet's record is its positions in those reports, and the count of tokens is stated with every result: “history across N indexed Pons tokens”, never “every Pons token”.

  • A closed position enters the win and loss counts only if everything it held was bought and sold on supported venues, with no transfer in or out and no unknown basis. Every other closed position is listed as “result unknown” and excluded, visibly.
  • Realised results are grouped by pair asset. Amounts in different assets are never added together.
  • Why not the whole chain: the public endpoint accepts address-less log queries over at most 30,000 blocks, so a wallet's full token list cannot be read from it. On a wallet page, candidate tokens are read by your browser from the block explorer or pasted in, and the server verifies each against the factory before it can be scanned.

Agent 06

Evidence Desk

The Evidence Desk computes nothing new. It restates the other modules' outputs as findings, each with supporting observations, the method, the coverage, the uncertainty, a plain-language sentence, and the ids of the evidence items behind it: event logs with transaction hash and log index, state reads with contract and block, simulations, and coverage records.

  • Observation Read from the chain or computed directly from it.
  • Inferred pattern A pattern in the data. Consistent with an explanation, not proof of it.
  • Open question Something this report does not establish.

There is no safety score. Findings are specific: concentration, unknown-basis share, liquidity against position size, an observed sell restriction.

Optional AI summary. If the operator configured a language-model key, a summary can be generated from the finished findings. The model must cite finding or evidence ids; afterwards each paragraph is checked mechanically, and one that cites an id the report does not contain, or contains a number the findings do not contain, is discarded. The application works the same without a key.

Vocabulary

States

Module and scan states

  • Queued Waiting for its turn. Nothing has been read yet.
  • Running Working now. Progress figures come from the backend as it writes them.
  • Completed Finished with a complete result.
  • Partial Finished, but part of the result is missing or unresolved. The note says which part.
  • Unavailable Could not be produced for a stated reason (no venue, no data, missing dependency).
  • Failed Stopped on an error. The note carries the error.

Position states

  • In profit The whole balance has a known cost basis below its value at the reference price.
  • Underwater The whole balance has a known cost basis above its value at the reference price.
  • Breakeven Value at the reference price is within the breakeven band of the cost basis.
  • Unknown Some or all of the balance has no known acquisition cost, or no reference price exists.
  • Dust Balance below one billionth of supply. Counted as a holder, left out of the profit and loss wallet counts.
  • Closed No balance at the snapshot block.
  • Excluded A venue, protocol contract or burn address. Left out of holder distributions.

Every state is a glyph and a word as well as a tone, so nothing depends on telling cyan from pink.

Read this

Known limits

  • Trades on venues other than the Pons curve and the launch's Uniswap v4 pool are not decoded. Tokens that moved through them appear as transfers with unknown cost.
  • Cost basis is what reached the venue. Fees a router keeps outside the swap, and gas, are not part of it.
  • Addresses are not people. One owner can hold many addresses, and one address can pool many owners. Counts of wallets are counts of addresses.
  • The reference price is a spot price at one block. Markets on this chain move every hundred milliseconds.
  • Exit simulations cover the sampled wallets, one route, one block. A holder that is itself a contract can only sell if its own code does.
  • The cross-token universe is whatever has been scanned on this instance.
  • State older than a few thousand blocks cannot be re-read from the public endpoint, so a stored report cannot be re-verified against historical state later; its inputs are stored with it instead.
  • Storage is finite. An instance indexes a bounded number of logs per token and keeps a bounded number of tokens and reports; the limits in force are on the status page. A history beyond the per-token limit is reported as partial, and a link to a removed snapshot says so. Scanning the token again rebuilds it from the chain.
  • Nothing here is financial advice, and no result is a statement that a token is safe.