Configuration keys
An oracle is keyed by token or intermediate reference, rather than by hub or spoke:AssetOracle:
Price sources
An LP source must be the only source on its key. Nested
Scaled.quote and LP
leg references are bounded by MAX_RESOLUTION_DEPTH = 3; exceeding the bound
returns #229. A reference cycle returns #225 OracleCycleDetected.
Feed providers
FeedSource contains provider, decimals, and max_stale_seconds:
Reflector asset references accept
Stellar(Address) or Symbol(Symbol); a
String reference returns #204. A direct Reflector feed must be USD-quoted.
A Reflector factor in Scaled must instead quote the Stellar token named by
Scaled.quote = Token(address). A USD-quoted factor or Ref quote fails with
#220.
FeedNature distinguishes market observations from fundamental valuations. It
affects staleness handling and the leg-age comparison described below.
The XOXNO oracle aggregates authenticated signer submissions into a median under
a configured quorum. The quorum applies across stored submissions; each submit
call authenticates one registered signer. Submission age and relative skew
control eligibility. See XOXNO oracle ABI
for submission, aggregation persistence, and administration.
A configured feed id does not prove that an observation is available or establish
its upstream pricing method. Match the provider address and feed id to the oracle
configuration and read a usable quote before integrating an asset.
Composition and tolerance
A two-source oracle requires both legs to pass resolution and freshness checks. It serves their midpoint,(a + b) / 2, only when they agree within tolerance.
One readable leg is incomplete and fails with #205 UnsafePriceNotAllowed;
there is no single-leg fallback.
Agreement compares the larger price to the smaller, expressed as a BPS ratio,
against upper_ratio_bps. The configured upper bound must be between
10_150 and 12_500.
Governance expresses this as excess tolerance above BPS = 10_000, from 150
through 2,500 bps. Invalid tolerance returns #208.
At configuration, lower_ratio_bps must equal
half_up(BPS * BPS / upper_ratio_bps). The price-time comparison uses the upper
ratio; comparing larger to smaller covers either direction of deviation.
A single-source oracle serves its accepted leg directly. It still checks
freshness, positivity, and sanity, and requires a tighter sanity band:
MAX_SINGLE_SOURCE_SANITY_BAND_BPS = 1000. Two sources with identical provider
trust sets also receive this cap. LP oracles use
MAX_LP_SANITY_BAND_BPS = 8182. An overly wide single-source band returns #226.
For two-source independence, RequireDisjoint forbids shared provider contracts.
AllowShared requires the declared shared set to match the actual set exactly,
or configuration fails with #232 IndependenceNotDeclared.
Freshness and sanity
If future-dated observations leave no readable leg, resolution returns
#210 NoLastPrice. In a dual-source oracle, one remaining fresh leg gives
#205, while a stale remaining leg gives #206.
The sanity band must be at least MIN_SANITY_BAND_BPS = 50 wide and stay within
MAX_REASONABLE_PRICE_WAD, equal to $1 billion per whole token. Sanity is a
pass/fail check on the resolved price; it never clamps an out-of-range value.
Failure behavior
Every valuation-dependent mutation needs a complete price snapshot. Provider failure, stale observations, disagreement, or invalid sanity checks revert the operation. This also applies to risk-decreasing actions when they need valuation. There is no per-flow permissive mode or TWAP-to-spot fallback. Choose the read method by its failure behavior:price_spread reports source divergence, not a confidence interval around the
midpoint. Dashboards can use quotes to report an individual market failure.
Transaction logic must require a valid price before using it.
PriceFeedRaw contains price_wad, asset_decimals, and timestamp.
PriceStatus contains final_wad, primary_wad, secondary_wad,
price_timestamp, stale, deviation, valid, and error_code: Option<u32>.
The price timestamp uses the older accepted leg.
The controller’s get_market_indexes_detailed includes equivalent diagnostics
under price_wad, primary_price_wad, anchor_price_wad, stale, deviation,
valid, and error_code.
Price-aggregator interface
Read signatures are:
A non-LP configuration probe rejects configuration failures but may accept a
stale, deviating, or out-of-band observation. LP admission requires a usable
price. Dependent keys receive structural validation, so a successful
configuration change does not establish that dependent prices are usable.
The three configuration methods emit
UpdateAssetOracleEvent on
["config", "asset_oracle"] with the full resulting configuration.
Use the Oracle disruption runbook
for diagnosis and repair, and Governance for
scheduling changes.
