Skip to content

Oracles & Mark Prices

A perpetual's price on the order book and the "true" value of the underlying asset are not the same thing. The order book can be thin, spoofed, or briefly dislocated; the underlying asset has a price that exists independently of any one venue. Proof keeps these separate. An external oracle feeds the exchange a manipulation-resistant reference price for each underlying asset, and the engine derives its reference prices — its mark prices — from that feed rather than from the raw order book wherever risk is at stake.

This document explains where prices come from, the two distinct marks the engine maintains, how the oracle decides event resolution, what happens when a feed goes stale, and why an oracle-driven design is safer than marking everything to the book.

Where prices come from

Every underlying perpetual is anchored to a push-based oracle. Price updates are pushed into the exchange as signed transactions — the exchange does not poll an endpoint or read prices off its own book. Each update carries a publish time, and the engine enforces that publish times are strictly increasing: an update older than the one already stored is rejected. That replay guard means a stale or rewound price can never overwrite a fresher one, even if it is re-submitted.

This oracle is the primary feed. It is the single source of truth for what an underlying asset is worth, and it does two jobs:

  1. It drives the risk mark for the underlying perpetual (and, indirectly, for the conditional perps built over it) — the price used for margin, equity, profit-and-loss, and liquidation.
  2. It drives event resolution for conditional markets whose outcome is a price question (e.g. "does the asset close above K?").

Oracle updates are processed with the highest priority in a block, ahead of any trading. So within any block, the engine first takes in fresh prices, then matches orders and runs risk against those prices. Traders never get filled or liquidated against a price the block has not yet seen.

What the conditional legs use

The conditional legs of a family — the two conditional perpetuals and the two prediction binaries — have no continuous oracle of their own. There is no external feed for "the asset's price if the event resolves YES." An attempt to push an oracle update directly to a conditional leg is rejected.

Instead:

  • A conditional perpetual is margined and settled against the underlying perpetual's oracle, because at resolution the winning conditional perp cash-settles to the underlying's price. Its own order book has a price (its conditional forward, CY or CN), but that price is not what the risk engine uses for margin. The leg's own book mark is a display reference (it tracks the leg's own book), not its risk mark.
  • A prediction binary has a known settlement value by construction — it pays $1 if it wins, $0 if it loses — so it does not need a price feed to be valued for risk.

So the only oracle any conditional market consults is the underlying perpetual's feed. There is no separate oracle surface that a stray or captured update could corrupt on the conditional side.

The risk mark vs the funding mark

Proof maintains two distinct mark prices per market, by design, and they can diverge. Confusing them is the single most common source of "the number looks wrong" questions, so it is worth being precise.

MarkDrivesComes from
Risk markMargin, equity, unrealized P&L, liquidation, and conditional-market settlementThe oracle (for perps); the underlying oracle (for conditional perps)
Funding markThe funding-rate premium, and nothing elseThe order book's own moving average of recent trades

The risk mark — oracle-based

The risk mark is the price the engine uses to decide whether you are solvent. For a standard perpetual, the risk mark is the oracle price — not the last trade, not the book mid. This is the deliberate anti-manipulation choice: a single spoofed print, a thin-book wick, or a momentary flash crash on the order book cannot move your margin or trigger your liquidation, because the engine is not looking at the book to value your position. It is looking at the external reference.

For a conditional perpetual, the risk mark is the underlying perpetual's oracle, because that is the price the winning branch will settle to. For a prediction binary, the relevant value for risk is its fixed $1/$0 payoff.

The engine also supports a multi-source risk-mark mode, where the mark is a blend (e.g. a median of the oracle, a liquidity-filtered book mid, and a composite of external venues), with each candidate source dropped when it is empty, crossed, or stale. Live markets run oracle-only for the strongest manipulation resistance; the blended mode is available where a composite reference is preferred.

The funding mark — book-based

The funding mark exists only to compute funding (see the funding section of the perpetuals docs). It tracks the order book's own price: a moving average of recent trades that responds to flow. It is deliberately a book-derived number, because funding's whole job is to measure how far the market's traded price has drifted from the oracle and to charge that gap to whichever side is causing it.

The funding mark is used for funding and nothing else. It never touches your margin, your equity, your liquidation, or settlement. Funding itself applies only to perpetuals — the entire conditional family (conditional perps and prediction binaries) is excluded and never accrues funding.

Why two marks?

Because the two jobs have opposite requirements. Risk valuation wants a price that is hard to manipulate and stable under thin or hostile book conditions — so it uses the oracle. Funding wants a price that reflects what the market is actually trading at so it can pull the book back toward the reference — so it uses the book. Forcing both onto one number would either make funding blind to real book drift or make margin vulnerable to book manipulation. Keeping them separate lets each do its job.

A worked illustration. Suppose an asset's oracle reads $100.00 and, after a burst of aggressive buying, the perp's book is trading around $100.40.

  • Your risk mark is $100.00. Your margin and any liquidation check are computed against $100.00, regardless of the $0.40 of book froth.
  • Your funding mark is ~$100.40. Funding sees a premium of about +0.40% of the oracle, so longs pay shorts this cycle — the payment that nudges the book back toward $100.00.

(All numbers here are illustrative.)

How the oracle drives event resolution

For conditional markets whose outcome is a price question, the same primary oracle that marks the underlying also decides the event.

Resolution settles all of a family's books atomically, in a single step, to one of three outcomes: YES, NO, or voided (unresolvable). When the outcome can be derived from a price — "did the underlying finish above K?" — the engine derives it from the oracle. The operator-asserted outcome is re-checked against the oracle and rejected if it disagrees. So a resolution cannot claim YES when the oracle says NO.

The one outcome that is never auto-derived from a price is a void. Voiding is the deliberate escape hatch for an event that genuinely cannot be resolved (a data source disappears, the question becomes ambiguous), and it always overrides — it is the one disposition an operator can assert that the oracle does not have to confirm.

At resolution:

  • The winning conditional perpetual cash-settles to the underlying's mark.
  • The losing conditional perpetual is voided — its profit-and-loss is zero and its margin is returned. It does not settle to $0 as a loss.
  • The prediction binaries pay $1 to the winner and $0 to the loser; on a void, both pay $0.

Because the same oracle anchors both the underlying's value and the event's outcome, the price you are marked against and the price your event resolves on are consistent — there is no second, disagreeing reference that the resolution could drift away from.

Staleness and why marks can pause

An oracle is only as good as its freshness. A reference price from ten minutes ago is not a safe basis for liquidating someone in a fast market. So the engine has staleness protections on the oracle, on both the read path (using a price) and the write path (accepting a new one).

On the read path, a market can be configured with a maximum acceptable age for its oracle. If the latest oracle price is older than that limit, the engine does not silently fall back to a stale number and does not mark to the possibly-dislocated book instead. It treats the mark as unavailable — risk operations that need a price effectively pause for that market rather than run against bad data. The protection is configurable per market; the point is that the engine has a defined behavior for "the feed went quiet" instead of trusting whatever number it last saw.

On the write path, a new price is only accepted if its publish time is strictly newer than the one already stored — the replay guard described above. A stale or rewound update can never overwrite a fresher one. Taken together, the read-path age limit and the write-path replay guard are the engine's oracle-staleness protections.

Why pause rather than guess? Because the alternatives are worse. If the engine kept using a frozen price, it could let an insolvent account look healthy (or mark a healthy account into a wrongful liquidation) the moment the real price moved. If it fell back to the order book, it would hand a manipulator exactly the lever the oracle exists to remove. Pausing — acting only on a price the engine can stand behind — keeps risk decisions anchored to data the engine trusts.

Why an oracle at all

Marking everything to the order book is simpler. Proof does not do it, for two reasons.

Manipulation resistance. If your margin and your liquidation price are read off the order book, then anyone who can move the book can move your risk. On a thin book, a handful of small prints or a single spoofed quote can walk the "price" far from fair value, and an attacker can engineer liquidations — or escape their own — by pushing the book around. Reading the risk mark from an external oracle removes that lever entirely. The oracle aggregates a broad, liquid view of the asset that no single order on Proof's book can budge, and the conditional legs are walled off from direct oracle updates so there is no side door. Manipulating the book still costs the manipulator real money against arbitrageurs, but it no longer touches anyone's margin.

Fewer liquidation cascades. Book-marked systems are prone to feedback loops: a price dip triggers liquidations, those liquidations sell into the book, the selling pushes the book lower, which triggers more liquidations. A transient wick can snowball into a cascade that has little to do with the asset's actual value. Because Proof's risk mark is the oracle, not the book, a momentary book dislocation does not by itself trigger anything. Liquidations, when they do happen, are evaluated against the external reference and are closed at that reference rather than by dumping into the book — which removes the self-reinforcing loop where each forced sale worsens the price for the next account. The result is fewer spurious liquidations and far less cascade risk from book noise alone.

The oracle-driven design depends on a feed that is live and honest, and that dependency is exactly what the freshness guards, the replay protection, and the pause-don't-guess behavior secure. The oracle removes the order book as an attack surface for risk, and the staleness machinery keeps the oracle itself just as trustworthy.

Recap

  • Underlying perpetuals are anchored to a push-based primary oracle; updates are signed, replay-guarded by strictly-increasing publish time, and processed before any trading in a block.
  • There are two marks: a risk mark (oracle-based) that drives margin, equity, P&L, liquidation, and settlement; and a funding mark (book-based) that drives funding alone. They can diverge by design.
  • The risk mark for a perp is the oracle; for a conditional perp it is the underlying's oracle (the price its winning branch settles to). Conditional legs have no oracle of their own, and direct oracle updates to them are rejected.
  • The same oracle resolves price-based events: a YES/NO claim is re-checked against the oracle and rejected on mismatch; void is the only outcome that is never auto-derived and always overrides.
  • Staleness protections on both the read and write paths (plus the replay guard) make a market pause rather than transact on an out-of-date price.
  • The oracle design exists for manipulation resistance (your risk can't be moved by moving the book) and fewer liquidation cascades (book noise doesn't trigger or feed forced selling).