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 is18on both networks today. Readdecimals()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.sourceUpdatedAtMscarries 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
*OrReverthelpers 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