Oracle methodology

Two prices: oracle vs mark

MNX maintains two distinct prices for every market, and they answer two different questions.

The oracle price is external truth. It answers: what is this asset worth in the outside world? Stock perpetuals take it from Pyth Lazer: Pyth signs each price, and each stock perpetual's oracle on mainnet checks that signature on chain before taking a Pyth price (see Price sources). Each update is step-bounded by a maxUpdateBps limit, so a single bad print cannot move the oracle arbitrarily far in one write. Futures, H100 and TRUMP are priced by the oracle signer. The oracle price drives margin checks, liquidation eligibility, the tradable price band, and the settlement reference. Outside a stock's regular trading hours its funding is paused, and its price comes from Pyth's extended-hours prices or, when Pyth reports the market closed, from Hyperliquid within a range around Pyth's last signed price (see Trading sessions).

The mark price is internal reality. It answers: where is this asset actually trading on MNX right now? The method, book_mid_v1, takes the median of three values from MNX's own order book: the best bid inside the tradable price band, the best ask inside the band, and the previous mark. A missing side counts as that edge of the band. A bid or ask counts once it has rested: it was live 400 ms before one of the market's batches sealed, or 400 ms passed with none of them settling, so a quote that never faced a batch does not move the mark. When no quotes sit inside the band, the previous mark carries forward, clamped to the band (reported as mark source carried); a market with no mark yet starts from the oracle price. The mark price drives unrealized profit and loss and conditional-order triggers.

Why two prices? Separation is manipulation resistance. If liquidations keyed off the internal book alone, a trader could push a thin book to force liquidations; instead, liquidation eligibility runs off the externally-anchored oracle, gated by per-connector staleness limits (roughly three minutes for equity and Pyth feeds) so a stale feed halts liquidation planning rather than triggering it. Conversely, profit and loss tracks the mark so it reflects where you could actually trade on MNX, while staying within the market's price band around the oracle.

One exception: futures have no external feed at all. Their oracle is an eight-hour exponential moving average (EMA) of MNX's own order book, which counts a bid or ask only once it has rested, as the mark does. See Futures, H100 and TRUMP: the oracle signer.

Trump approval: VoteHub

The TRUMP oracle uses VoteHub's published Donald Trump job approval average, in percentage points: 36.9 means 36.9% approval.

The price is computed and signed by the MNX oracle signer, a separate service whose key exists only in a hardware security module. The signer reads VoteHub's average itself, checks it against the mean of VoteHub's raw polls, and publishes the value unchanged; the exchange only relays the signed update and cannot change the price. A value more than three points from the raw polls, or one the raw polls cannot be read to check, is not published.

MNX periodically checks for the latest usable reading dated on or before today in Pacific time. Readings must pass validation and be no more than three calendar days old. Same-day corrections are accepted without changing past trades or funding.

Failed or rejected updates leave the previous price in place. Moves greater than 2.5% per update are rejected, so the oracle can temporarily differ from VoteHub.

An outage does not automatically settle the market. If VoteHub data remains unavailable for an extended period, MNX may switch to another oracle measuring Donald Trump's job approval rating or resolve the market.

Source: VoteHub, CC BY 4.0. Approval values are used unchanged.

Price sources

MNX draws each market's oracle price from a source hierarchy that depends on the instrument type.

Equities — Pyth Lazer primary. For most listed equities, Pyth Lazer is the primary external oracle. Pyth signs every price it publishes, and each stock perpetual's oracle on mainnet, a PythAnchoredOracle, takes a Pyth price only with that signature: it checks the signature on chain, refuses a price no newer than the last one it took, and moves toward the signed price by at most maxUpdateBps per write. When Pyth reports the market closed, it also accepts the market's Hyperliquid price, but only with Pyth's signed proof of the closure and only within a range around Pyth's last signed price (see Trading sessions). The exchange relays Pyth's prices: it can delay one, but cannot forge or replay it. Hyperliquid's price carries no signature, so the contract cannot tell whether a Hyperliquid price the exchange submits is really Hyperliquid's, only that it is within that range. The Hong Kong listings Z.AI and MINIMAX use Pyth Lazer feeds 3258 and 3257, priced in HKD and converted to USD with Pyth's signed USD/HKD rate.

Crypto — Pyth Lazer only. The crypto perpetuals use Pyth Lazer crypto feeds through the same signed PythAnchoredOracle path: BTC feed 1, ETH 2, SOL 6, ZEC 66, HYPE 110 and MEGA 3205. Their underlyings trade around the clock and Pyth never reports them closed, so they have no Hyperliquid fallback: if Pyth stops publishing, the oracle holds its last price. MEGA also skips Pyth prices whose bid-ask spread is wider than 1%, and holds its last price while the spread stays wider.

Metals — Pyth Lazer, then Hyperliquid. GOLD and SILVER track spot gold and silver per troy ounce through Pyth Lazer metal feeds 346 (XAU/USD) and 345 (XAG/USD), which Pyth publishes from Sunday 18:00 to Friday 17:00 New York time with a daily break from 17:00 to 18:00. While Pyth reports them closed, the oracle takes the Hyperliquid xyz:GOLD and xyz:SILVER prices, within 25% of Pyth's last signed price, and their funding accrues only while Pyth reports the market open.

Hyperliquid secondary fallback. Every stock perpetual listed on mainnet except TLT and SMH has a reviewed Hyperliquid price for when Pyth reports its market closed; those two have none, so their price holds while Pyth reports them closed. The Hyperliquid price must stay inside the market's reviewed floor and ceiling and within 20% of Pyth's last signed price (25% for Hong Kong stocks). That primary anchor is fixed while Hyperliquid is in use, preventing accepted fallback prices from gradually moving the reference. A missing anchor or one older than 14 days freezes the oracle; Hyperliquid never bootstraps the anchor.

Index and pre-IPO markets. The H100 GPU market takes its price from the SemiAnalysis GPU index rather than an equity feed. Pre-IPO valuation futures have no external price feed at all: before settlement, prices are set entirely by trading on MNX's internal order book, and the oracle price used for margin checks, liquidation eligibility, and the tradable price band is an eight-hour EMA of that book. For both, the oracle signer section below gives the method.

Pre-launch perpetuals. A perpetual for a token or a company's shares that Pyth does not price yet is priced like a future until Pyth publishes a feed for it: its oracle price is the eight-hour EMA of its own order book, computed by the oracle signer, its funding is zero and its leverage is 1×. Once Pyth has a feed, MNX points the market at a new Pyth oracle that starts at the market's current oracle price and then moves toward Pyth's price by at most 2.5% per update, about once a minute: closing a gap of 2× takes about half an hour, and one of 10× about an hour and a half. Trading continues throughout, and marks and fills stay inside the tradable band around the moving oracle. Funding starts once the oracle reaches Pyth's price. If the market never converts, its terms set a date and the price it settles at.

Polymarket-guarded binary futures. The binary futures DPREZ and RSENATE26 use the same eight-hour EMA, kept from moving away from the matching Polymarket market's price: a range from 0.10 below its bid to 0.10 above its ask, each measured as the depth-weighted price of the first 1,000 shares on that side. After ten minutes without a usable Polymarket reading, this guard switches off until readings return; the oracle signer section gives the details.

Futures, H100 and TRUMP: the oracle signer

Who computes the price. The oracle signer, a separate service that MNX runs, computes the oracle prices of numeric futures, binary futures, the H100 market and the TRUMP market (see Trump approval) from public data, and signs each with a key that exists only in a hardware security module (Google Cloud HSM). Updates the signer priced are recorded with method oracle_signer_v1. It prices a pre-launch perpetual exactly as it prices a numeric future until the market converts to its Pyth feed.

Each update (futures). Once a minute the signer reads the latest on-chain oracle price a and forms a sample s from the market's public order book: a moved up to the best bid if that bid is above a, or down to the best ask if that ask is below a, and otherwise a itself. Only bids and asks inside the tradable price band count, and only once they have rested: a bid or ask was live 400 ms before one of the market's batches sealed, or 400 ms passed with none of them settling. Reduce-only bids and asks count only what they can close: an account's reduce-only orders on a side share its position, best price first, after its ordinary orders on that side at the same or a better price. A missing side counts as that edge of the band, so it never pulls the price, and an empty book gives s = a. (When the best bid is above the best ask, as happens for a moment before each batch clears, the two are swapped first.) The new price is p = a + (s − a) × w, where w is the time since the previous update, counting at most 60 seconds, divided by eight hours: 1/480 of the gap at the normal one-minute pace. Missed minutes are not caught up. The result is an eight-hour exponential moving average kept on chain: the latest oracle price is the average. Moving it therefore takes a bid or ask that stays where anyone can trade against it; a trade alone does not move it.

The book reading. The signer reads each market's public book (markets/<symbol>/book) once a minute, at a random second, and uses a reading for up to two minutes, and only if the book was no more than five seconds behind the exchange when read.

Speed limit. The signer never signs a price that moves faster than an eighth of the band per hour: in each direction, the distance from the oracle price to that edge of the tradable band, divided by eight, per hour. At a ±20% band that is 2.5% of the price per hour, up or down. For binary futures the band is measured toward each payout bound, so their prices stay inside the payout range.

Polymarket brake (DPREZ and RSENATE26). The signer reads the matching Polymarket market every 30 seconds. The range runs from 0.10 below Polymarket's depth-weighted bid to 0.10 above its depth-weighted ask, each walked over the first 1,000 shares, and a reading counts only when both the best and the depth-weighted spreads are no wider than 0.05. A sample counts only if it lies no farther outside the range than the current price, so the book cannot move the price out of the range, and outside it the price moves toward the range only as the book and the speed limit allow; a sample that does not count leaves the price unchanged for that minute. With no usable reading under two minutes old the price is published unchanged; ten minutes after the last usable reading the brake switches off, and the market follows its own book until readings return.

H100. The sample is SemiAnalysis's latest H100 index measurement, which the signer reads every five minutes and uses while it is under 110 minutes old (SemiAnalysis stamps each measurement on the hour and publishes it about 35 minutes later). A measurement stamped more than five minutes in the future is rejected, and one older than the latest already used is ignored. The price moves toward the measurement by at most the speed limit, 2.5% per hour at H100's ±20% band, and updates every minute.

When an input is missing. Without a usable book reading, the signer keeps publishing the current price unchanged, and stops twelve minutes after the last usable reading. Without new updates, liquidations pause once the oracle price is three minutes old and trading pauses once it is 15 minutes old; both resume with the next update. For H100 the input is its measurement: once the latest is 110 minutes old the price is published unchanged, and publishing stops ten minutes later; its liquidation and trading limits are both 75 minutes. If the signer cannot sign at all (it is down, its key service fails, or fewer than two of its blockchain data sources respond and agree), updates stop at once, with the same pauses.

Markets that open with an auction. A future listed with an opening auction starts at a listing price MNX chooses, and its public order book stays empty until it opens, so the signer keeps the oracle there. When the auction closes, the signer moves the oracle to the auction's price in steps of at most the oracle's own update limit (2.5%, at most one step every 45 seconds), but only while the market has never traded, which it checks on chain. If orders are cancelled before the opening batch, the exchange plans the price again and the signer heads for the new one; while a result is held, the oracle stays where it is. The market opens at the auction's price; from then on the signer follows the order book as above.

Anyone can check a futures price. Its inputs are public: the on-chain oracle answers and band parameters, the public order book, and for DPREZ and RSENATE26 Polymarket's public order books. Anyone watching them can check that each published futures price follows these rules.

Liquidation and price staleness

Liquidation eligibility is evaluated off the oracle price. The liquidation planner reads the on-chain oracle price for each market (not the mark price) when determining margin health, liquidation eligibility, and the tradable price band. The auto-deleveraging (ADL) planner uses the oracle price, unrounded, only to choose and rank the positions it deleverages; each leg executes at the bankrupt account's bankruptcy price (see the three stages below).

The oracle write is step-bounded by maxUpdateBps. Every on-chain setPrice submission is checked against the oracle's per-update bound. If the target price would move the oracle by more than maxUpdateBps (a limit expressed in basis points, where one basis point is one hundredth of a percent) in a single update, the submitted price is stepped to the bound instead, and the bounded submission is recorded with method max_update_bounded_v1 and an explicit reason ("bounded to … by maxUpdateBps=…"). A single anomalous external print therefore cannot instantly move liquidation thresholds or the tradable band; large moves are absorbed over successive one-minute updates. Markets the oracle signer prices are the exception: a signed price beyond the bound is never rewritten, and the update is skipped instead.

On PythAnchoredOracle markets, the bound is enforced by the contract itself. Instead of a pre-stepped setPrice, the updater submits Pyth Lazer's raw signed update. The contract verifies the signature against the trusted Pyth signer, derives the price target and the market session from the signed payload, and clamps its own answer to at most maxUpdateBps per write, moving toward that target — the same stepping math, relocated on-chain. While Pyth reports the session closed, the contract accepts the Hyperliquid secondary only alongside a fresh signed proof of the closed session, bands it against the signed closing print, and steps it under the same bound. Every accepted write must also carry a strictly newer Pyth payload timestamp than the last, so an already-consumed update can never be replayed. A compromised updater key can therefore delay the oracle, but it cannot forge a live price target or re-serve an old payload. During a signed closed session, it can choose a Hyperliquid target only inside the contract's band around the signed close, and each write remains capped by maxUpdateBps.

Every connector type carries a liquidation-price max-age gate. The freshness limits are:

ConnectorMax age for liquidation
pyth (Pyth Lazer feeds)3 minutes
semianalysis (H100 index)1 hour 15 minutes
polymarket (Polymarket-guarded binary futures)3 minutes

Each limit applies to every market that uses that connector type. Markets with no external price connector use the 3-minute default.

Stale prices pause liquidations rather than trigger them. If a market's price exceeds its staleness gate, liquidation planning for that market is skipped entirely and eligibility checks fail with reasons such as oracle_price_stale. The system never liquidates against a number it cannot vouch for. This is also how a closed or stuck feed is made safe: when a Pyth session is closed (e.g. a Hong Kong equity outside trading hours) with no Hyperliquid fallback available, the updater stops writing, so the on-chain price ages past its staleness gate and liquidation pauses rather than running against an unrefreshed value. A stuck Hyperliquid fallback is handled the same way: the updater detects that Hyperliquid's price and order book have both stopped changing and stops re-submitting the price, so its on-chain timestamp ages out instead of looking perpetually fresh.

Liquidation runs in three stages. A position below its maintenance requirement is first closed with reduce-only orders on the book while its equity is at least two-thirds of that requirement. With positive equity below two-thirds, a backstop vault takes over the remaining position and keeps the remaining margin as its fee. Once equity is zero or negative, auto-deleveraging (ADL) applies. The planner ranks the positions on the other side of the market at the oracle price, unrounded and after pending funding: a profitable position scores its profit as a share of its entry value times its leverage (notional divided by equity), so the most profitable, most leveraged positions come first, and a position at a loss ranks after every profitable one. It matches the bankrupt account against the highest-ranked positions, one leg each. Every leg executes at the bankrupt account's bankruptcy price, the price at which its equity after funding is zero, not at the oracle price. In a large price gap that price can be far from the oracle and worse than a counterparty position's own entry price, so a deleveraged position can close at a loss. ADL applies to both user accounts and child vaults. A trader whose position ADL reduces or closes, or a backstop vault takes over, gets a notice in the app, at the time or on their next visit, and an email unless they turned liquidation alerts off, and their portfolio's Liquidations tab lists the event; the notice and the row don't name the bankrupt account.

Trading sessions

A stock perpetual's funding follows its stock's regular session: it accrues during regular trading hours (U.S. hours for U.S. stocks, Hong Kong hours for Z.AI and MINIMAX) and is paused outside them. The price keeps updating at every hour:

  • In pre-market, after-hours and overnight trading, Pyth still signs prices, and the oracle follows them. Pyth publishes no overnight prices for MRNA and URNM, so from 20:00 to 04:00 New York time they are priced as they are while the market is closed.
  • When Pyth reports the market closed, as over a weekend or a holiday, the oracle takes the stock's Hyperliquid price instead. The contract accepts it only with Pyth's signed proof of the closure and only within 20% of Pyth's last signed price (25% for Hong Kong stocks), and each update moves the price by at most 2.5%. The Hyperliquid price is not used if Hyperliquid's price and order book for the stock have both stopped changing for 10 minutes, or if it falls outside that range; the oracle then holds its last price. TLT and SMH have no Hyperliquid price, so theirs holds while Pyth reports them closed.
  • URNM, Z.AI and MINIMAX skip Pyth prices whose bid-ask spread is wider than 1%; while the spread stays wider, the price holds.
  • For Hong Kong stocks the USD price also uses Pyth's signed USD/HKD rate. While the stock trades, the rate must be at most three minutes old; while the stock is closed, at most six hours; when Pyth signs the currency market itself closed, as over weekends, the last rate carries forward.

Crypto perpetuals have no closed session: their price updates and their funding accrues 24 hours a day, every day, including weekends and U.S. market holidays.

A price that stops updating pauses liquidations once it is three minutes old and trading once it is 15 minutes old. At every hour, trades fill only within the market's make/take bounds, its tradable price band around the oracle price: currently ±5% for stock, metal and crypto perpetuals, and ±10% for MEGA.