Skip to content

Oracle risk

The OracleAdapter reads the closing print — the last round published no later than closeTs + closeGrace (5 minutes) and no earlier than closeTs − maxPreCloseLag (30 minutes) — cross-checks a backup feed within 3%, defers when unsure, and gives governance a delayed, evented override only after 72 hours. These rules remove after-hours prints, single-round glitches and silent failure.

Keeper timing is not a risk. The selection depends only on the feed’s round history at or before the grace end, and observe is rejected until the grace has elapsed, so the observed round is the same whether the keeper calls one second after the grace or hours later, and whatever the feed prints in between (audit finding M-ORACLE-WINDOW, fixed). No party can choose a favourable price by timing the call.

Residual riskEffectMitigation
Feed reports a wrong close within tolerance (e.g. a 2% error)Wrong coupon or, near the barrier, wrong settlementBackup feed deviation check catches only disagreements above maxDeviationBps
Both feeds share an upstream data source that is wrongSame as above, undetectedChoose feeds with independent sources where available
Feed publishes nothing inside the close window (idle, outage, unregistered holiday)Observation deferred and cannot recover on its own: later rounds never qualifymaxPreCloseLag is set to the 24 h heartbeat on deployment so a live Chainlink feed always qualifies; a PythProFeed backup lets anyone post an exact closing print; governance force or cancel after 72 h remains the last resort
Chainlink pre-close print is up to 0.5 % away from the true close (deviation-triggered feed, no round at the close)Coupon or barrier decided on a price within the feed’s deviation thresholdBounded by the feed’s 0.5 % rule; a posted Pyth Pro closing print inside the window takes precedence in the cross-check and tightens this to Pyth’s confidence interval (maxConfidenceBps, 1 %)
Pyth Pro signer set compromised or a wrong signed update postedBackup round wrongDeviation check against the Chainlink primary defers on a disagreement above 3 %; Pyth governs its signer set on the verifier contract
Feed unreachable when the keeper callsObservation deferred; coupons delayedRetry once the feed answers again: the closing print still qualifies
Feed stops updating for daysObservations deferred; coupons delayed; maturity delayedGovernance force or cancel after 72 h
Feed decimals or uiMultiplier semantics changeSystematic mispricingFeeds are governed per underlying; changes require a timelocked setFeed
Governance forces a wrong priceDirect loss to one legforceDelay of 24 h with an event; guardians and the community can react; cancelling instead is the conservative path
Corporate actions (splits, dividends, spin-offs)s0 and later prices are no longer comparableStock Token issuers adjust token quantities or feed values per their own rules (Robinhood docs); governance may cancel affected observations. Series should avoid known event dates where possible
Calendar misconfiguration (missed holiday)Observation falls on a non-trading day; the feed is idle, so the observation defers and needs governanceGovernance registers holidays ahead; tests pin US holidays and DST for 2026 to 2030

What “settles at last good price” means

Section titled “What “settles at last good price” means”

If governance cancels the maturity observation, NoteCore settles at lastPrice, the last successfully observed price. This avoids an indefinite lock but means maturity economics are those of an earlier date. Cancellation is a last resort after both feeds have failed for 72 hours.

The provisional reference price used during Subscription (latestPrice) affects only the required prefund and the pro-rata bookkeeping of SHIELD deposits. If the stock moves sharply between deposit and strike, a SHIELD depositor’s prefund may be insufficient for the matched notional at s0; matching then falls back on prefundCapacity, and the excess stock is refundable. Depositors can over-prefund to avoid this.

OracleAdapter.peek(feed, closeTs) returns what observe would without effects ((0, false) until the grace has elapsed). resolvableAt(closeTs) is the first second at which observe is accepted. deferredSince(feed, closeTs) reports when a deferral began. Watch ObservationDeferred events and the adapter’s force-proposal events.