Oracle·EVM · Solana · Sui · Aptos · Multi-chain
Stork
Ultra-low-latency pull oracle built for perp DEXs and other latency-critical DeFi. Aggregators refresh signed temporal-numeric values every ~500ms; subscribers stream off-chain via WebSocket and post updates to the on-chain Stork contract whenever their app needs a fresh price.
- 01perp DEXs and high-frequency derivatives
- 02rapid asset listings (sub-second quotes from launch day)
- 03RWA price feeds with publisher attestation
- 04any market where price age matters in milliseconds, not minutes
- 05multi-chain (EVM, Solana, Sui, Aptos) low-latency feeds
- pnpm add @storknetwork/stork-evm-sdk
- forge install Stork-Oracle/stork-external
| Variable | Scope | Description |
|---|---|---|
| STORK_CONTRACT_ADDRESS | Client | Stork verifier contract address (`IStork`) on the target chain. See docs.stork.network/resources/contract-addresses. |
| STORK_WS_URL | Server | Stork WebSocket endpoint for streaming signed updates (e.g. `wss://api.jp.stork-oracle.network/evm/subscribe`). Requires API key for production. |
| STORK_API_KEY | Server | Stork API key issued by Stork Network for the WebSocket / REST subscription tier. |
Stork is a PULL oracle. Off-chain, subscribe to the Stork WebSocket for the asset IDs you need; each message is a `TemporalNumericValueInput` containing the signed `(timestampNs, quantizedValue)` plus publisher signatures. When your app is about to settle a trade, post the update on-chain by calling `IStork(stork).updateTemporalNumericValuesV1{value: stork.getUpdateFeeV1(updates)}(updates)` — the contract calls `verifyStorkSignatureV1` per update and only stores values fresher than the current state. Then read with `stork.getTemporalNumericValueV1(bytes32 id)` and validate `block.timestamp * 1e9 - tnv.timestampNs <= maxAgeNs`. Import `@storknetwork/stork-evm-sdk/IStork.sol` + `StorkStructs.sol` for the interfaces.
- ⚑Pull oracle: every consuming tx that needs a fresh price MUST call `updateTemporalNumericValuesV1` first (with the matching `msg.value = getUpdateFeeV1`); reading without an update returns the LAST stored value which may be milliseconds-old or hours-old depending on prior traffic.
- ⚑Always staleness-check `tnv.timestampNs` (NANOSECONDS, not seconds) against `block.timestamp * 1e9` — Stork uses nanosecond resolution; treating it as seconds is a 1e9 off-by-magnitude error that will pass every freshness check.
- ⚑Quantized value scaling: Stork returns `int192 quantizedValue` with a per-asset quantization (often 1e18 but not guaranteed) — always read the asset's quantization spec from the docs; mixing quantizations across assets in the same market causes orders-of-magnitude bugs.
- ⚑Network fees: each on-chain update pays a per-update fee (`getUpdateFeeV1` returns wei); under-paying reverts and over-paying is NOT refunded. Pull updates also pay normal calldata gas (signature verification is non-trivial — batch updates per tx).
- ⚑Signature set rotation: Stork can rotate publisher keys; pinning a hardcoded public key in your verification path will break on rotation — always use the on-chain `verifyStorkSignatureV1` rather than DIY verification.
- ⚑WebSocket subscriptions are paid / API-keyed: the public docs API is rate-limited and not for production trading — provision a dedicated subscription before launch.
- ⚑Per-chain contract addresses differ; Solana/Sui/Aptos use platform-specific receivers and a different SDK — the EVM `IStork` interface does NOT translate to non-EVM chains.