Executability
Independent measurement · v18 · corrected 2026-09-04

The price on screen
is not the price you get

A price oracle tells you what something is worth. This measurement tells you whether you can actually sell it. Three unrelated markets, one recurring gap: the number on the screen and the number you get when you press the button are further apart than they look.

Tokenized QQQ
$6.46
Selling $100 of QQQ on Robinhood Chain returns $6.46. At $100,000 it returns $30.
Prediction markets · one-sided
52.2%
Of 596 books checked: you can buy in, you cannot get out
Same screen, same asset class
3300×
SPY returns 99.7% on a $100,000 sell; QQQ returns 0.03%
Finding one · On-chain aggregators

Asking one aggregator can overstate the cost by an order of magnitude

Published slippage figures almost always come from a single aggregator. This measurement queries six at once: CoW, KyberSwap, ParaSwap, 0x, 1inch and LiFi. Same moment, same token, same notional size, taking the best result a buyer could actually get.

The gap is not a few basis points. It is several times over.

Ethereum · 2026-08-31 · sell side · median price impact relative to the $100 tier. "No quote" means the source explicitly declined to price that size. That is a measurement, not a failed call.
TokenSizeParaSwap onlyKyberSwap onlyBest of six
LDO$100,000−11.29%−4.22%−0.71%
LDO$1,000,000no quote−85.14%−8.51%
PENDLE$100,000no quote−6.61%−0.79%
PENDLE$1,000,000no quote−60.23%−49.12%
CRV$100,000−6.06%−2.38%−1.82%
MKR$100,000−3.99%−1.01%−1.01%
UNI$1,000,000−6.65%−1.94%−1.21%
AAVE$1,000,000−3.58%−2.38%−1.06%

The extreme case is LDO at $1M: KyberSwap alone reports −85%, best-of-six is −8.5%. Anyone writing "on-chain liquidity is terrible" from a single source is off by a factor of ten.

And the best source changes with size

This is not a question of one aggregator being consistently better. Change the notional and the winner changes:

Best-quoting source at each size tier. LDO and PENDLE switch from 1inch to CoW at large sizes. CoW runs batch auctions with solver quotes, which is not strictly comparable to immediate AMM routing; that caveat travels with the data.
Token$100$1,000$10,000$100,000$1,000,000
WETH1inch1inch1inch1inch1inch
LINK1inch1inch1inch1inchKyberSwap
MKRKyberSwapKyberSwapKyberSwapKyberSwapKyberSwap
CRV1inch1inch1inch1inchKyberSwap
LDO1inch1inch1inchCoWCoW
PENDLE1inch1inch1inch1inchCoW

Solana: an exit ladder from a single source

Jupiter is the only quotable source on Solana, so the figures below are subject to the finding above and probably overstate the true cost. They are included because the magnitudes still say something.

SOL−0.13%
TRUMP−8.38%
PENGU−9.65%
WIF−26.71%
BONK−87.21%
PYTH−92.90%
JTO−93.41%
JUP−97.17%
Price impact on a $1,000,000 sell relative to the $100 tier · Jupiter · 2026-08-31 · ~102 samples per cell

A note on what these numbers mean. "−92.90%" means: at current on-chain liquidity, a sell order of that size would be filled down to that level. It does not mean "you will lose 92%". An order that size would most likely be refused rather than filled, and you can split it or route through a CEX. What the number tells you is the cost of dumping it in one go, and that at $1M these tokens have no executable market at all.

The $10,000 tier is closer to a real position: BONK −28.70%, PYTH −15.25%, WIF −3.40%, JTO −2.42%. All are CEX-listed tokens with meaningful daily volume.

Finding two · Tokenized stocks · corrected

The previous version of this section was wrong

Everything this section said in the version published on 4 September is void: that six of eight tokenized stocks could not be sold, that $100 of SPY returned $0.90, and that AAPL fell off a cliff above $1,000. None of it holds.

The cause was mine, not the market's. The scan that builds the pool table silently skipped block ranges that failed. It found about 55 pools where the chain has 25,122, and the handful it did find were mostly the shallow ones. I measured those and reported the result as a property of the asset.

What the earlier version published, against a re-measurement of the same thing. These figures are shown only so the size of the error is visible without going back to the superseded page.
ClaimPublished (v17)Corrected
SPY, sell $1000.90% · PUBLISHED IN ERROR99.93%
AAPL, sell $10,0002.82% · PUBLISHED IN ERROR99.85%
Tokens that cannot be soldsix of eight · PUBLISHED IN ERRORone of nine

What changed in the method

  • Complete pool table. The scan now aborts on any failed block range instead of skipping it. Of 25,122 initialised pools, 1,027 pair a stock token with USDG; 125 of those can fill $10,000. The eight that return the most are kept per token. Selection is reproducible: build_pool_table.py.
  • Same-pool round trip. Buy in one pool, sell the whole position back through that same pool. The previous method took the best buy pool and the best sell pool separately and derived a rate between them; that rate belongs to no actual pool and produced recovery figures above 100%, which cannot persist. A closed loop needs no rate assumption and must come in under 100%.
  • Nine tokens, USDG-quoted pools only. AMC was absent from the earlier table because its pools were among those the broken scan missed.

Corrected measurements

Twelve rounds over 5.1 hours, every 30 minutes, each pinned to a single block. Every size filled in every round; nothing was unquotable. Where a figure moves between rounds, the p10–p90 range is given underneath.

Robinhood Chain (chainId 4663) · 12 rounds, one every 30 minutes · 2026-09-04 07:30 → 12:42 UTC · blocks 54,088,399 → 54,270,401. Same-pool round trip: buy with USDG, sell the whole position back through the same pool. Median share of notional recovered, with the p10–p90 range. No round failed to fill at any size, so the "could not fill" count is zero throughout and is omitted.
Token$100$1,000$10,000$100,000
SPY99.93%99.93%99.91%99.71%
AAPL99.93%99.92%99.85%99.06%
GOOGL99.99%99.95%99.53%97.97%
NVDA99.99%99.89%99.48%96.50%
TSLA99.89%99.77%99.07%96.75%
RDDT99.32%99.32%99.24%93.12%
90.1–96.6
AMC99.75%99.62%97.08%
86.1–99.0
74.55%
28.5–83.6
GME99.49%99.37%97.97%
36.9–98.6
17.33%
3.7–22.5
QQQ6.46%1.83%0.26%0.03%

QQQ is the one token that cannot be sold at any size. $100 returns $6.46 and $100,000 returns $30. It is not a size effect and not a moment: all twelve rounds agree to within a tenth of a percent. Every other token on this chain returns at least 93% of a $100,000 sell.

GME and AMC are where size still bites, and they are the two tickers retail sentiment concentrates in. Both are fine up to $1,000. GME at $100,000 returns 17% and never exceeded 23% in any round; AMC at the same size ranges from 28% to 84% depending on when you ask. The medians alone would hide that: the reason both carry a range is that a single number would misrepresent them.

One observation, not yet a finding. Both GME and AMC improved markedly during the window — GME at $10,000 went from about 30% to 98% and stayed there, while AMC at $100,000 climbed steadily from 18% to 83% without reversing. The two shapes are different enough that they are unlikely to share a cause, and neither is explained by anything measured here. This is a single day's observation. Whether it repeats is not something one session can establish, and it is recorded here as an open question rather than a result.

Reproducibility

You do not have to trust me. Run it yourself.

Every figure above comes from an on-chain call, and an on-chain call at a given block height is deterministic: the same inputs produce the same output for anyone, at any time, in any language.

So each round of measurement emits a hash whose preimage contains only fields a third party can reproduce exactly:

Canonical preimage, rhdepth-v2. Integers are hashed as decimal strings: uint256 exceeds JavaScript's safe integer range, and passing them as numbers loses precision silently. Each round yields 36 canonical records (9 tokens × 4 sizes, one closed round trip each); the run makes many more calls than that, probing every candidate pool, but only the winning pool's figures enter the hash.
In the hashWhy
Block heightState anchor
poolIdIdentifies the pool
Input amount (raw integer)Call parameter
Midpoint amount (raw integer)Tokens received before selling back
Output amount (raw integer)Chain return value, deterministic
StatusFilled / insufficient liquidity
Timestamps, network latency✗ excluded: nobody else can reproduce them
Slippage, recovery and other derived floats✗ excluded: float serialisation differs across languages

Verified in practice: replaying every round trip independently for the first v2 round (block 54,088,399) reproduces the recorded hash byte for byte.

Run it yourself

This page ships with the raw data and the verification script, with no third-party dependencies (code/evm.py is a from-scratch implementation needing only Python 3 and curl):

Every figure on this page corresponds to a snapshot of 12 rounds ending at block 54,270,401, published as data/snapshot-v18-12r/. That directory does not change after publication, so its checksums will always match. Collection continues in the live directory data/2026-09-04/, which grows past what this text describes.

You need an archive node for Robinhood Chain (historical eth_call; public endpoints typically retain only the last ~128 blocks of state):

export RHCHAIN_RPC="https://<archive endpoint>" python3 code/verify.py 54088399

What this gives you is verifiability, not decentralization. The right to publish these hashes is centralised, and that is a fact. But it does not ask you to trust the publisher: replay the block, and it either matches or it does not. The thing being trusted is arithmetic, not me.

Finding three · Prediction markets

The same gap, in an unrelated market

Every prediction market shows a price on its interface. Pull the actual order book and few of them can be traded.

More interesting than an outright empty book is the one-sided market: real depth on the ask, dozens of levels absorbing tens of thousands of dollars, while every bid sits at a dust price of 0.01. You can buy in at 0.99; when you want out, 0.01 is the only bid. Plenty of levels, all at prices that cannot catch you.

9.4%
Tradeable
56
52.2%
One-sided
311
21.3%
Borderline
127
17.1%
Empty quote
102
2026-09-03 07:10 UTC · Polymarket + Kalshi + Pascal, 38,775 active markets · eight whole-word keyword searches · only the highest-volume markets in each set were checked. Criteria for "tradeable": spread ≤ 0.10, ≥ 3 ask levels, book absorbs ≥ $200, and best bid > 0.02.
KeywordMatchedNo 24h volumeCheckedTradeableOne-sidedBorderlineEmpty
bitcoin23854780471516
ethereum1886266046416
election1,15490010888677
fed82657514311416
trump5101071144277112
nba696559213323
china2492421435
gpt10026727271127
Total2,3651,28859656311127102

Two details stand out.

For bitcoin and ethereum, the tradeable count is zero. Across 144 checked books, not one had both sides standing; they are almost all one-sided or empty. Meanwhile nba has 21 of 59 tradeable and fed has 14 of 75. A busier topic does not mean a more tradeable one.

54.5% of matched markets had no trades in 24 hours. Searching election returns 1,154 markets, 900 of them silent. On the interface they look identical to the active ones.

Method

Our instruments lied to us nine times

This section does not usually appear in a report like this. It is here because it explains something more important: why almost nobody does independent executability measurement.

Not because it is hard, but because instruments lie quietly. Nine errors over six days, each producing a precise number that looked like an insight. Seven were caught before anything was published. Two were not: they are marked below, and the section they corrupted is corrected above. A process that genuinely self-corrects will eventually catch something late — what matters is which side of publication each one landed on, so that is stated.

01
Depth overstated by a factor of a million
Limitless returns order-book sizes as 6-decimal fixed point. The trade path divided by 1e6; the book path did not. So "average price to fill $10,000" always equalled the top-of-book price and the whole ladder was flat. 99.9% of rows looked like this, and not one of them raised an error.
02
"Kalshi is 100% empty quotes"
Kalshi returns top-of-book with its market list; depth requires one call per market with no batch endpoint. So we only stored the top level and n_ask was always 1. Apply a "≥ 3 ask levels" test and it fails 100% by construction. That was an artefact of our collection, not a property of their market. Publishing that about a regulated exchange once would be enough to destroy the "independent measurement" claim.
03
74% of the market list had already expired
The Polymarket enumeration passed active=true&closed=false, and those two flags do not exclude expired markets. 74% of the list was dead, the 20,000-market budget was spent on them, and the cursor never reached the currently active set. The symptom was "searching bitcoin returns 3 results". It also contaminated the statistics: dead markets have no book, so they were classified as empty quotes and dragged the tradeable share down.
04
A market with no bids classified as tradeable
With no bids, bid1 = 0, so spread = ask − 0 = ask. Whenever the ask was cheap (say 0.05) the spread came in under 0.10 and passed the test, for a market with not a single bid in it. The output before the fix read "spread 1.000 · ✅ tradeable", which is self-contradictory. Correcting it cut that category by more than half.
05
An alert that fired every day for nothing
The health check kept its list of "slow sources" hardcoded. After one source's interval changed from 600s to 1800s the list was not updated, so it appeared once every three rounds while still being counted as "should be present every round". The multi-source quorum dropped from 89% to 43% and the alert fired daily with nothing actually wrong underneath. The same class of error — one fact written down in two places, then drifting apart — occurred four times in three days.
06
"On-chain tokenized stock pools are basically empty" — this was wrong
The first scan concluded that every pool had a ~92% round-trip loss, and that nearly went into the report. The cause: this chain produces a block every 100 milliseconds, so its 53.41 million blocks are about 62 days, and we had only scanned the most recent 4 million — about 4.6 days. That window contained nothing but freshly minted launchpad pools; the real stock-token pools were created in the chain's first days, entirely outside the scan. A full-chain rescan reversed the conclusion: NVDA and TSLA are genuinely tradeable. "The last N blocks" means a completely different span on different chains, and any block-windowed analysis has to convert to time first.
07
The 64 rows in a round came from 64 different moments
The collector recorded one block number at the start of a round, then made every call against "latest". A round takes 60–85 seconds and the chain advances roughly 700 blocks in that time. Two things break: the recorded block does not match the state the data came from, so nobody can ever verify it; and the rows within a round do not match each other, which breaks the premise of a same-moment cross-section. This one was caught by the verification script — it failed on its first run — and would otherwise have persisted silently. Fixed by pinning the whole round to one block height, at the cost of requiring an archive node.
08
The pool table was 0.2% complete — found after publication
The scan that builds the pool table skipped block ranges that failed instead of stopping. It returned 55 pools where the chain has 25,122, and the ones it happened to catch were mostly shallow. Every tokenized-stock figure in the previous version was measured against those pools: SPY's real round trip at $100 is 99.93%, not 0.90%, and the AAPL "size cliff" does not exist. Pool count is not a proxy for depth either — AMC has among the most pools of any token and among the fewest that can fill $10,000. Any pool table built before the scan was made fail-loud has to be discarded, not patched.
09
A metric that could exceed 100% — found after publication
The old measurement took the best buy pool and the best sell pool separately, then derived a rate between them to size the sell. That rate belongs to no actual pool. It produced round-trip recoveries above 100% — buy and immediately sell back at a profit — which cannot persist for more than a few seconds in any real market. The replacement closes the loop inside one pool, needs no rate assumption, and cannot exceed 100% by construction: if it ever does, that is a bug announcing itself.

And one obstacle that is not a bug

Measuring at all can get you rate-limited. ParaSwap (now Velora) allows roughly 5,000 calls a day on the free tier, counted per egress IP rather than per key, and not separated by domain. We sent 5,622 in a day and got a solid 11 hours of 429s starting 23:31 UTC on 31 August, until the rolling window cleared.

0x disabled our key entirely on 4 September, after two notices about the quote-to-fill ratio. We stopped calling them rather than retrying, and 0x is excluded from the comparison until that is resolved.

But the barrier is not uniform, and that turns out to be the more useful finding. Asked the same question, 1inch replied that quote-only use is fine, that they have no quote-to-fill rule, and that they had never throttled a single one of our calls — with the condition that the free tier is for non-commercial use, which this is. So "independent measurement is impossible" is not an industry fact. It is the result of asking each provider, one at a time, and getting different answers. The barrier is not the code and not a universal policy. It is that almost nobody asks.

Admitting what is missing is more credible than pretending to be complete. Most of these errors surfaced only because figures were checked against the raw data; two of them survived to publication and were caught only when a re-run forced a correction. "Only about 10% of Polymarket markets are tradeable" was written into external copy and then withdrawn; "on-chain tokenized stock pools are all empty" had an entire section drafted before it was overturned. This is the reason to write a verification tool: the first errors it catches are your own.

Limits

What this data cannot be used for

  • The time depth is days, not months. On-chain data starts 2026-08-30, prediction markets 08-29. Every conclusion is a cross-section and supports no time-series claim. "Who is better in the long run" needs weeks of samples at minimum.
  • Solana has only one quote source. Jupiter is the only one available, so that ladder has no cross-source comparison, and by the first finding it probably overstates the true cost.
  • Prediction markets were sampled by keyword, not surveyed. Eight keywords, and only the highest-volume markets in each set were checked. Spot-checking 50 from the tail found 45 with no retrievable order book at all — but it is still a sample.
  • Limitless is missing from this pull. Its market-list endpoint returned empty at sampling time and it is excluded from the totals. That happened three times in three days; treat its availability as uncertain.
  • Kalshi only supports a degraded verdict. It publishes top-of-book only, so its results are marked "depth unknown", and the bias is toward overstating the tradeable share, not understating it.
  • "Cannot be executed" is not "you will lose X%". A refused quote means the size cannot be filled at current liquidity. It is not a cost you would actually pay.
  • Tokenized stocks cover USDG-quoted pools only. Some tokens also have ETH/WETH pools, excluded here; a token could be deeper against a different quote asset. TSLA is known to have additional depth in an ETH pool.
  • The pool table has no external cross-check. It is internally consistent — the scan aborts rather than skipping a failed range, and this run had none — but nothing independent confirms it is complete. DexScreener counts uninitialised pools in its liquidity figures and is not used as a reference; the block explorer's API is behind anti-bot protection.
  • 0x is absent. Its key was disabled on 4 September, so the aggregator comparison in the first section reflects the six sources available on 31 August, not today's five.
  • Only 5.1 hours and 12 rounds. The "depth is stable" conclusion covers a short window and does not extrapolate across days, weekends or earnings. Behaviour while US markets are closed has not been measured.
  • Quotes are not fills. Every figure comes from a simulated Quoter call, not an executed trade. Real execution is affected by MEV, slippage protection and gas, and is generally worse rather than better.
  • The prediction-market figures are a 2026-09-03 snapshot. Event markets expire; the batch of 49 earnings markets referenced there has since ended with the earnings season, so a re-check will not return the same match counts.