Oracles, mark prices and robust price indices
Validators publish perp oracle prices every 3 seconds; the mark price used for margin and liquidation is a median that no single book or venue can move.
Every perp has two reference prices, and neither is its last trade. The oracle price comes from spot venues and drives funding. The mark price mixes the book with outside prices and drives margin and liquidation. Both are medians, to minimise the risk of manipulation.
The mark is a median of three inputs
Section titled “The mark is a median of three inputs”Say the inputs read 3,000, 3,012 and 2,998. The mark is the median, 3,000. If a wick on the book lifts input 2 to 3,050, the median of 3,000, 3,050 and 2,998 is still 3,000.
External perp mids are weighted Binance 3, OKX 2, Bybit 2, Gate IO 1, MEXC 1. The mark also sets TP/SL triggers and unrealised profit and loss, and updates with each oracle publication. The EMAs are time-weighted; for a new sample arriving t after the last update:
numerator = numerator * exp(-t / 2.5 minutes) + sample * tdenominator = denominator * exp(-t / 2.5 minutes) + tema = numerator / denominatorWhat this means for you. A book wick alone won’t liquidate you, but an external move the book has not followed can.
Oracle prices come from spot venues
Section titled “Oracle prices come from spot venues”Every 3 seconds each validator takes a weighted median of spot mids per perp asset:
| Source | Weight |
|---|---|
| Binance | 3 |
| OKX | 2 |
| Bybit | 2 |
| Kraken | 1 |
| KuCoin | 1 |
| Gate IO | 1 |
| MEXC | 1 |
| Hyperliquid spot | 1 |
Assets whose main spot liquidity is on Hyperliquid (HYPE, in the docs’ example) exclude external sources until those are liquid enough; assets liquid elsewhere (BTC) exclude Hyperliquid spot. Most oracles are in USDT against USDC collateral, unconverted (quanto). PURR and HYPE use USDC oracles, as their most liquid spot market is Hyperliquid’s.
HIP-3 deployers supply their own prices
Section titled “HIP-3 deployers supply their own prices”On a HIP-3 dex the deployer, or an oracleUpdater it names, pushes setOracle: oracle prices, up to two lists of mark inputs, and external perp prices that guard against sudden mark deviations. The mark is the median of those mark inputs and the local book price, median(best bid, best ask, last trade), so it is partly deployer supplied.
Beyond the table’s limits, pushes are expected every 3 s even without change, and no mark update may take open interest to 10 times its cap. The 10 s stale fallback is to the local book price, and the docs say not to rely on it. They also warn that most price indices make poor perp oracles and that a deployer is slashable for every market on its dex (operating a perp dex).
The protocol clamps the deployer’s feed, but its quality is the deployer’s responsibility.
Other prices built on these
Section titled “Other prices built on these”- Recurring HIP-4 outcomes settle on the mark, interpolated linearly between the updates either side of settlement (settlement).
- Portfolio margin prices borrowed assets at a median of spot, mark and oracle price.
- Orders too far from the oracle fail as
oracleRejected.
The numbers
Section titled “The numbers”| Parameter | Value |
|---|---|
| Oracle publication | every 3 seconds, by validators |
| Final oracle price | stake-weighted median of validator submissions |
| Mark price inputs | 3, plus a 30 s EMA when exactly 2 exist |
| EMA of mid minus oracle | 150 s (decay constant 2.5 minutes) |
HIP-3 setOracle spacing |
at least 2.5 s; expected every 3 s |
| HIP-3 mark move per update | at most 1% from the previous mark |
| HIP-3 price clamp | 10x the start-of-day value |
| HIP-3 stale mark fallback | after 10 s without an update |
| HIP-3 cross margin review | any externalPerpPx move over 50% from the start-of-day price |
| Borrow oracle price | median(HL_spot_USDC_price, HL_perp_mark_price * USDT_USDC_oracle, HL_perp_oracle_price * USDT_USDC_oracle) |
Reading and pushing prices from code
Section titled “Reading and pushing prices from code”metaAndAssetCtxs and activeAssetCtx carry markPx, oraclePx, premium and impactPxs; read them; don’t rebuild the mark. Precompiles 0x806, 0x807 and 0x808 return mark, oracle and spot price as a uint64: divide perp prices by 10^(6 - szDecimals), spot by 10^(8 - baseSzDecimals).
For the HIP-3 push, sort every list by coin before signing. markPxs is a list of rounds of pairs, and externalPerpPxs must include every asset on the dex.
{ "type": "perpDeploy", "setOracle": { "dex": "<dex>", "oraclePxs": [["<coin>", "101.5"]], "markPxs": [[["<coin>", "101.6"]]], "externalPerpPxs": [["<coin>", "101.4"]] }}Details that catch integrations out
Section titled “Details that catch integrations out”- The oracle’s venues (seven spot plus Hyperliquid spot) differ from the mark’s (five perp, no Kraken or KuCoin).
- The
binaryPricetemplate settles on an N-second TWAP, not one mark print. - A precompile mark read is from when the EVM block was built; a CoreWriter action on it executes later, at a newer price.
For what happens at the mark, see Leverage and liquidation. For differently built oracles, see Hyperps and index perpetuals.