Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
a454497
feat(about): add Independence and disclosure section
Flotapponnier Jun 9, 2026
b4f3a83
feat(badge): add Share on X intent + Markdown copy on product badge c…
Flotapponnier Jun 9, 2026
1b716f9
fix(badge): emit per-chain badges when provider only leads on subset …
Flotapponnier Jun 9, 2026
f63b546
feat(badge): redesign with spinning 3d brand mark
Flotapponnier Jun 10, 2026
ce5175b
feat(seo): dedicated per-chain bench pages, drop duplicate ?chain= si…
Flotapponnier Jun 10, 2026
0bf20f2
feat(badge): exact chain x region cell rankings via rank_matrix_query
Flotapponnier Jun 10, 2026
0a58017
fix(specs): trim oracle-deviation + stablecoin-peg methodology under …
Flotapponnier Jun 10, 2026
100ca1b
fix(seo): fallback for unresolved placeholders + no-data copy on chai…
Flotapponnier Jun 10, 2026
3d3991f
feat(spec): require rank_matrix_query on region-dimensioned benches
Flotapponnier Jun 10, 2026
a01c3b3
Merge pull request #378 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
4a1637b
feat(seo): per-chain pages v2 for dimension benches + rpc-capabilitie…
Flotapponnier Jun 10, 2026
ac03d50
Merge pull request #379 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
930bb94
fix(build): render dimension chain pages on demand, prerender row pag…
Flotapponnier Jun 10, 2026
e29b215
Merge pull request #380 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
8aa4e20
fix(badge): faithful 3d masthead sphere with true 360 yaw spin
Flotapponnier Jun 10, 2026
3159413
Merge pull request #381 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
e907d90
fix(badge): dynamic width from title length, drop 32-char ellipsis
Flotapponnier Jun 10, 2026
46ffa62
Merge pull request #382 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
cd57e4d
fix(cache): bump bench cache keys for cellRanks + short-TTL scoped ba…
Flotapponnier Jun 10, 2026
8cda45e
fix(spec): quorum guard, sub-50% provider render no longer counts as …
Flotapponnier Jun 10, 2026
8d4410a
fix(snapshot): coverage ratchet guard + stash carry-over on write
Flotapponnier Jun 10, 2026
2d64232
Merge pull request #383 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
75f4b4b
feat(ledger): per-bench ledger column relabeling (ledger_columns)
Flotapponnier Jun 10, 2026
998498e
fix(data): harden cache layer per multi-agent review
Flotapponnier Jun 10, 2026
a8e53d4
Merge pull request #384 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
7e04114
fix(spec): restrict percentile retry to the unfiltered view
Flotapponnier Jun 10, 2026
d560799
Merge pull request #385 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
f42fdac
fix(prom): raise query concurrency cap 8 to 64, 8 starved large page …
Flotapponnier Jun 10, 2026
6287b60
Merge pull request #386 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
5c22012
feat(seo): brand name in homepage intro for entity recognition
Flotapponnier Jun 10, 2026
931a5f7
fix(build): raise static page generation timeout to 240s
Flotapponnier Jun 10, 2026
7a2821f
Merge pull request #387 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
5c019c1
feat(prom): read ocb:* recording rules on the 3 heaviest benches
Flotapponnier Jun 10, 2026
b5010c1
Merge pull request #388 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
79f69ac
feat(ledger): 24h/7d/30d timeframe toggle, drop redundant revenue tabs
Flotapponnier Jun 10, 2026
0e57577
Merge pull request #389 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
9309076
fix(perf): bench pages static again + honest post-migration formulas
Flotapponnier Jun 10, 2026
0063a12
Merge pull request #390 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
13bbb28
fix(specs): editorial truth pass across 12 benches
Flotapponnier Jun 10, 2026
3c81339
Merge pull request #391 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
92ded23
feat(hl-bench): 15 unidentified builders + users 7d/30d on timeframe …
Flotapponnier Jun 10, 2026
6db691b
Merge pull request #392 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
6cf7620
fix(ci): staging deploy timeout 15 to 30 min
Flotapponnier Jun 10, 2026
c12cf75
Merge pull request #393 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
e23ccad
feat(bench): hyperliquid hip3 deployer revenue leaderboard (bench 035)
Flotapponnier Jun 10, 2026
16f3409
Merge pull request #394 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 10, 2026
beba2d0
fix(build): render product + alternatives pages on demand, prerender …
Flotapponnier Jun 11, 2026
8c9d4d6
Merge pull request #395 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
7eb18e7
fix(snapshot): persist metricPanels so KV-served benches keep view ta…
Flotapponnier Jun 11, 2026
3d48177
Merge pull request #396 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
8487a2d
fix(build): product OG images on demand too, last prerender blocker
Flotapponnier Jun 11, 2026
8e71177
Merge pull request #397 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
1a06ea5
fix(build): chain pages fully on demand, catalog too big to cache at …
Flotapponnier Jun 11, 2026
2a0517c
fix(build): skip variant prefetch during next build, aggregate only
Flotapponnier Jun 11, 2026
ec9c221
Merge pull request #398 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
b53d063
fix(perf): fetch bench variants on demand instead of embedding all
Flotapponnier Jun 11, 2026
fa07669
Merge pull request #399 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
a37051b
feat(seo): add Wikidata entity to Organization sameAs
Flotapponnier Jun 11, 2026
3ed5625
fix(runtime): maxDuration 300 on heavy pages + single-flight dns check
Flotapponnier Jun 11, 2026
8d3621e
Merge pull request #400 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
e912458
fix(build): render bench pages on demand, stop prerendering 25+ Prom-…
Flotapponnier Jun 11, 2026
514f840
Merge pull request #401 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
a9a3e77
fix(build): stop prerendering og/twitter images for bench slugs
Flotapponnier Jun 11, 2026
9cfc98d
Merge pull request #402 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
7c5ace3
fix(format): add sec unit for true-seconds gauges (last fill age)
Flotapponnier Jun 11, 2026
9e4fbd0
Merge pull request #404 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
3110550
fix(cache): round prom values to 6 sig digits so heavy benches fit th…
Flotapponnier Jun 11, 2026
e8d7ab3
Merge pull request #405 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
f8cca99
fix(ledger): honest headers when sorted by a panel (no p50 label on u…
Flotapponnier Jun 11, 2026
3386d3e
Merge pull request #406 from ChainBench/feat/per-chain-bench-pages
Flotapponnier Jun 11, 2026
fe43e33
merge main into dev for prod release (keep main's dev-only bench holds)
Flotapponnier Jun 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/staging-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ concurrency:
jobs:
deploy:
runs-on: ubuntu-latest
timeout-minutes: 15
# 30 min: the build prerenders every bench/product/OG route against
# Prom through a query concurrency cap, and the per-page budget is
# 240s (next.config.ts). 15 min started killing builds once the HL
# bench grew past 60 providers.
timeout-minutes: 30
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
Expand Down
284 changes: 284 additions & 0 deletions benchmarks/hyperliquid-hip3-deployers.yml

Large diffs are not rendered by default.

25 changes: 12 additions & 13 deletions benchmarks/l1-finality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

slug: l1-finality
number: "006"
title: Fastest L1 blockchain finality, live across 10 chains
title: Fastest L1 blockchain finality, live across 11 chains
seo_title: "Fastest L1 finality 2026: TON, SUI, Stellar, Solana, Ethereum"
seo_description: "Fastest L1 blockchain finality, measured live for 10 chains. TON 0.2 s, SUI 0.5 s, Stellar 4 s, Solana 13 s, Ethereum ~16 min. p50 over 24h, open methodology."
seo_description: "Fastest L1 blockchain finality, measured live for 11 chains. TON, SUI and Hedera in seconds, Solana ~13 s, Ethereum ~12.8 min. Live percentiles over 24h, open methodology."
subtitle: Wall-clock seconds from latest block to the finalized block on Ethereum, Solana, TON, SUI, Stellar and 5 more chains, refreshed every 10 seconds.
seo_intro: |
This page measures L1 finality time live for every major Layer-1 blockchain, with p50 / p90 / p99 refreshed every 10 seconds. Stellar finality time is ~5 seconds, the close interval the Stellar Consensus Protocol locks in via federated Byzantine agreement. Solana finality time goes from sub-second on the processed commitment to ~12.8 s on finalized after 32 confirmed slots. Ethereum finality time is ~12.8 minutes, the 2-epoch Casper FFG window. Hedera finality time clears in 3-5 seconds via Hashgraph aBFT. SUI finality time and TON finality time both sit under one second via Mysticeti DAG-BFT and BAG consensus. BNB and Avalanche finality time land near two seconds through fast-finality forks. Probabilistic chains (Litecoin, Monero, Cardano) settle on a confirmation-depth convention measured here in minutes.
This page measures L1 finality time live for every major Layer-1 blockchain, with p50 / p90 / p99 refreshed every 10 seconds. Stellar finality time is ~5 seconds, the close interval the Stellar Consensus Protocol locks in via federated Byzantine agreement. Solana finality time goes from sub-second on the processed commitment to ~12.8 s on finalized after 32 confirmed slots. Ethereum finality time is ~12.8 minutes, the 2-epoch Casper FFG window. Hedera finality time clears in 3-5 seconds via Hashgraph aBFT. SUI finality time and TON finality time both sit under one second via Mysticeti DAG-BFT and BAG consensus. BNB and Avalanche finality time land near two seconds through fast-finality forks. Probabilistic chains (Litecoin, Monero) settle on a confirmation-depth convention measured here in minutes.

faq:
- q: "What is blockchain finality?"
Expand All @@ -17,7 +17,7 @@ faq:
- q: "What is Ethereum finality time?"
a: "Ethereum finality time is {{p50:ethereum}} (p50, 24h). That is 2 epochs of 32 slots of 12 seconds each, the window Casper FFG needs to justify and finalize a checkpoint. The benchmark measures it live by polling eth_getBlockByNumber(\"latest\") and eth_getBlockByNumber(\"finalized\") every 10 seconds and taking the timestamp delta."
- q: "What is Solana finality time?"
a: "Solana exposes two commitments. Processed is optimistic and lands sub-second, typically under 500 ms. Finalized requires 32 confirmed slots and clocks {{p50:solana}} (p50, 24h). The leaderboard value is finalized, the stricter guarantee. Sub-second Solana finality is real but only at the processed commitment level, not finalized."
a: "Solana exposes two commitments. Processed is optimistic and lands sub-second, typically under 500 ms. Finalized requires 32 confirmed slots and clocks {{p50:solana}} (24h average). The leaderboard value is finalized, the stricter guarantee. Sub-second Solana finality is real but only at the processed commitment level, not finalized."
- q: "What is SUI finality time?"
a: "SUI clocks {{p50:sui}} (p50, 24h) on this benchmark via the Mysticeti DAG-BFT consensus protocol. The chain exposes millisecond-precision timestamps so the measurement is genuinely sub-second. Mysticeti's two-vote commitment pattern reaches deterministic finality without the multi-block confirmation depth used by classical Byzantine fault tolerant chains."
- q: "What is TON finality time?"
Expand All @@ -29,9 +29,9 @@ faq:
- q: "What is BNB Chain finality time?"
a: "BNB Smart Chain finalizes via the BEP-126 fast-finality fork, dropping the confirmation depth that legacy probabilistic chains require. p50 sits at {{p50:bnb}} (24h), measured via persistent WebSocket subscription that records T1 when block N first appears as latest and T2 when it crosses the finalized threshold."
- q: "Which blockchain has the fastest finality time?"
a: "Sub-second BFT chains lead. TON and SUI both clock under one second on this live benchmark. BNB and Avalanche sit around one to two seconds via their fast-finality forks. Solana finalized lands around 12.8 s, Ethereum at 12.8 min, and probabilistic chains (Litecoin, Monero, Cardano) trail at 15 to 30 minutes by confirmation-depth convention."
a: "Sub-second BFT chains lead. TON and SUI both clock under one second on this live benchmark. BNB and Avalanche sit around one to two seconds via their fast-finality forks. Solana finalized lands around 12.8 s, Ethereum at 12.8 min, and probabilistic chains (Litecoin, Monero) trail at 15 to 30 minutes by confirmation-depth convention."
- q: "How is L1 finality time measured on this page?"
a: "Two methods, picked per chain. RPC pollers compare latest vs finalized block timestamps every 10 seconds, used for Ethereum, Solana, TRON, Stellar, SUI, TON, Litecoin, Monero, Cardano. WebSocket subscribers record wall-clock time T1 when a block first appears on the head stream and T2 when it crosses the finality threshold, giving millisecond-precision lag for sub-poll chains (BNB, Avalanche)."
a: "Two methods, picked per chain. RPC pollers compare latest vs finalized block timestamps every 10 seconds, used for Ethereum, Solana, TRON, Stellar, SUI, TON, Litecoin, Monero. WebSocket subscribers record wall-clock time T1 when a block first appears on the head stream and T2 when it crosses the finality threshold, giving millisecond-precision lag for sub-poll chains (BNB, Avalanche)."

per_chain_explainer:
- slug: ethereum
Expand All @@ -41,7 +41,7 @@ per_chain_explainer:
- slug: solana
h2: "Solana finality time"
body: |
Solana exposes two commitments. Processed is optimistic and lands sub-second, typically under 500 ms. Finalized requires 32 confirmed slots and clocks {{p50:solana}} (p50, 24h) on this benchmark. The leaderboard value is finalized, the stricter guarantee. Sub-second Solana finality is real but only at the processed commitment level. Measured via `getSlot{commitment:"processed"}` and `getSlot{commitment:"finalized"}` translated through block timestamps.
Solana exposes two commitments. Processed is optimistic and lands sub-second, typically under 500 ms. Finalized requires 32 confirmed slots and clocks {{p50:solana}} (24h average) on this benchmark. The leaderboard value is finalized, the stricter guarantee. Sub-second Solana finality is real but only at the processed commitment level. Measured via `getSlot{commitment:"processed"}` and `getSlot{commitment:"finalized"}` translated through block timestamps.
- slug: stellar
h2: "Stellar finality time"
body: |
Expand Down Expand Up @@ -69,7 +69,7 @@ per_chain_explainer:
- slug: tron
h2: "TRON finality time"
body: |
TRON's solidity confirmation hovers around {{p50:tron}} (p50, 24h), matching the documented 20-block delay at 3-second block intervals. The solidity flag in TRON consensus is the chain's equivalent of finalized: a block survives until 20 confirmations before being considered irreversible. Measured via `/wallet/getnowblock` (head) minus `/walletsolidity/getnowblock` (solidity-confirmed).
TRON's solidity confirmation hovers around {{p50:tron}} (24h average), matching the documented 20-block delay at 3-second block intervals. The solidity flag in TRON consensus is the chain's equivalent of finalized: a block survives until 20 confirmations before being considered irreversible. Measured via `/wallet/getnowblock` (head) minus `/walletsolidity/getnowblock` (solidity-confirmed).
- slug: litecoin
h2: "Litecoin finality time"
body: |
Expand All @@ -90,7 +90,7 @@ abstract: |
finalized block. The harness uses two complementary methods. For
chains with finality much longer than our 10 s poll interval we read
`latest.timestamp, finalized.timestamp` from the chain RPCs (Ethereum,
Solana, TRON, Litecoin, Monero, Cardano). For chains whose finality
Solana, TRON, Litecoin, Monero). For chains whose finality
is faster than the poll interval (BNB, Avalanche, SUI, TON, Stellar)
we maintain a persistent WebSocket / SSE subscription, recording
wall-clock time T1 when block N is first seen as `latest` and T2
Expand All @@ -114,17 +114,16 @@ methodology:
- "TON: tonapi.io `/blockchain/masterchain-head` minus 3 seqno."
- "Litecoin (probabilistic): blockchair `/stats.best_block_height` minus 6 confirmations via `/dashboards/block/{height}.block.time`."
- "Monero (probabilistic): monero-rpc `get_info` minus 10 confirmations via `get_block_header_by_height`."
- "Cardano (probabilistic): koios `/tip` minus 15 confirmations via `/blocks?block_height=eq.<height>`. 15 matches the depth top exchanges (Coinbase / Kraken) treat as final settlement; Ouroboros Praos full settlement is k = 2160 blocks (~12 h) and is not the practical convention."
- "Hedera (planned, currently disabled): mirror-node `/api/v1/blocks` only exposes already-final blocks, so true wall-clock lag is impossible from public endpoints. Re-enables once Block Nodes (HIP-1056) leave private preview."
- "Result: `lag_seconds = headTimestamp, finalizedTimestamp`. We also record the block-height delta and per-chain fetch latency."
- "Excluded by design: XRP (no close-time on `ledger_current`, wall-clock measurement requires WS subscribe to ledger stream, not yet implemented)."
- "Failures (5xx, timeouts, rate limits) leave the previous gauge in place and increment a per-chain `fetch_errors_total` counter; the page falls back to the last successful sample."

findings:
- "{{name:sui}} returns {{p50:sui}} (p50, 24 h), matching its Mysticeti DAG BFT design. The chain exposes ms timestamps so the measurement is genuinely sub-second."
- "{{name:ethereum}} sits at {{p50:ethereum}} (p50, 24 h), aligned with the 2-epoch finalization spec (32 slots × 12 s × 2)."
- "{{name:ethereum}} sits at {{p50:ethereum}} (24 h average), aligned with the 2-epoch finalization spec (32 slots × 12 s × 2)."
- "{{name:tron}}'s solidity confirmation hovers around {{p50:tron}}, exactly the documented 20-block delay at 3 s blocks."
- "{{name:litecoin}} and {{name:monero}} sit at {{p50:litecoin}} and {{p50:monero}} (p50, 24 h) by construction, set by the chosen confirmation depth."
- "{{name:litecoin}} and {{name:monero}} sit at {{p50:litecoin}} and {{p50:monero}} (24 h average) by construction, set by the chosen confirmation depth."
- "{{best_name}} currently leads the leaderboard at {{best_p50}} (p50, 24 h) across {{count}} measured L1s. {{worst_name}} trails at {{worst_p50}}."
- "Hedera's Hashgraph aBFT is designed to finalize in 3-5 s but is excluded from the live leaderboard because the mirror node only exposes finalized blocks, wall-clock measurement requires the Block Node service (HIP-1056), still in private preview."

Expand Down Expand Up @@ -190,7 +189,7 @@ providers:

- slug: ton
name: TON
tag: Masterchain commit, measured via SSE wall-clock
tag: Masterchain commit, polled via tonapi.io
formula: "Median wall-clock milliseconds for a TON masterchain block to commit under BAG consensus, polled via tonapi.io with a 3-seqno lookback, p50 over 24h."
queries:
p50: quantile_over_time(0.50, l1_finality_wallclock_lag_milliseconds{chain="ton"}[24h])
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/metadata-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ abstract: |

A value of 100% means every field was returned for every fresh token; a
value of 50% means half the fields were missing on average. Sort order on
this page is ascending, so the lowest coverage shows first, which is the
this page is descending, so the highest coverage shows first, which is the
inverse of latency benchmarks. Readers should compare the columns
themselves; numerical p50 is the headline.

Expand Down
2 changes: 1 addition & 1 deletion benchmarks/network-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ slug: network-coverage
number: "005"
title: Crypto data API with most blockchains supported, live coverage ranking
seo_title: "Crypto data API most chains 2026: CoinPaprika, GeckoTerminal"
seo_description: "Crypto data API with the most blockchains supported, ranked live. CoinPaprika 306, GeckoTerminal 264, CoinStats 149, Codex 120, Mobula 79. Audited every six hours."
seo_description: "Crypto data API with the most blockchains supported, ranked live. {{best_name}} leads at {{best_p50}} networks; GeckoTerminal, CoinStats, Codex, Covalent, Dune and Mobula compared. Audited every six hours."
subtitle: Number of blockchains each major crypto data API officially supports, audited every six hours against each provider's public network endpoint.
category: Aggregators
status: live
Expand Down
6 changes: 3 additions & 3 deletions benchmarks/oracle-deviation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ abstract: |
We measure live oracle disagreement by polling four price oracles
every 30 seconds for ten USD-quoted blue chips, then computing the
full pairwise deviation matrix per pair. Deviation between two
sources is `|price_a, price_b| / ((price_a + price_b) / 2) * 100`
sources is `|price_a - price_b| / ((price_a + price_b) / 2) * 100`
in percent; the bench surfaces it both per source-pair
(`ocb_oracle_deviation_pct{source_a, source_b}`) and as the per-pair
maximum across all source pairs (`ocb_oracle_max_deviation_pct`).
Expand All @@ -64,12 +64,12 @@ methodology:
- "Sources. Chainlink AggregatorV3 via `eth_call(latestRoundData())` on Ethereum mainnet (no API key, public RPC with fallback), Pyth Network via Hermes REST `/api/latest_price_feeds` batch endpoint (no key), Binance REST `/api/v3/ticker/price` on USDT-quoted symbols (treated as ≈ USD), Coinbase REST `/products/<P>/ticker` on USD-quoted products. All four are free, no-auth, public endpoints."
- "Pairs (10). BTC, ETH, SOL, BNB, AVAX, LINK and POL are tracked on all 4 sources. XRP, ADA, DOGE are tracked on 3 sources (Pyth + Binance + Coinbase) because the Chainlink mainnet AggregatorV3 contracts for these USD feeds are deprecated and no longer updated by node operators, the provider tag flags it."
- "Cadence. 30 second polling interval per (source, pair). 4 sources × 10 pairs × 2/minute = 80 requests/minute total, comfortably under every free-tier ceiling (Binance 1200/min, Coinbase 10/s public, Pyth ~30/s soft, public RPC courteous). HTTP timeout is 8 s per request to match the gas-estimation harness."
- "Deviation formula. For every unordered pair of sources `(a, b)` that both have a fresh sample for the same pair: `deviation_pct = |price_a, price_b| / ((price_a + price_b) / 2) * 100`. With 4 sources we compute 6 pairwise deviations per asset; with 3 sources we compute 3. Per-pair headline is the max across all source-pairs (`ocb_oracle_max_deviation_pct`)."
- "Deviation formula. For every unordered pair of sources `(a, b)` that both have a fresh sample for the same pair: `deviation_pct = |price_a - price_b| / ((price_a + price_b) / 2) * 100`. With 4 sources we compute 6 pairwise deviations per asset; with 3 sources we compute 3. Per-pair headline is the max across all source-pairs (`ocb_oracle_max_deviation_pct`)."
- "Stale-price guard. A source's sample is considered stale and excluded from the deviation calculation if its last successful update is older than `2 * pollInterval` (60 s). Prevents a dead Coinbase ticker from registering as a 0% deviation against itself by leaving the price gauge fossilized."
- "Chainlink round age. The on-chain `updatedAt` timestamp from `latestRoundData()` is published separately as `ocb_oracle_last_round_age_seconds{source=\"chainlink\", pair}`. Chainlink updates only on deviation (typically 0.25-0.5% for blue chips) or heartbeat (~1 h), so a 30-minute age on a quiet ETH minute is normal; a 2-hour age on SOL during a volatile minute is the actual signal."
- "USDT ≈ USD assumption. Binance only quotes USDT pairs (BTCUSDT, etc.). We treat USDT as ≈ USD ± 10 bps drift, which is acceptable for a bench whose alert floor is ≥ 10 bps. A real USDT depeg would surface as Binance drifting from the other three sources for *every* pair simultaneously, exactly what we want this bench to flag, not hide."
- "MATIC → POL migration. Polygon migrated MATIC → POL 1:1 on Sep 4 2024. The Chainlink mainnet feed contract is still named MATIC/USD but on-chain `description()` confirms it tracks the POL token; Pyth renamed the feed to POL/USD; Coinbase delisted MATIC-USD and only lists POL-USD; Binance kept MATICUSDT as a frozen historical pair AND lists POLUSDT. We point Binance at POLUSDT so all four sources track the same underlying asset. Bench label is kept as `pair=\"MATIC/USD\"` for query continuity."
- "Time-aligned deviation (canonical headline). For every pair of sources (a, b) we anchor on the more recent of their two SourceTSs (Chainlink's on-chain `updatedAt` for Chainlink, fetch time for the continuously-updating sources) and look up the older source's price in a 30-minute per-source rolling history at the anchor moment. The result is published as `ocb_oracle_deviation_at_oracle_ts_pct` and feeds the leaderboard headline `ocb_oracle_max_deviation_pct`. This eliminates the artifact where Chainlink's heartbeat lag inflates 'deviation' by the market's drift between its updates — a researcher grading oracle quality wants to compare Chainlink's price against the market at Chainlink's own updatedAt, not at the harness's fetch instant. The legacy fetch-time gauge (`ocb_oracle_deviation_pct`, aliased as `ocb_oracle_deviation_at_fetch_ts_pct`) is preserved unchanged for backward compatibility. Alignment misses (no history sample within ±10s of the anchor) are counted as `ocb_oracle_alignment_miss_total`. Methodology recommendation from Coinpaprika data team review; matches the convention published by Chaos Labs and Risk DAO oracle risk reports."
- "Time-aligned deviation (canonical headline). For every source pair we anchor on the more recent SourceTS (Chainlink's on-chain `updatedAt`, fetch time for continuous sources) and look up the older source's price in a 30-minute rolling history at that moment. Published as `ocb_oracle_deviation_at_oracle_ts_pct`, feeding `ocb_oracle_max_deviation_pct`. Removes Chainlink heartbeat-lag inflating deviation; alignment misses count as `ocb_oracle_alignment_miss_total`."
- "Excluded by design. Redstone (push-pull, no continuous gauge to scrape without integration contract), Uniswap V3 TWAP (per-pool integration + derivation of same CEX prints), DIA (smaller footprint than the four kept), and aggregator-of-aggregators (CoinGecko, CMC, DefiLlama), re-aggregating already-aggregated data adds latency and hides per-source disagreement."

findings:
Expand Down
Loading
Loading