Oracle
Live GPU compute benchmarks · protocol reference prices · public data
The oracle turns fragmented GPU rental-market observations into auditable USD-per-GPU-hour benchmarks — one per supported GPU class. Computation is offchain: every candidate carries the methodology, provenance, and receipt that produced it, and the public API serves the benchmark as data. A separate publisher process independently audits each candidate and writes eligible values to the onchain GPUPriceOracle — the external reference price the gUSD protocol executes against: hook fills, POL pricing, and primary issuance all read it. This tab shows how the number is made; the other tabs let you audit it — the benchmarks it publishes, the rules it runs, the health of every layer, and the interfaces it serves.
Pipeline
sources → protocol executionSOURCES GPU rental markets · ECB FX · 2 watchdog feeds
order books · rate cards · price lists
cadences FAST 15s · MEDIUM 60s · SLOW 900s
│
▼
INGEST append-only ledger
every observation stored with its inputs · nothing rewritten
│
▼
NORMALIZE units · FX → USD per GPU-hour
ECB reference rates · monthly ÷ 730 · arithmetic tripwire
│
▼
PANEL one vote per provider
depth floors ≥5 machines · ≥3 hosts · median per provider
│
▼
SCREENS MAD 3σ · jump
|price − median| > 3σ excluded · ≥25% solo move needs 2 corroborators
│
▼
WEIGHTS executable 1.0 · rate card 0.6 · cap 0.35
│
▼
AGGREGATE weighted mean · confidence band
dispersion = 1.4826 · MAD / median
│
▼
GATES ≥4 providers · ≥3 observations · ≤30 min · disp ≤ 0.45
fail ⇒ withheld · silent window ⇒ carry forward ≤24h, stale
│
▼
CANDIDATE oracle verdict · calcHash receipt
benchmark API + receipt — REST · SSE · WS · this app
│
▼
PUBLISHER independent audit of every candidate
violations recorded · publishes on deviation / heartbeat policy
(~0.5% move or ~24h) · no price ⇒ never published
│
▼
GPUPriceOracle onchain reference price, USD/GPU-hour × 10⁴
│
▼
PROTOCOL hook fill edges · POL pricing · issuance backstopCollectors watch the GPU rental markets on three cadences — order books print executable prices, principals publish rate cards — alongside two independent watchdog feeds and ECB reference rates. Every observation lands in an append-only ledger and is normalized to USD per GPU-hour.
The engine screens what arrives: a deviation beyond three robust standard deviations from the panel median is excluded, and a solo provider jumping 25% needs two corroborators before the move counts. What survives is voted into per-provider medians, weighted — executable quotes 1.0, rate cards 0.6, any one provider capped at 35% — and aggregated into a weighted mean with a confidence band.
Publication gates decide the oracle's verdict: four providers, three observations behind every vote, a 30-minute age ceiling, dispersion within bounds — pass and the benchmark publishes with its receipt; fail and it withholds. A silent window carries the last figure forward for at most 24 hours, flagged stale.
Computation and publication are deliberately separate layers. The candidate — its verdict, band, and receipt — exists whether or not anything goes onchain. The publisher re-derives each candidate against the stored methodology, records what it finds, and publishes when the benchmark has moved ~0.5% from the last published value — or a heartbeat (~24 h) refreshes it. Onchain writes are driven by that policy, not by every computation.
The thresholds on this diagram are the shipped engine defaults, catalogued on the Methodology tab; the live source registry — every collector, its role, and its cadence — prints there too, served from the oracle itself.
Why trust it
auditable by constructionObservations and receipts are stored as they land and never rewritten. History is a ledger, not a document that can be edited — an audit can replay it from the start.
Every candidate embeds a receipt — the methodology config, every gate verdict, every contribution and exclusion — and calcHash is its sha256. Re-running the same window over the same inputs reproduces the same bytes: a receipt is a fact, not a claim.
A separate publisher process re-derives each candidate against the stored methodology — freshness, contributors, dispersion, band, source health — and records every violation in its own audit ledger. Publication itself is policy-driven (deviation trigger, heartbeat). The gate is not the calculator grading its own work.
Benchmark computation, publisher audit, and onchain publication are separate processes with separate state. The Health tab reports each layer for what it is — a candidate's status is not the publisher's verdict, and neither is the onchain state.
Every benchmark figure on this site carries the oracle's own verdict — LIVE, STALE, WITHHELD, FROZEN, UNAVAILABLE. The interface never paints a figure healthier than the oracle says it is.
Reference vs execution
doctrineThe benchmark answers one question: what is one GPU-hour of a class worth in the underlying compute economy? It is derived from rental-market observations — order books, rate cards, price lists — and the protocol's own markets never vote in it. The market does not feed back into the benchmark.
Onchain execution answers a different question: at what price can this specific trade execute? Uniswap-native LP liquidity fills at the pool price up to an oracle-anchored edge; demand beyond that edge is filled by the hook itself from POL inventory and the issuance backstop, priced off the current oracle reference. One swap is the complete market — neither side has to equal the benchmark exactly.
Because the hook prices its edges off the oracle, oracle-priced execution moves when the oracle moves — it does not wait for AMM ticks to drift toward the new reference. A stale oracle degrades gracefully: the hook steps aside and the pool trades natively until a fresh publication returns.
Benchmark board
USD / GPU-hour · reference price| Benchmark | Reference / GPU-hour | 24h | Sources | Updated |
|---|---|---|---|---|
| — | — | — | — | |
| — | — | — | — | |
| — | — | — | — | |
| — | — | — | — |
Reading the panel receipt…
Each benchmark is the engine's USD-per-GPU-hour reference for its class, built from provider observations. Select a benchmark to read its panel receipt — the contributors, weights, methods, screens, and exclusions behind the latest candidate.
gUSD H100 benchmark
reference seriesNo series yet — the oracle's candles for this range have not loaded.
The benchmark's own series — execution tapes live under Protocol data (Developers tab) and on each market's desk
These are the rules the oracle runs as shipped — not a summary of intent. Every threshold below is the value in the published methodology configuration; a change to any of them is a new version, and every candidate records the one that produced it.
Pipeline stages
thresholds live in config, never in code| Stage | Rule | Parameters |
|---|---|---|
| Normalize | Units and FX fold into USD per GPU-hour against ECB reference rates (monthly ÷ 730). Rows must add up: a listed total that disagrees with its own per-GPU price is a lie, and is excluded. | tol $0.005/GPU · gpus 1–16 · on_demand |
| Panel | One vote per provider: the median of that provider's observations — volume-weighted by machine count for order books, a plain median over listed prices for rate cards — taken over a book that clears the depth floors. A thinner book than the floors is held out, not priced. | ≥5 machines · ≥3 hosts |
| Screens | Cross-provider MAD screen excludes sources beyond 3 robust σ (σ = 1.4826·MAD) from the panel median; it arms only at 4+ providers, and a zero-MAD tie falls back to a symmetric 3× ratio band. Separately, a provider jumping 25% against its own trailing median is suspect unless 2 others moved 10%+. | 3σ · band 3× · jump 25% ⇉ 2×10% |
| Weights | Executable order-book votes weigh 1.0, rate cards 0.6. After aggregation, no single provider may exceed 35% of total weight — no principal owns the number. | 1.0 / 0.6 · cap 0.35 |
| Aggregate | Weighted mean of the capped weights over the per-provider medians — that is the published price. The confidence band comes from p±σ votes: each contributor casts three votes at p(1−σ), p, p(1+σ) with σ = max(0.03, its own historical dispersion); the band's centre is the weighted mean of the central third of all votes, and its half-width the distance to the 25th/75th weighted quantiles. Dispersion is 1.4826·MAD / median. | mean · vote-IQM band · σ floor 0.03 |
| Gates | Publishing requires 4+ providers, 3+ observations behind every vote, observations no older than 30 minutes, at least one executable contributor, and dispersion ≤ 0.45. Any gate failing ⇒ the figure is withheld (the receipt still records why). | 4 · 3 · 30 min · 1 exe · ≤0.45 |
| Stale | A window that comes back silent carries the last figure forward — flagged stale, never re-dated — for at most 24 hours. Past that window the figure is withheld. | 24 h carry-forward |
| Movement | Publishing allowance: the printed figure carries a bounded, deterministic, mean-reverting offset within ±0.05% of the computed anchor, so rate-card-settled panels (whose sources are static list prices) still print a moving series. The anchor itself is untouched — screens, band and gates compute on real data — and every publication records its exact offset in the receipt. The first publication prints the pure anchor; stale and withheld figures never drift. | ±0.05% · mean-reverting · recorded |
Verdicts
Full settlement quorum met, dispersion ≤ 0.25. The figure publishes at full confidence.
Dispersion within 0.45, or the panel computed on a relaxed quorum. It publishes, flagged — never at full confidence.
The window came back silent; the last figure inside 24 h is carried forward, flagged.
A gate failed, or silence outlasted the carry-forward window. No figure prints.
Withheld is safer than fabricated: when the gates fail, the oracle publishes no figure rather than a doubtful one, and the interface prints no number rather than a wrong one.
Provider registry
GET /v1/providers · read-onlyReading the collector registry…
Methodology version
versioned, never mutatedThe methodology is a configuration, not code paths: thresholds live in a validated config that is versioned and stored with every receipt. There is no hot-editing — a methodology change is a new config under a new version, checked field by field before it can drive a computation, and a config that half-matches fails loudly rather than partially applying.
Per-panel overrides are part of the versioned config, never side channels: a panel that cannot reach the full settlement quorum may carry explicit, versioned relief — named additional sources, a lower provider floor, executable pricing relaxed — and the override may only ever relax a gate. The engine caps any panel that computes below the full settlement quorum at degraded: a relaxed panel can never claim healthy. Which panels carry which relief prints with the registry and receipts — the config, not this page, is the record.
Historical receipts stay tied to the version that produced them — the wire stamps every candidate with its methodologyVersion, and older receipts stay readable against their own rules. History is never re-interpreted under new rules.
The stack reporting itself — not a dashboard's opinion of it. Benchmark health comes off the same wire the benchmarks do: candidate freshness, contributing providers, collector breakers, per-panel verdicts. Onchain publication health comes from the indexed GPUPriceOracle state — what the publisher last wrote, and how the benchmark has moved since. The layers report separately because they are separate: a candidate's status is not the publisher's verdict, and neither is the onchain state.
Benchmark feed
candidate layer · GET /v1/prices · /v1/health- Latest receipt
- —
- Updated
- —
- Live sources
- —
- Overall
- —
- Database
- —
No publication has reached this session yet — the cells fill with the first candidate.
Collector health
GET /v1/health · per-collector breakersReading collector health…
Panel freshness
the oracle's own verdict| Panel | Status | Last publication |
|---|---|---|
| gUSD H100 Index | — | — |
| gUSD H200 Index | — | — |
| gUSD L40S Index | — | — |
| gUSD RTX4090 Index | — | — |
Freshness is the oracle's own verdict on the candidate layer, not the page's: LIVE sits inside the publisher's freshness gate, STALE inside the carry-forward window, WITHHELD when the gates refused to assert a price. A dash means no publication has reached this session. What the publisher did with these candidates is the next panel's question.
Onchain publication
GPUPriceOracle · indexed state · GET /v1/protocol/oracle/:gpu| Panel | Onchain | Benchmark | Gap | Publication | Age |
|---|---|---|---|---|---|
| gUSD H100 Index | — | — | — | none indexed | — |
| gUSD H200 Index | — | — | — | none indexed | — |
| gUSD L40S Index | — | — | — | none indexed | — |
| gUSD RTX4090 Index | — | — | — | none indexed | — |
The publisher audits every candidate against the stored methodology and records violations in its own ledger (not exposed here); publication itself follows the deviation/heartbeat policy, so the onchain value lags the benchmark by design. Stale means the publication outlived the protocol's staleness window; a dash means the indexer has seen no publication for that panel. Blocks, not client clocks, date a publication.
The oracle is both protocol infrastructure and a public data product. This tab documents the read interfaces exposed by this deployment: benchmark data from the GPU pricing engine, and indexed protocol state from the chain. Every endpoint below is served today and consumed by this site — there is no private path the app keeps for itself. Point a client at the base URL and read.
Interface catalog
status as shippedBenchmark data — the pricing engine
Protocol data — indexed chain state
All rows are live. Protocol routes are registered when this deployment indexes chain state; without the indexer they answer 404 rather than pretending. Nothing here invents endpoints that don't exist.
Endpoint reference
the candidate is the unit| Parameter | Routes | Meaning |
|---|---|---|
| :gpu | all /v1/prices/:gpu/* | panel id (H100_PANEL_V1) or gpu id (H100_SXM_80GB); anything else is a 404 |
| limit | history · protocol lists | benchmark history 1–500, default 100; protocol pages 1–200, default 100 |
| intervalSec | candles | one of 60 · 300 · 900 · 1800 · 3600 · 14400 · 21600 · 43200 · 86400 · 604800 (seconds) |
| from · to | candles · stats | candles take epoch ms or ISO instants (absent → trailing 24 h, ≤2000 buckets); protocol stats take epoch seconds, hourly grain |
| cursor | protocol lists | keyset cursor from the previous page's nextCursor — no offsets, stable under inserts |
| chainId | protocol lookups | disambiguates a pool/gpu id that exists on more than one indexed chain |
Shape
{
gpuId: "H100_SXM_80GB",
panelId: "H100_PANEL_V1",
price: 2.4312, // USD / GPU-hour · null when withheld
confidenceLow: 2.4015, // the confidence band
confidenceHigh: 2.4609,
dispersion: 0.018, // 1.4826·MAD / median
status: "healthy", // healthy · degraded · stale · withheld
providersObserved: 10, // panel size this window
providersContributing: 9, // votes that survived the screens
methodologyVersion: "0.4.0",
calcHash: "3f9c1ab…", // sha256 receipt — the publication's identity
computedAt: "2026-09-04T14:00:00.000Z",
windowStart: "2026-09-04T13:00:00.000Z",
windowEnd: "2026-09-04T14:00:00.000Z"
}As served — GET /v1/prices/H100_PANEL_V1
{
"gpuId": "H100_SXM_80GB",
"panelId": "H100_PANEL_V1",
"price": 2.4312,
"confidenceLow": 2.4015,
"confidenceHigh": 2.4609,
"dispersion": 0.018,
"status": "healthy",
"providersObserved": 10,
"providersContributing": 9,
"methodologyVersion": "0.4.0",
"calcHash": "sample00calculatehash0000000000000000000000000000",
"computedAt": "2026-09-04T14:00:00.000Z",
"windowStart": "2026-09-04T13:00:00.000Z",
"windowEnd": "2026-09-04T14:00:00.000Z"
}Sample candidate shape — the oracle has not published to this session. Connect the oracle to see the live payload here.
Code samples
https://beta-api.gusd.lolBASE=https://beta-api.gusd.lol # latest candidate for one settlement panel (panel id or gpu id) curl $BASE/v1/prices/H100_PANEL_V1 # the panel receipt behind it — contributors, weights, screens curl $BASE/v1/prices/H100_PANEL_V1/providers # 1-hour reference candles for the trailing week (epoch ms) curl "$BASE/v1/prices/H100_PANEL_V1/candles?intervalSec=3600&from=$(($(date +%s)000-604800000))&to=$(date +%s)000" # indexed protocol state — pools, per-asset stats, the onchain publication curl $BASE/v1/protocol/pools curl $BASE/v1/protocol/gpus/H100_SXM_80GB curl $BASE/v1/protocol/oracle/H100_SXM_80GB # live publications curl -N $BASE/v1/stream/sse
const BASE = "https://beta-api.gusd.lol";
type Candidate = {
gpuId: string;
price: number | null; // USD / GPU-hour
status: string; // healthy · degraded · stale · withheld
calcHash: string; // receipt identity
methodologyVersion: string;
};
// one-shot read — plain GET, CORS open, no keys
const res = await fetch(`${BASE}/v1/prices/H100_PANEL_V1`);
const candidate = (await res.json()) as Candidate;
// indexed protocol state lives under /v1/protocol on the same host
const gpus = await fetch(`${BASE}/v1/protocol/gpus`).then((r) => r.json());
// live publications
const stream = new EventSource(`${BASE}/v1/stream/sse`);
stream.addEventListener("candidate", (e) => {
const c = JSON.parse((e as MessageEvent<string>).data) as Candidate;
});
stream.onopen = async () => {
// the stream is lossy — REST is the truth; sync on open
await fetch(`${BASE}/v1/prices`);
};import json, requests, sseclient
BASE = "https://beta-api.gusd.lol"
# one-shot read
candidate = requests.get(f"{BASE}/v1/prices/H100_PANEL_V1", timeout=5).json()
# indexed protocol state — pools, per-asset stats, the onchain publication
pools = requests.get(f"{BASE}/v1/protocol/pools", timeout=5).json()
oracle = requests.get(f"{BASE}/v1/protocol/oracle/H100_SXM_80GB", timeout=5).json()
# live publications — re-read REST on connect; the stream is lossy
stream = requests.get(f"{BASE}/v1/stream/sse", stream=True, timeout=None)
for event in sseclient.SSEClient(stream).events():
if event.event == "candidate":
candidate = json.loads(event.data)All endpoints are plain GETs, CORS is open, and there are no keys. The base URL shown is this deployment's — set NEXT_PUBLIC_ORACLE_URL to point the samples elsewhere. Protocol routes hang off the same host under /v1/protocol.
Streaming
SSE · WebSocket: connected
: ping
event: candidate
data: {"gpuId":"H100_SXM_80GB",
"price":2.4312,
"status":"healthy", …}Frames are event: candidate with the candidate JSON as data — the same shape as GET /v1/prices/:gpu. After connecting the server writes : connected, then : ping every 15 seconds; the ping proves the transport, not the data.
Candidates publish as computed, debounced at least 10 seconds apart per panel — silence usually means nothing changed, not that the stream died.
The stream is lossy by design: a highlight reel, not a record. Treat REST as the truth — on open, re-read GET /v1/prices before trusting the frames you missed. The client that powers this site does exactly that.
A WebSocket variant serves the same candidates at GET /v1/stream, wrapped as text frames: {"type":"candidate","candidate":{…}}.
Historical data
GET /v1/prices/:gpu/candlesintervalSec ∈ 60 300 900 1800 3600 14400 21600 43200 86400 604800 — one minute to one week. Each bucket aggregates the computed benchmarks that landed within it.
from/to take epoch ms or ISO instants; absent, the trailing 24 hours. A window may span at most 2000 buckets. Buckets return oldest-first on a regular grid, ready for arithmetic on t.
A silent interval comes back as a carried bucket — o = h = l = c = previous close, samples 0, carried: true. It asserts that nothing new landed, never a level: skip it or flatten it, but never read it as a price.
The benchmark's own history — every gated computation aggregated per interval. These are observations, not trades: execution OHLC is a different series, served from the indexed swap tape under /v1/protocol/pools/:poolId.
Access
open by constructionEvery endpoint on this tab is open today — plain GETs, CORS open, no keys, no account. There is no separate public tier to opt into: the feed that serves you is the feed this site runs on, and the protocol routes are the same interfaces the app reads its indexed state from.
The protocol page describes the architecture the data flows through — how benchmarks become reference prices, and how execution consumes them.