Docs

Somnia Price Feeds

Somnia Price Feeds

A push-based crypto price feed on Somnia. Agent subcommittees price every tracked pair across exchanges about once a second and write the median onchain, as a spot and a mark price that any contract reads for free.

Spot and mark prices onchain, about once a second, free to read.

Somnia Price Feeds is a push-based crypto price feed. A self-re-arming onchain schedule ticks roughly once a second. Each tick sends a request to a Somnia Agents subcommittee that prices every tracked pair across exchanges, and the median is written back into contract storage. Consumers read those cells: there is no subscription to buy, no fee per read and no callback.

Two prices are published for each pair:

What it is Use it for
spot The median index price across venues, recomputed every tick Settlement, display
mark An EMA over the spot series, which damps single-tick spikes Liquidation, margin

The onchain feed is the supported surface. An indexer also serves the history for charts and monitoring, but nothing that moves value should read from it.

Addresses

PriceFeedScheduler is a UUPS proxy. Its address stays fixed across upgrades, so bind to the proxy, never to an implementation.

Network Chain ID PriceFeedScheduler
Somnia Mainnet 5031 0x1998C88D54a240b8C671493f27f58eC416b81D7F
Somnia Testnet 50312 0x7ccAE31E45693475be1e4BAa2360D6997eB2D32B

Conventions

  • Prices are unsigned and scaled by 10 ** decimals(), which is 18 on both networks today. Read decimals() once rather than hardcoding it.
  • Timestamps are Unix milliseconds, not seconds. A cell's timestamp is block.timestamp * 1000, so it is second-granular and shared by every pair written in the same tick. sourceUpdatedAtMs carries millisecond precision.
  • Cadence. Ticks fire on a fixed grid, just after each whole second. A tick delivered very late skips one grid point rather than firing twice back to back.
  • Pairs are ccxt-style strings, such as "BTC/USDC".
  • Reads never revert on stale or missing data. A pair that is untracked, removed or not yet written returns zero. You decide what is too old: the feed never invents a value. The *OrRevert helpers revert on your bound, not the feed's.

Read a price safely

latest() returns (price, updatedAtMs) and never reverts, so a consumer that forgets to check both fields will trade on a zero or an hour-old price. Use the one-call safe form instead:

// Copy IQualifiedPriceFeed into your project, or declare just the functions you call:
// the feed publishes no ABI package today.
import {IQualifiedPriceFeed} from "./IQualifiedPriceFeed.sol";

contract Consumer {
    IQualifiedPriceFeed constant FEED =
        IQualifiedPriceFeed(0x1998C88D54a240b8C671493f27f58eC416b81D7F);

    uint256 constant MAX_AGE_MS = 5_000; // 5 missed ticks tolerated

    function settle() external view returns (uint256 btc) {
        // Reverts NoPrice() if never written, StalePrice(ageMs, maxAgeMs) if too old.
        btc = FEED.latestOrRevert("BTC/USDC", MAX_AGE_MS);
    }
}

Set maxAgeMs by what a stale price would cost you. Settlement and liquidation want single-digit seconds at a one-second cadence; display can be generous. A bound below the tick cadence means nothing, because cell timestamps are second-granular.

Next steps

  • Reading prices: the four read interfaces, the quality fields and the mark hazard.
  • Feed liveness: tell a dead feed from one unpriced pair.
  • Pairs and events: the tracked pairs, the events and how to request a new pair.
  • Reference: every call and what it returns, and the historical-data indexer.

Somnia Price Feeds is built on Somnia Agents and Somnia Reactivity, the same pieces as the Somnia Oracle. Third-party feeds from Stork, DIA and Protofire also run on Somnia Mainnet: see Oracles.

Copied from somnia-oracle's price feed integration guide, until the oracle's docs manifest publishes it.Edit this page

Send feedback

Agents: POST the same to /api/feedback.