Why oracles matter

Price markets use oracle prices to open positions, close positions, compute health, and check liquidation. The oracle is the source of truth for the market price used by the contract. The app display can lag, fail, or differ from the price that lands in your transaction.

What the oracle price means

Each market uses a single oracle price — the tracked asset valued in the market’s collateral token, normalized to a common 1e18 scale. There is no separate “mark price” and “index price”: the same oracle price is used to open, value (mark), close, compute health, check liquidation, and settle. When that price moves, everything moves with it.

Supported oracle patterns

Deployments may use Chainlink, Pyth, or onchain TWAP-style sources depending on the market. Some Pyth-backed actions require a price update in the same transaction and an ETH fee to pay for that update. If the price update data is missing or stale, the transaction can fail. Some markets can also use adapter contracts that normalize different price sources for the pool. The configured adapter matters more than the brand of oracle shown in the app, because the adapter defines validation and freshness checks. Chainlink-style feeds can fail when the answer is zero or negative, when the reported round is stale (older than the latest round), when the price is older than the market’s staleness window, or when it falls outside the market’s configured price bounds. Pyth markets use a pull-update flow, so the app or router refreshes the feed before opening, closing, or liquidating. Pyth staleness is hard-capped at 60 seconds — a Pyth-backed market needs a price update no older than 60s, so the feed has to be refreshed in or near the same transaction as your trade. Even after a fresh update, a Pyth read can still be rejected if the feed’s confidence interval is too wide relative to the price (each market sets a maximum confidence). A too-wide confidence reverts the transaction, so a successful price update does not guarantee a successful trade. DEX-backed markets can read onchain spot or TWAP adapters. TWAP windows can reduce short-term manipulation risk, but they still depend on pool liquidity, window length, and adapter configuration.

Stale or invalid prices

Oracle contracts can reject stale, zero, negative, or unreasonable prices. A price of zero, below a lower sanity floor, or above an upper sanity bound is rejected — the floor and the cap are both tunable per market. For Chainlink and DEX markets a price older than 10 minutes is treated as stale by default (tunable per market). Pyth markets are stricter: their staleness window is hard-capped at 60 seconds and cannot be raised above that. When a price is rejected, opening, closing, and liquidation are all unavailable until the oracle is updated — in a stressed market you may be temporarily unable to close. DEX adapters do not apply a time-based staleness check the way Chainlink and Pyth do — they read the current onchain pool state. A TWAP window (at least 30 minutes) resists short-term manipulation, but it is not a freshness guarantee, and a live read is still risky if the underlying pool is thin or manipulated.

Oracle changes

Oracle changes are timelocked, and there are two separate flows, each a 24-hour propose-then-accept process:
  • Swapping a market’s oracle is controlled by a risk role on the pool, with a 24-hour delay before the new oracle can be accepted. Acceptance re-checks that the candidate still matches the market and collateral and is still the authorized oracle, so a proposal revoked during the delay cannot be installed. When positions are open, the swap is also bounded: if the new feed’s price differs from the old feed’s by more than 2%, or the old feed is unreadable at all, the swap can only complete after a guardian has put the market into reduce-only mode. Recovering from a broken oracle is therefore an explicit two-role action, and reduce-only stays on until governance clears it.
  • Changing an oracle’s underlying data source (for example the upstream feed) is controlled by the oracle’s owner, with its own 24-hour delay. The new source must be pre-approved, and acceptance compares the old and new source prices in the same block, reverting above a 2% difference. This path never skips the comparison, so it only supports a healthy-to-healthy switch.
No one can set an arbitrary price directly; a source can only be swapped through these timelocked flows.

Scheduled market hours

Most markets trade around the clock. A market can instead be bound to a trading calendar (weekly sessions, weekends, and holidays), for example to track a stock index. On such a market:
  • While the market is scheduled closed, the oracle keeps serving the last valid price (a frozen price), and the pool blocks new risk: you cannot open a position or add liquidity. Closing, reducing leverage, adding margin, liquidation, removing liquidity, and claiming settlement all stay available.
  • Right after each scheduled open there is a fixed reopen grace window (set per market) during which new risk is still blocked.
  • The frozen price is only served up to a staleness cap. If the feed stays dead past that cap, price reads revert until the feed recovers.
  • Funding, on markets that enable it, keeps accruing against open positions while the market is closed.
Markets without a trading calendar are unaffected and trade 24/7 as long as the oracle is live.

Sequencer availability on L2 markets

On L2 markets the oracle also checks that the chain’s sequencer is alive before any price is used; this guard is mandatory on Base mainnet. While the sequencer is down, and for a grace period after it restarts (one hour by default), every price read reverts, so opening, closing, adding margin, reducing leverage, liquidation, and LP actions are all temporarily unavailable. Collateral already owed to you can still be withdrawn with claimSettlement.

User checklist

  • Confirm the market name and oracle source.
  • Check whether the app is asking you to pay a Pyth update fee.
  • Avoid signing if the displayed price looks stale or inconsistent.
  • Recheck position health after large oracle moves.