For the complete documentation index, see llms.txt. This page is also available as Markdown.

Oracle Manager

Overview

OracleManager is Curvance's protocol-level price hub. Market contracts call it to price underlying assets, cToken shares, collateral positions, and debt positions through a single interface.

The manager does not maintain price feeds itself. It routes each supported asset to one or more approved oracle adaptors, normalizes price results, applies cToken exchange-rate conversion when the queried asset is a Curvance cToken, and returns an error code that downstream contracts use as a safety signal.

Prices are returned with 18-decimal precision. A price can be denominated in USD or in the chain's native gas token, depending on the inUSD argument.

Architecture

OracleManager is built around three registries:

Registry
Getter
Purpose

Approved adaptors

isApprovedAdaptor(address)

Controls which adaptor contracts may be used by the manager.

Asset pricing config

getPricingAdaptors(address)

Lists the adaptor dependencies for an underlying asset.

Curvance cTokens

cTokens(address)

Maps a supported cToken to its underlying asset.

The constructor stores the protocol centralRegistry, and every configuration function checks centralRegistry.hasElevatedPermissions(msg.sender) before changing oracle state.

constructor(ICentralRegistry cr);

Supported Asset Model

An asset is supported when it has at least one configured pricing adaptor. A Curvance cToken is supported when it has been registered in cTokens and its underlying asset has at least one configured adaptor.

The manager supports up to two adaptor dependencies per asset. Current developer-facing integrations should treat normal pricing as single-source, with adaptor-level freshness and guard checks handled inside the configured adaptor. The two-adaptor code path exists for assets that are configured with two adaptor dependencies, where the manager can compare returned prices against configured deviation bounds.

Adaptors return IOracleAdaptor.PricingResult:

Field
Meaning

price

The adaptor's price value.

inUSD

Whether price is USD-denominated.

hadError

Whether the adaptor encountered a pricing issue.

When an adaptor's denomination does not match the requested denomination, the manager converts through the configured price of the native gas token.

cToken Pricing

For registered cTokens, getPrice() first prices the underlying asset, then multiplies by the cToken exchange rate:

Query
Exchange-rate read
Rounding

getPrice(cToken, ..., true)

exchangeRate()

Down

getPrice(cToken, ..., false)

exchangeRate()

Up

getPriceIsolatedPair() collateral side

exchangeRateUpdated()

Down

getPricesForMarket() collateral side

getSnapshotUpdated() then exchangeRate()

Down

The market helper functions use updated cToken reads because they support liquidity checks that need current account and exchange-rate data.

Price Query Flow

  1. The caller requests a price through getPrice(asset, inUSD, getLower) or through a market helper.

  2. The manager checks the optional SEQUENCER_ORACLE() uptime feed from the central registry. If no feed is configured, the check returns true.

  3. If asset is a registered cToken, the manager replaces it with its underlying asset for adaptor pricing.

  4. The manager loads the asset's adaptor list and reverts if no adaptor is configured.

  5. With one adaptor, it calls IOracleAdaptor.getPrice(asset, inUSD, getLower).

  6. With two adaptors, it calls both adaptors, handles adaptor errors, checks deviation bounds, and returns either the lower or higher price based on getLower.

  7. If the original query was for a cToken, the manager converts the underlying price into a cToken share price.

  8. If the resulting price is zero, the manager escalates the result to BAD_SOURCE.

Use getLower = true when valuing collateral conservatively. Use getLower = false when valuing debt conservatively.

Error Code Handling

OracleManager uses numeric error codes from ConstantsLib:

Code
Name
Meaning

0

NO_ERROR

The price was returned without an oracle-manager error signal.

1

CAUTION

One source failed in a two-adaptor configuration, or the two adaptor prices exceeded the configured caution bound.

2

BAD_SOURCE

No usable price was available, the returned price was zero, the optional uptime-feed check failed, or the two adaptor prices exceeded the configured bad-source bound.

getPrice() returns the error code to the caller. Market helper functions take an errorCodeBreakpoint and revert with OracleManager__ErrorCodeFlagged() when the observed code is greater than or equal to that breakpoint.

This makes the caller's tolerance explicit. For example, a caller that passes BAD_SOURCE accepts CAUTION but rejects BAD_SOURCE; a caller that passes CAUTION rejects both CAUTION and BAD_SOURCE.

Market Query Helpers

Market-facing helpers price cTokens and account positions in the form used by liquidity checks.

Function
Collateral pricing
Debt pricing
State behavior

getPriceIsolatedPair()

Prices the collateral cToken's underlying with getLower = true, then converts to share value with exchangeRateUpdated().

Prices the debt cToken's underlying with getLower = false.

Updates the collateral cToken exchange rate.

getPricesForMarket()

For snapshots marked isCollateral, prices the underlying with getLower = true, then converts to share value.

For non-collateral snapshots, prices the underlying with getLower = false.

Calls getSnapshotUpdated(account) on each asset.

Both helpers require each provided cToken to be registered in cTokens. If a cToken is not registered, the helper reverts with OracleManager__NotSupported().

Permissions and Configuration

Only addresses with elevated permissions in the central registry can configure the manager. These functions add or remove approved adaptors, attach approved adaptors to assets, configure two-adaptor deviation bounds, and register cTokens.

Dual adaptor infrastructure exists on live deployments, but are unused in practice.

Deviation bounds are configured in basis points. The manager enforces:

Constant
Value
Meaning

MIN_DEVIATION_BOUND

20

Minimum allowed caution bound, equal to 0.20%.

MAX_DEVIATION_BOUND

350

Maximum allowed bad-source bound, equal to 3.50%.

MIN_CAUTION_TO_BAD_SOURCE_DELTA

20

Minimum gap between caution and bad-source bounds, equal to 0.20%.

When bounds are stored, the manager adds BPS internally. For example, an input of 200 is stored as 10200 so _checkBounds() can compare price ratios directly.

Configuration emits:

Event
Emitted when

AdaptorDependencyAdded(address asset, address adaptor)

An adaptor dependency is added for an asset.

AdaptorDependencyRemoved(address asset, address adaptor)

An adaptor dependency is removed from an asset.

AssetDeviationBoundsSet(address asset, uint256 badSourceBoundUSD, uint256 cautionBoundUSD, uint256 badSourceBoundNative, uint256 cautionBoundNative)

Two-adaptor deviation bounds are set.

Integration Considerations

  • Read real contract addresses from the deployment registry for the chain you are integrating with. Use placeholder addresses in examples and application config templates.

  • Treat returned prices as 18-decimal values.

  • Check both price and errorCode when calling getPrice() directly. A non-reverting call can still return CAUTION or BAD_SOURCE.

  • Use the same conservative direction as protocol liquidity checks: lower prices for collateral, higher prices for debt.

  • Use market helpers when reproducing market health checks, because they update snapshots and exchange rates where the protocol expects updated values.

  • Do not assume a cToken can be priced directly until cTokens(cToken) returns a nonzero underlying and the underlying is supported.

  • Do not hardcode adaptor behavior in integrations. The manager exposes adaptor addresses, but source-specific checks are implemented inside each adaptor.

User Interaction Functions

Price Reads

getPrice()

Description: Returns the price of an asset or registered cToken and an oracle-manager error code. This is a view function and does not update cToken exchange rates.

Function signature:

Inputs:

Type
Name
Description

address

asset

Underlying asset or registered cToken to price.

bool

inUSD

true for USD-denominated price, false for native-token-denominated price.

bool

getLower

true to return the lower value in a two-adaptor setup, false to return the higher value.

Return data:

Type
Name
Description

uint256

price

18-decimal price.

uint256

errorCode

0, 1, or 2.

  • Reverts with OracleManager__NotSupported() if the asset has no configured adaptor.

  • Returns (0, BAD_SOURCE) if the optional SEQUENCER_ORACLE() uptime-feed check fails.

  • Converts registered cToken prices using exchangeRate().


getPriceIsolatedPair()

Description: Returns conservative prices for a collateral cToken and debt cToken pair. This function is used by market logic that needs collateral value in share terms and debt value in underlying terms.

Function signature:

Inputs:

Type
Name
Description

address

collateralToken

Registered cToken used as collateral.

address

debtToken

Registered cToken used for debt.

uint256

errorCodeBreakpoint

Error code threshold that causes a revert.

Return data:

Type
Name
Description

uint256

collateralSharesPrice

Collateral cToken share price after applying exchangeRateUpdated().

uint256

debtUnderlyingPrice

Debt token underlying price.

  • Reverts with OracleManager__ErrorCodeFlagged() when an observed error code is greater than or equal to errorCodeBreakpoint.

  • Reverts with OracleManager__NotSupported() if either cToken is not registered.


getPricesForMarket()

Description: Returns updated account snapshots and conservative prices for a list of cTokens in a market.

Function signature:

Inputs:

Type
Name
Description

address

account

Account to snapshot.

address[] calldata

assets

cToken addresses to price.

uint256

errorCodeBreakpoint

Error code threshold that causes a revert.

Return data:

Type
Description

AccountSnapshot[] memory

Updated cToken snapshots for account.

uint256[] memory

Prices aligned to assets.

uint256

Number of assets processed.

Calls getSnapshotUpdated(account) on each asset. Prices collateral snapshots in cToken share terms and debt snapshots in underlying terms.


Support and Status Reads

getPricingAdaptors()

Description: Returns the adaptor addresses currently configured for an asset.

Function signature:

Inputs:

Type
Name
Description

address

asset

Underlying asset whose pricing adaptors should be returned.

Return data:

Type
Name
Description

address[] memory

result

Current adaptor dependencies for asset.

Events: None.

This returns the dynamic adaptor array that the generated assetPricingConfig() getter omits.


isSupportedAsset()

Description: Returns whether an underlying asset or registered cToken is supported by the manager.

Function signature:

Inputs:

Type
Name
Description

address

asset

Underlying asset or registered cToken to check.

Return data:

Type
Description

bool

true if the asset has at least one configured pricing adaptor. For cTokens, support is checked through the registered underlying asset.

Events: None.


isSequencerValid()

Description: Returns whether the optional central-registry uptime-feed check currently permits pricing.

Function signature:

Inputs: None.

Return data:

Type
Description

bool

true when no uptime feed is configured or the configured feed currently passes the manager's check.

Events: None.

getPrice() returns (0, BAD_SOURCE) when this check fails. Market helper functions revert with OracleManager__ErrorCodeFlagged() when this check fails.


isApprovedAdaptor()

Description: Returns whether an adaptor address is approved for manager use.

Function signature:

Inputs:

Type
Name
Description

address

adaptor

Adaptor address to check.

Return data:

Type
Description

bool

true if the adaptor is approved for manager use.

Events: None.


cTokens()

Description: Returns the underlying asset for a registered Curvance cToken, or address(0) if the token is not registered.

Function signature:

Inputs:

Type
Name
Description

address

cToken

Curvance cToken address to inspect.

Return data:

Type
Description

address

Registered underlying asset, or address(0) when cToken is not registered.

Events: None.

OracleManager uses this mapping to decide whether getPrice() should price the input as a cToken share.


assetPricingConfig()

Description: Returns the stored deviation-bound fields for an asset. The generated getter does not return the dynamic adaptor array; use getPricingAdaptors(asset) for adaptor addresses.

Function signature:

Inputs:

Type
Name
Description

address

asset

Underlying asset whose stored deviation bounds should be read.

Return data:

Type
Description

uint16

Stored USD bad-source bound.

uint16

Stored USD caution bound.

uint16

Stored native-token bad-source bound.

uint16

Stored native-token caution bound.

Events: None.

The stored values include the BPS offset added by _setDeviationBounds(). Use getPricingAdaptors(asset) to read the configured adaptor addresses.


centralRegistry()

Description: Returns the central registry used for permission checks and optional uptime-oracle lookup.

Function signature:

Inputs: None.

Return data:

Type
Description

ICentralRegistry

Central registry used by the manager.

Events: None.


native()

Description: Returns the sentinel address used for the chain's native gas token.

Function signature:

Inputs: None.

Return data:

Type
Description

address

Sentinel address used to price the chain's native gas token.

Events: None.

The sentinel is 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE.


Constant Getters

Description: Return immutable oracle-manager configuration limits.

Function signatures:

Inputs: None.

Return data:

Function
Type
Description

GRACE_PERIOD_TIME()

uint256

Uptime-feed grace period, in seconds.

MAX_DEVIATION_BOUND()

uint256

Maximum allowed deviation bound, in BPS.

MIN_DEVIATION_BOUND()

uint256

Minimum allowed deviation bound, in BPS.

MIN_CAUTION_TO_BAD_SOURCE_DELTA()

uint256

Minimum gap between caution and bad-source bounds, in BPS.

Last updated

Was this helpful?