Oracles
How Project 0 uses Switchboard and Pyth oracles for asset pricing, confidence intervals, and EMA.
Each Bank is configured with an oracle by the Group administrator. P0 supports multiple oracle providers:
- Switchboard -- The typical oracle provider. Switchboard oracles require the caller to send a crank instruction just before using the oracle data, to refresh the price.
- Pyth -- Also supported. Pyth oracles are kept up-to-date by their infrastructure and typically require no action from callers.
- Fixed Price -- Some Banks use a fixed, administrator-set price (rare, used for special cases).
Banks can use multiple oracle accounts. For example, Kamino Banks require both a price oracle and the Kamino reserve account to compute accurate valuations.
Oracle Confidence Interval Adjustment
Some oracles report a price with a confidence interval (P +/- c), representing the range within which the true price likely falls. P0 uses confidence intervals conservatively:
- Assets (collateral) are priced at the lower bound:
P - P * c - Liabilities (debt) are priced at the upper bound:
P + P * c
Example: If the oracle reports Token A at $20 with a 5% confidence interval:
- As collateral, Token A is valued at $20 - $1 = $19
- As debt, Token A is valued at $20 + $1 = $21
The confidence interval is capped at a maximum of 5%. If the oracle reports a wider confidence interval, the protocol may clamp it to 5% or abort the transaction entirely. This is relatively unique to P0 in the borrow-lending space and provides an additional layer of protection against oracle instability.
EMA vs Spot Price
Some oracles report both a spot price (the current instantaneous price) and an Exponential Moving Average (EMA) price (a price-over-time instead of an instant price "right now").
When both are available, P0 uses them strategically:
| Operation | Price Used |
|---|---|
| Borrowing | EMA price (more stable, harder to manipulate) |
| Liquidation | Spot price (more responsive to rapid changes) |
If an EMA price is not available, all operations use the spot price.
Staleness
Oracle data must be fresh. If an oracle's data is stale, transactions that depend on it will fail.
- For Pyth oracles, this is rarely an issue since Pyth maintains its own update cadence.
- For Switchboard oracles, the caller must send a crank instruction just before the transaction to refresh the data.
When composing transactions that use Switchboard oracles, either bundle the crank instruction in the same transaction (if compute and account limits allow) or send a separate crank transaction with a brief delay before the main transaction. Many operators use Jito bundles for this.
Oracle Configuration
Each Bank's oracle configuration is readable from bank.config.oracle_keys. The oracles must be passed in the order they appear in this field when constructing transactions that require risk engine checks.
For Banks with multiple oracle accounts (like Kamino Banks), all oracle accounts must be included. For Kamino specifically, refresh_reserve must also execute within the same slot.