Superstate Oracle is a price feed that stores prices like a regular oracle. However, when consumers need to read the latest price, it doesn't return the last stored price. Instead, it computes the current price based on the last two stored prices using a formula. Think of it as a price-over-time curve—we don't have the exact equation, but using the last two points on the curve, we can predict the next point (the current price at the current timestamp).
We can use a function like the following, which is called when consumers call latestRoundData().
The USDY price change is by design monotonic, deterministically linked to a daily interest rate, A range-based model would either drift away from reality or need constant manual overrides.
For the getPrice() function, it needs to iterate over ranges; if the number of added ranges increases, it takes a lot of time in the worst case to find the right range. But in the case of USDY, as the price is stable, only a handful of ranges need to be set. In reality, the last range was added in 2023.
The range model is good for:
RWA with RWA with predictable accrual or daily fixed interest rate
For volatile assets, the "range" concept can only be used for sanity checks: cap/floor limits or maximum daily change guards around a separate real price feed.
Daily Fixed Interest Rate Model
The range oracle is a perfect match for assets with a daily fixed interest rate.
Assets where you can represent their yield as a constant per-day accrual:
Tokenized Money Market Funds (MMFs)
E.g. Ondo’s OMMF
Oracles often expose a daily growth factor for NAV (Net Asset Value) per share.
Tokenized Treasury Bills (T-bills)
Although T-bills are zero-coupon, in practice protocols (like Ondo) smooth their yield into a daily accrual model so users see price per token increasing each day.
Stable debt agreements / bond tokens
Fixed-rate loan pools or tokenized bonds where the coupon is smoothed daily for accounting.
Even if coupons are quarterly, some protocols accrue it daily for NAV reporting.
Example: T-bill Interest Rate
T-bill is a short-term debt security issued by the U.S. Department of the Treasury.
Key Features
Maturity: T-bills mature in a year or less (common terms are 4, 8, 13, 26, and 52 weeks).
No interest payments: Instead of paying interest, T-bills are sold at a discount to their face value. At maturity, the government pays the holder the full face value.
Example: You might buy a T-bill for $9,800, and at maturity, you receive $10,000. The $200 difference is your return.
Daily Interest Rate (IR)
The "yield" comes from the discount between the purchase price and face value. To model T-bills as earning a fixed daily rate, choose a daily IR that matches the annualized T-bill yield.
We can use the general Range struct for any asset with a daily fixed interest rate.
We need to compute the dailyInterestRate . Typically, T-bill yields are quoted on an annualized basis (e.g., 5% annual yield). Convert this to a daily rate using the following formula, then multiply by 1e27 before storing it in the contract.
$$ dailyFactor=(1+annualYield)^{1/365}
$$ dailyIR= dailyFactor * 10^{27} $$
Adding new Range
T-bills are issued at maturities like 4-week, 8-week, 13-week, 26-week, and 52-week. The oracle treats yield as a fixed daily interest rate within each "range." When a new T-bill is bought or rolled over, you start a new range with the updated daily IR (derived from that bill's discount rate). The frequency of new ranges matches the rollover frequency of the underlying strategy.
Example: If the product always holds 4-week T-bills
You'd create a new range roughly every 4 weeks—when the old T-bill matures and a new one is purchased.
Range Oracle Risks for Fixed Daily Interest Rate Model
Temporary mispricing
can lead to arbitrage opportunities or unfair liquidations in DeFi protocols that rely on the oracle.
Each range assumes a fixed daily interest rate. For example, with T-bills, new auctions at maturity can have significantly different yields. If the oracle doesn't update the range promptly, it will overstate or understate NAV until corrected.
Real T-bills settle on specific dates and may include weekends or holidays. If the on-chain range doesn't align exactly with off-chain accrual dates, small but persistent divergences accumulate. For example, if a 13-week bill matures on a Friday but you roll on the following Monday, your oracle may continue to "grow" through the weekend incorrectly unless you set precise range end dates.
Mitigation
Each range in your oracle corresponds to the life of the current T-bill position with its fixed daily yield. When that T-bill matures (on the auction settlement date), the range should end at that timestamp. The oracle then needs a new range with the daily interest rate from the newly purchased T-bill (based on the latest auction). Within a short update window (N hours/days) after the auction settles, governance posts the new range.
If the current timestamp is beyond the last range’s end, the loop finds that last range and calls derivePrice(range, range.end - 1). In other words, the oracle freezes at the last valid price, just before the expired range ended. So, the oracle becomes stale.
In getPrice(), if block.timestamp >= lastRangeEnd, return (price, stale=true) or emit a flag (or revert with StaleOracle).
Long History
Since ranges are append-only, each new yield environment creates a new range. If yields change frequently, you'll accumulate a long history of ranges, adding complexity for historical lookups.
When a node executes the loop, it may be slow or could time out.
When another contract calls this view during a state-changing transaction, it does consume gas within that transaction.
Mitigate
Use binary search to keep getPrice() at O(log n) complexity instead of O(n).
Market risk misrepresentation
The oracle publishes a deterministic path where price always increases at a fixed daily rate. Real markets involve secondary market fluctuations, auction variability, and credit/settlement risks. DeFi users relying on the oracle may assume guaranteed monotonic growth, which doesn't always hold true in practice.
Example for T-bills:
If secondary prices fall due to interest rate shocks, the NAV of a T-bill ETF changes immediately.
However, your oracle will only update when the next range is set, meaning short-term shocks remain invisible.
Mitigation
If the oracle always outputs a smooth path, it misrepresents market reality—making the asset appear safer and more predictable than it actually is.
Add metadata that clearly states how the oracle computes its values. Example: a string or URL field like methodology = "Smoothed NAV based on fixed daily IR" so integrators know it’s a model, not a real-time market price.
Add a boolean or enum flag that says whether smoothing is in effect. Example: isNAVSmoothing = true.
External sanity oracle: Optionally bring in another feed — e.g., Chainlink’s T-bill price index, or a secondary market mark-to-market. Compare |oraclePrice−referencePrice|≤ε. If deviation is larger than allowed (say > 1%), pause the oracle or flag it as stale.
Governance / Trust Risk
Since an admin must set new ranges, the oracle has trust assumptions.
A malicious or negligent admin could set an artificially high daily rate for the next range.
DeFi protocols integrating your oracle need to trust governance (or have circuit breakers).
Mitigate
Use multi-signature setters, emit detailed events (like RangeSet with reasons), and maintain an on-chain allowlist of authorized feeders.