Skip to content

Oracle Configuration

Mihai edited this page Sep 6, 2026 · 1 revision

Oracle Configuration

The price aggregator is a governance-owned contract that assembles token prices from governed source configurations. A token's configuration is shared across hubs and spokes; named reference keys support intermediate values. This page explains source admission, composition, and operator responsibilities. See Oracle System for transaction behavior and Governance and Timelock for authority.

Composing an asset price

Each registered key has an AssetOracle: one or two sources, decimal information, freshness limits, a tolerance band, a dependency-independence policy, and minimum and maximum accepted prices. Token prices are USD per whole token in WAD precision (10^18). Each source can be:

Source Valuation
Direct feed A provider's observation, normalized to WAD.
Scaled feed A bounded factor multiplied by the resolved USD price of another key. For example, units of an underlying asset per receipt token multiplied by USD per underlying asset.
Aquarius constant-product LP A share of fair pool value, using reserves, resolved constituent prices, and total LP shares.
Aquarius stable LP A share of the two-token StableSwap invariant, valued at the lower constituent price.

Scaled and LP sources resolve their dependencies through the same price checks. A composition cannot contain a cycle, and at most three nested dependency steps are allowed. Repeated reads reuse values within the current invocation; this cache does not carry a previous transaction's price into a new one.

An LP configuration has exactly one top-level source. It still depends on both constituent prices. The aggregator checks the pool kind, share-token identity, ordered constituent tokens, token decimals, positive reserves and share supply, and a configured minimum fair pool value. Stable pools also need a supported amplification coefficient. These checks constrain valuation; they do not establish that an arbitrary pool contract is trustworthy.

Feed providers and denomination

Provider Read method Relevant checks
Reflector SEP-40 spot or Twap(records) Declared decimals must match the provider. A direct feed must quote USD; a scaled factor must quote the exact token identified by its quote key. Resolution and history must support the configured window.
RedStone A feed ID on a multi-feed contract Fixed 8-decimal price width; package and write timestamps both matter.
XOXNO oracle A feed ID using the RedStone-compatible format Decimals must match the oracle, and the configured source age budget must cover its maximum submission age.

Reflector's Twap mode computes an equal-weight arithmetic mean of accepted observations. It is not weighted by elapsed time. Admission requires 3–12 requested records; a read requires the complete requested window, allows at most one extra returned record, and rejects incorrectly ordered or insufficiently spaced timestamps. Freshness is measured from the oldest accepted observation.

RedStone and XOXNO feeds are declared either Market or Fundamental. Market feeds follow traded prices; fundamental feeds can represent a slower quantity such as NAV or an exchange ratio. The declaration affects admission and age-spread checks. It is a governance assertion, not a classification the aggregator proves. Feed IDs and factor denomination must therefore be selected correctly.

Agreement, independence, and smoothing

With one source, its usable value becomes the result. With two, both must be readable, fresh, and within tolerance. The accepted result is their midpoint, rounded down in WAD units. There is no fallback to a surviving leg.

Tolerance compares the larger price with the smaller, independent of source order:

round_half_up(max(price_a, price_b) × 10,000 / min(price_a, price_b))
    <= 10,000 + tolerance_bps

The configured tolerance must be 150–2,500 BPS (1.5%–25%). Agreement within that band bounds disagreement; it does not prove either price is economically correct.

For each source, admission collects every transitive feed-provider contract address. Two-source configurations choose one policy:

Policy Requirement
RequireDisjoint The two provider-address sets share no address.
AllowShared A non-empty declared set exactly matches the addresses shared by the two sources.

Provider names alone do not establish independence. Two contracts served by the same operator or upstream exchange can still fail together. Explicit sharing also means a common dependency can move both values without triggering disagreement. Operators must evaluate those economic and administrative dependencies separately from the on-chain address check.

For a non-LP configuration, at least one complete source must contain no unsmoothed Market component anywhere in its dependencies. Reflector spot, Market-classified RedStone/XOXNO feeds, and nested LP valuations count as unsmoothed components. Reflector TWAP and Fundamental feeds satisfy their respective local admission condition. This rule is independent of source order: either source can supply the qualifying path. A single Market spot feed is rejected even with a narrow sanity band; a single Fundamental spot feed can qualify. LP configurations waive the top-level smoothing and tolerance requirements and apply their separate admission checks.

Sanity bounds and freshness

Every usable final price must be positive and fall inside its configured sanity interval. The interval must have positive, ordered endpoints, a midpoint-relative half-width of at least 50 BPS, and an upper price no greater than $1 billion. Its width is measured as:

half_width_bps = (max_price − min_price) × 10,000 / (max_price + min_price)

A non-LP single-source configuration is capped at a 1,000-BPS half-width (10%). The same cap applies to two sources with identical transitive provider-address sets. Two sources with different sets are exempt from this cap, even when explicitly declared sharing remains. LP configurations instead have an 8,182-BPS cap. The actual configured interval still applies on every price read.

Each feed has its own maximum observation age, and each asset has an overall age envelope. These inputs must be between 60 and 93,600 seconds (26 hours). Out-of-range inputs are rejected, not clamped. No transitive feed budget may exceed the containing asset's envelope.

At read time:

  • An observation is stale when its age exceeds the applicable budget. Scaled prices use the earlier factor/quote timestamp; LP prices use the earlier constituent timestamp.
  • A timestamp more than 60 seconds ahead of ledger time makes an observation unusable. For multi-feed data, both package and write timestamps are checked, and the earlier timestamp determines age.
  • Two Market sources may differ in observation time by at most 3,600 seconds. A Fundamental source exempts the pair from this extra age-spread test, but not from either source's age limit. For a scaled source, the factor's declared nature determines this classification.
  • Missing observations, invalid normalization, failed dependencies, excessive disagreement, and sanity violations cannot become valid lending prices.

Governance and admission

Governance schedules asset-oracle configuration and tolerance changes against the price aggregator. Token-key decimals are resolved from the token contract; named references use zero asset decimals. At execution, the aggregator validates source structure, dependency depth and cycles, staleness envelopes, independence, smoothing, tolerance, and sanity bounds, then performs provider-specific attestation.

A non-LP configuration receives a probe that rejects configuration failures while allowing temporary market-condition failures. Admission therefore does not guarantee that its price is usable immediately. LP admission requires a fully usable price. Changing a key also structurally revalidates every registered dependent; it does not perform new live provider attestations for all dependents.

Tolerance updates validate the new tolerance and probe the configured key; LP configurations do not accept tolerance updates. The ORACLE role can immediately narrow an existing sanity interval. It cannot widen or shift it beyond the current interval; widening requires timelocked oracle reconfiguration. See Governance and Timelock for authority and scheduling.

XOXNO oracle trust boundary

The XOXNO oracle has its own constructor-supplied administrator and registered signer set. Each submission authenticates one signer. A new aggregate requires a quorum of fresh submissions clustered within the configured timestamp-skew window, and uses the lower median of those prices.

An ordinary submission that misses quorum retains the previous aggregate until freshness checks reject it. Owner-triggered recomputation clears a feed that lacks quorum. Honest participation must be assessed within the accepted cluster; a threshold above half the registered signers alone does not prove an honest median when signers are absent.

The lending aggregator's freshness, agreement, and sanity checks remain a separate consumer boundary. They cannot remove compromised signer administration, correlated upstream errors, or manipulation that stays inside configured bands. Selecting trustworthy contracts, economically independent data, defensible Fundamental classifications, and appropriate budgets remains a listing responsibility. See Security for the wider threat model.

References

Clone this wiki locally