> For the complete documentation index, see [llms.txt](https://docs.curvance.com/app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.curvance.com/app/developer-docs/oracles.md).

# Oracles

### Overview

Curvance routes protocol price reads through `OracleManager`. Markets and cTokens use this manager to price supported assets, Curvance cToken shares, collateral, and debt through a single integration surface.

The oracle layer has three jobs:

* Map each supported asset to its configured pricing adaptor.
* Normalize adaptor responses into 18-decimal price values.
* Return an error code that tells calling contracts whether the price can be used for the requested operation.

{% hint style="info" %}
Live market configuration is single-source per asset. The codebase contains dual-adaptor support, but external integrations should treat the active path as one approved adaptor per asset with heartbeat checks, positive-price checks, and optional price guards for pegged or reference-priced assets.
{% endhint %}

### Architecture

#### `OracleManager`

`OracleManager` is the protocol-facing price hub. It stores approved adaptors, per-asset pricing configuration, and cToken-to-underlying mappings.

The manager exposes:

* `getPrice(asset, inUSD, getLower)` for direct price reads.
* `getPriceIsolatedPair(collateralToken, debtToken, errorCodeBreakpoint)` for isolated-market collateral and debt pricing.
* `getPricesForMarket(account, assets, errorCodeBreakpoint)` for account-level market checks.
* `getPricingAdaptors(asset)` and `isSupportedAsset(asset)` for integration discovery.

When an input asset is a registered Curvance cToken, `getPrice()` resolves its underlying asset first, reads the underlying price, then multiplies by the stored cToken exchange rate. Lower-bound reads round down, and upper-bound reads round up.

#### Adaptors

Adaptors implement `IOracleAdaptor`. They are responsible for source-specific validation and return an `IOracleAdaptor.PricingResult` with:

* `price`: the reported price.
* `inUSD`: whether the returned price is denominated in USD or the chain's native token.
* `hadError`: whether the adaptor found an invalid, stale, unsupported, or guarded price.

`BaseOracleAdaptor` provides the shared adaptor model: supported-asset tracking, per-asset price guards, price normalization to WAD scale, heartbeat-style data validation, and permission checks for configuration.

The current oracle source map includes three high-level categories:

* Direct push-feed adaptors for externally reported prices.
* Wrapped aggregator helpers that adjust an underlying feed by an exchange rate.
* Pendle-specific adaptors that compose a quote-asset price with a TWAP-derived rate.

Direct feed and Pendle adaptor paths converge at `IOracleAdaptor.getPrice()` before `OracleManager` evaluates the result. Wrapped aggregator helpers sit behind compatible feed adaptors and adjust the value those adaptors read.

#### Price Guards

Price guards live on adaptors, not on `OracleManager`. A guard can set a minimum price and a maximum price for an asset in a specific denomination. If a guarded price falls below the configured minimum, the adaptor returns a zero price that bubbles up as an oracle error. If the price is above the configured maximum, the adaptor clamps the returned price to the maximum.

Price guards are configured for pegged or reference-priced assets where bounded movement is part of the market design. Volatile assets should not be documented as having guards by default.

See [Price Guard](/app/developer-docs/oracles/price-guard.md) for the guard configuration model.

### Pricing Flow

<figure><img src="/files/2l81gGsRqqXRTCJ7u0tY" alt=""><figcaption></figcaption></figure>

1. A market, cToken, or integrator calls `OracleManager`.
2. If the input is a registered cToken, the manager resolves the underlying asset from `cTokens`.
3. The manager loads the asset's configured adaptor from `assetPricingConfig`.
4. The manager calls `IOracleAdaptor.getPrice(asset, inUSD, getLower)`.
5. The adaptor validates source data, normalizes the price, applies any configured guard, and returns `PricingResult`.
6. If the adaptor returned the opposite denomination, the manager converts between USD and the chain's native token by pricing the native token through the same manager.
7. If the original input was a cToken, the manager multiplies the underlying price by the stored cToken exchange rate.
8. The manager returns `(price, errorCode)` or reverts in market-specific helpers when the returned error code reaches the caller's `errorCodeBreakpoint`.

The `getLower` flag controls conservative pricing direction. Collateral-side reads use the lower price, while debt-side reads use the higher price. This keeps solvency checks pessimistic for both sides of a position.

`getPriceIsolatedPair()` prices collateral cToken shares with the lower underlying price and a fresh exchange rate, then prices debt underlying with the higher underlying price. `getPricesForMarket()` follows the same direction per account asset: collateral snapshots use lower share prices, and debt snapshots use higher underlying prices.

### Error Code Model

Oracle reads use numeric error codes:

<table><thead><tr><th width="92">Code</th><th width="132">Source name</th><th>Meaning</th></tr></thead><tbody><tr><td><code>0</code></td><td><code>NO_ERROR</code></td><td>The price read completed without an oracle error.</td></tr><tr><td><code>1</code></td><td><code>CAUTION</code></td><td>A dual-adaptor path found a partial failure or configured deviation. This path exists in source but is not the live single-adaptor model.</td></tr><tr><td><code>2</code></td><td><code>BAD_SOURCE</code></td><td>The price source failed, returned zero, returned stale or invalid data, or could not be trusted for the requested read.</td></tr></tbody></table>

`getPrice()` returns the error code with the price. It can still revert when the asset has no configured pricing path or an adaptor is not approved.

Market-facing helpers enforce the caller's breakpoint:

* `getPriceIsolatedPair(..., errorCodeBreakpoint)` reverts with `OracleManager__ErrorCodeFlagged()` when either side reaches the breakpoint.
* `getPricesForMarket(..., errorCodeBreakpoint)` reverts with `OracleManager__ErrorCodeFlagged()` when any account asset reaches the breakpoint.

Liquidation and solvency paths choose their breakpoint based on the operation. Integrators should not assume every nonzero error code has the same effect across all callers.

### Integration Considerations

* Discover support through `isSupportedAsset(asset)` or `getPricingAdaptors(asset)` before relying on a price read.
* Read real manager and adaptor addresses from the deployment registry for the chain you are integrating. Do not hardcode sample addresses.
* Treat prices as WAD-scaled values unless a downstream contract explicitly documents a different unit.
* Pass `inUSD = true` when matching Curvance market solvency paths, which price collateral and debt in USD.
* Use `getLower = true` for collateral-side previews and `getLower = false` for debt-side previews.
* Do not treat price guards as global protection for every asset. Check adaptor guard configuration when a pegged or reference-priced asset depends on bounded pricing.
* Do not continue a user flow after `BAD_SOURCE`. The manager and market helpers use that condition to block unsafe operations.
* When reading cToken prices, remember that the manager prices cToken shares by combining underlying price with the cToken exchange rate.

### Related Pages

* Oracle Manager
* Price Guard
* Adaptors


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.curvance.com/app/developer-docs/oracles.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
