DeviationBoundedOracle
DeviationBoundedOracle
Section titled “DeviationBoundedOracle”Deployment scope
Section titled “Deployment scope”This API matches the current DeviationBoundedOracle v2.16.0 source. At BNB Chain block 118367342, transparent proxy 0xc79Cb7efEBd121DC4B39eA141C214606595D665A pointed to implementation 0x16691f500541ca35bd63DD878B6D78728C9518AE.
The proxy and implementation do not establish the live whitelist, protection state, cache settings, ACM permissions, or keeper assignments. Read those values at the block used by an operator or integration.
The proxy API also inherits owner, pendingOwner, transferOwnership, acceptOwnership, renounceOwnership, accessControlManager, and owner-only setAccessControlManager.
The DeviationBoundedOracle provides manipulation-resistant pricing for lending operations.
It maintains a per-market rolling min/max price window. When the current spot price deviates significantly from the window bounds, protection mode activates automatically and conservative pricing kicks in:
- Collateral is valued at min(spot, windowMin) — caps collateral value at recent window low
- Debt is valued at max(spot, windowMax) — floors debt value at recent window high
This protects against instantaneous or short-duration price manipulation attacks on low-liquidity collateral tokens. Sustained attacks beyond the window period are expected to be handled by off-chain monitoring systems.
The oracle exposes both view and non-view price functions. The non-view variants update the price window and trigger protection. The view variants read stored state only. A transient price cache avoids redundant ResilientOracle calls within the same transaction when updateProtectionState is called before the view price reads.
For a feature-level description of how protection mode behaves end-to-end (problem statement, trigger logic, keeper role, exit conditions), see Protection Mode.
Solidity API
Section titled “Solidity API”enum PriceBoundType { MIN, MAX}enum KeeperAction { SetMinPrice, SetMaxPrice, ExitProtectionMode}MarketProtectionState
Section titled “MarketProtectionState”Per-asset protection state tracking the min/max price window
struct MarketProtectionState { uint128 minPrice; uint128 maxPrice; bool currentlyUsingProtectedPrice; bool isBoundedPricingEnabled; uint64 lastProtectionTriggeredAt; uint64 cooldownPeriod; address asset; uint128 triggerThreshold; uint128 resetThreshold; bool cachingEnabled;}KeeperActionItem
Section titled “KeeperActionItem”One item in a syncPriceBoundsAndProtections payload
struct KeeperActionItem { address asset; enum IDeviationBoundedOracle.KeeperAction action; uint256 value;}TokenConfigInput
Section titled “TokenConfigInput”One item in a setTokenConfigs payload
struct TokenConfigInput { address asset; uint64 cooldownPeriod; uint256 triggerThreshold; uint256 resetThreshold; bool enableBoundedPricing; bool enableCaching;}MIN_THRESHOLD
Section titled “MIN_THRESHOLD”Minimum allowed threshold value (5%) to account for keeper deadband
uint256 MIN_THRESHOLDMAX_THRESHOLD
Section titled “MAX_THRESHOLD”Maximum allowed threshold value (50%)
uint256 MAX_THRESHOLDKEEPER_DEADBAND
Section titled “KEEPER_DEADBAND”Keeper deadband threshold (5%). Used by checkAndGetWindowDrift (a view) so the off-chain keeper can skip pushes whose delta is below the deadband. Not enforced on-chain inside updateMinPrice / updateMaxPrice — those only validate the spot bound and the cross bound.
uint256 KEEPER_DEADBANDRESILIENT_ORACLE
Section titled “RESILIENT_ORACLE”Resilient Oracle used to fetch spot prices
contract ResilientOracleInterface RESILIENT_ORACLEnativeMarket
Section titled “nativeMarket”Native market address
address nativeMarketVAI address
address vaiCOLLATERAL_PRICE_CACHE_SLOT
Section titled “COLLATERAL_PRICE_CACHE_SLOT”Transient storage slot for caching final collateral prices within a transaction
bytes32 COLLATERAL_PRICE_CACHE_SLOTDEBT_PRICE_CACHE_SLOT
Section titled “DEBT_PRICE_CACHE_SLOT”Transient storage slot for caching final debt prices within a transaction
bytes32 DEBT_PRICE_CACHE_SLOTNATIVE_TOKEN_ADDR
Section titled “NATIVE_TOKEN_ADDR”Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc) and can serve as any underlying asset of a market that supports native tokens
address NATIVE_TOKEN_ADDRassetProtectionConfig
Section titled “assetProtectionConfig”Per-asset protection state
mapping(address => struct IDeviationBoundedOracle.MarketProtectionState) assetProtectionConfigallAssets
Section titled “allAssets”Append-only array of all assets ever initialized, used for enumeration
address[] allAssetsconstructor
Section titled “constructor”Constructor for the implementation contract. Sets immutable variables.
constructor(contract ResilientOracleInterface _resilientOracle, address nativeMarketAddress, address vaiAddress) publicParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| _resilientOracle | contract ResilientOracleInterface | Address of the ResilientOracle contract |
| nativeMarketAddress | address | The address of a native market (for bsc it would be vBNB address) |
| vaiAddress | address | The address of the VAI token, or address(0) if VAI is not deployed on the chain. |
initialize
Section titled “initialize”Initializes the contract admin
function initialize(address accessControlManager_) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| accessControlManager_ | address | Address of the access control manager contract |
getBoundedCollateralPrice
Section titled “getBoundedCollateralPrice”Gets the bounded collateral price for a given vToken, updating protection state
function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| vToken | address | vToken address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| collateralPrice | uint256 | The bounded collateral price |
📅 Events
Section titled “📅 Events”- MinPriceUpdated if a new window minimum is recorded
- MaxPriceUpdated if a new window maximum is recorded
- ProtectionTriggered if the spot price deviates beyond the threshold
getBoundedDebtPrice
Section titled “getBoundedDebtPrice”Gets the bounded debt price for a given vToken, updating protection state
function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| vToken | address | vToken address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| debtPrice | uint256 | The bounded debt price |
📅 Events
Section titled “📅 Events”- MinPriceUpdated if a new window minimum is recorded
- MaxPriceUpdated if a new window maximum is recorded
- ProtectionTriggered if the spot price deviates beyond the threshold
getBoundedPrices
Section titled “getBoundedPrices”Gets both the bounded collateral and debt prices for a given vToken, updating protection state
function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| vToken | address | vToken address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| collateralPrice | uint256 | The bounded collateral price |
| debtPrice | uint256 | The bounded debt price |
📅 Events
Section titled “📅 Events”- MinPriceUpdated if a new window minimum is recorded
- MaxPriceUpdated if a new window maximum is recorded
- ProtectionTriggered if the spot price deviates beyond the threshold
updateProtectionState
Section titled “updateProtectionState”Fetches the spot price, updates the protection window, and (when the asset’s cachingEnabled flag is true) caches the resolved collateral and debt prices in transient storage for the duration of the transaction. When cachingEnabled is false, the window/trigger update still happens but no cache write occurs and subsequent view reads recompute live from spot.
function updateProtectionState(address vToken) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| vToken | address | vToken address |
📅 Events
Section titled “📅 Events”- MinPriceUpdated if a new window minimum is recorded
- MaxPriceUpdated if a new window maximum is recorded
- ProtectionTriggered if the spot price deviates beyond the threshold
getBoundedCollateralPriceView
Section titled “getBoundedCollateralPriceView”Gets the bounded collateral price for a given vToken (view variant)
function getBoundedCollateralPriceView(address vToken) external view returns (uint256 collateralPrice)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| vToken | address | vToken address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| collateralPrice | uint256 | The bounded collateral price |
getBoundedDebtPriceView
Section titled “getBoundedDebtPriceView”Gets the bounded debt price for a given vToken (view variant)
function getBoundedDebtPriceView(address vToken) external view returns (uint256 debtPrice)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| vToken | address | vToken address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| debtPrice | uint256 | The bounded debt price |
getBoundedPricesView
Section titled “getBoundedPricesView”Gets both the bounded collateral and debt prices for a given vToken (view variant)
function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| vToken | address | vToken address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| collateralPrice | uint256 | The bounded collateral price |
| debtPrice | uint256 | The bounded debt price |
updateMinPrice
Section titled “updateMinPrice”Updates the minimum price in the rolling window for a given asset. On-chain validation requires newMin <= maxPrice and newMin <= currentSpot; the 5% KEEPER_DEADBAND is not enforced here — the keeper consults checkAndGetWindowDrift off-chain to decide whether the push is worth it.
function updateMinPrice(address asset, uint128 newMin) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
| newMin | uint128 | The new minimum price |
📅 Events
Section titled “📅 Events”- MinPriceUpdated
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only authorized keeper addresses
❌ Errors
Section titled “❌ Errors”- ZeroPriceNotAllowed if newMin is zero
- MarketNotInitialized if the asset has not been initialized
- InvalidMinPrice if newMin exceeds the current spot or is strictly above maxPrice
updateMaxPrice
Section titled “updateMaxPrice”Updates the maximum price in the rolling window for a given asset. On-chain validation requires newMax >= minPrice and newMax >= currentSpot; the 5% KEEPER_DEADBAND is not enforced here — the keeper consults checkAndGetWindowDrift off-chain to decide whether the push is worth it.
function updateMaxPrice(address asset, uint128 newMax) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
| newMax | uint128 | The new maximum price |
📅 Events
Section titled “📅 Events”- MaxPriceUpdated
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only authorized keeper addresses
❌ Errors
Section titled “❌ Errors”- ZeroPriceNotAllowed if newMax is zero
- MarketNotInitialized if the asset has not been initialized
- InvalidMaxPrice if newMax is below the current spot or is strictly below minPrice
exitProtectionMode
Section titled “exitProtectionMode”Exits protection mode for a given asset
function exitProtectionMode(address asset) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
📅 Events
Section titled “📅 Events”- ProtectionModeExited
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only authorized monitor/keeper addresses
❌ Errors
Section titled “❌ Errors”- ProtectedPriceInactive if protection is not currently active
- CooldownNotElapsed if cooldown period has not elapsed
- PriceRangeNotConverged if window range is still above exit threshold
syncPriceBoundsAndProtections
Section titled “syncPriceBoundsAndProtections”Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check
function syncPriceBoundsAndProtections(struct IDeviationBoundedOracle.KeeperActionItem[] actions) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| actions | struct IDeviationBoundedOracle.KeeperActionItem[] | The list of keeper actions to apply |
📅 Events
Section titled “📅 Events”- MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only authorized keeper addresses
❌ Errors
Section titled “❌ Errors”- InvalidKeeperAction if an item carries an unsupported action enum value
setTokenConfig
Section titled “setTokenConfig”Initializes protection for a new asset. The window is seeded with the current spot from the ResilientOracle (so the oracle must be live for the asset). Whitelist participation is independent of initialization — enableBoundedPricing may be false, in which case the asset is configured but the DBO short-circuits to spot until governance flips the flag with setAssetBoundedPricingEnabled.
function setTokenConfig(struct IDeviationBoundedOracle.TokenConfigInput tokenConfig_) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| tokenConfig_ | struct IDeviationBoundedOracle.TokenConfigInput | Token config input for the asset |
📅 Events
Section titled “📅 Events”- ProtectionInitialized
- BoundedPricingWhitelistUpdated
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only Governance
❌ Errors
Section titled “❌ Errors”- ZeroAddressNotAllowed if asset is the zero address
- ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero
- MarketAlreadyInitialized if the asset has already been initialized
- ThresholdBelowMinimum if triggerThreshold is below 5%
- ThresholdAboveMaximum if triggerThreshold is above 50%
- InvalidResetThreshold if resetThreshold is at or above triggerThreshold
- VAINotAllowed if asset is the VAI token
- PriceExceedsUint128 if the seeded spot price overflows uint128
setTokenConfigs
Section titled “setTokenConfigs”Batch-initializes protection for multiple assets in a single transaction. Per-item validation matches setTokenConfig; any item revert rolls back the whole batch.
function setTokenConfigs(struct IDeviationBoundedOracle.TokenConfigInput[] tokenConfigs_) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| tokenConfigs_ | struct IDeviationBoundedOracle.TokenConfigInput[] | Array of token config inputs, one per asset |
📅 Events
Section titled “📅 Events”- ProtectionInitialized for each asset
- BoundedPricingWhitelistUpdated for each asset
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only Governance
❌ Errors
Section titled “❌ Errors”- InvalidArrayLength if the input array is empty
- Any error raised by per-item validation (see
setTokenConfig)
setCooldownPeriod
Section titled “setCooldownPeriod”Sets the cooldown period for an asset
function setCooldownPeriod(address asset, uint64 newCooldown) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
| newCooldown | uint64 | The new cooldown period in seconds |
📅 Events
Section titled “📅 Events”- CooldownPeriodSet
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only Governance
setThresholds
Section titled “setThresholds”Sets the trigger and reset thresholds for an asset
function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
| newTriggerThreshold | uint256 | The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold. |
| newResetThreshold | uint256 | The new reset threshold (mantissa). Must be non-zero and below the trigger threshold. |
📅 Events
Section titled “📅 Events”- TriggerThresholdSet if the trigger threshold changed
- ResetThresholdSet if the reset threshold changed
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only Governance
❌ Errors
Section titled “❌ Errors”- ThresholdBelowMinimum if newTriggerThreshold is below 5%
- ThresholdAboveMaximum if newTriggerThreshold is above 50%
- InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold
setAssetBoundedPricingEnabled
Section titled “setAssetBoundedPricingEnabled”Sets whether an asset is enabled for bounded pricing
function setAssetBoundedPricingEnabled(address asset, bool enabled) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
| enabled | bool | Whether bounded pricing should be enabled for the asset |
📅 Events
Section titled “📅 Events”- BoundedPricingWhitelistUpdated
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only Governance
❌ Errors
Section titled “❌ Errors”- ProtectedPriceActive if trying to disable an asset while protection is active
setCachingEnabled
Section titled “setCachingEnabled”Toggles transient caching of the bounded (collateral, debt) pair for an asset
function setCachingEnabled(address asset, bool enabled) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
| enabled | bool | Whether transient caching is enabled for this asset |
📅 Events
Section titled “📅 Events”- CachingEnabledUpdated
⛔️ Access Requirements
Section titled “⛔️ Access Requirements”- Only Governance
❌ Errors
Section titled “❌ Errors”- MarketNotInitialized if the asset has not been initialized
getInitializedAssets
Section titled “getInitializedAssets”Returns all asset addresses that have ever been initialized
function getInitializedAssets() external view returns (address[])Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| [0] | address[] | Array of all initialized asset addresses |
isBoundedPricingEnabled
Section titled “isBoundedPricingEnabled”Checks if an asset is whitelisted for bounded pricing
function isBoundedPricingEnabled(address asset) external view returns (bool)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| [0] | bool | True if the asset is whitelisted |
currentlyUsingProtectedPrice
Section titled “currentlyUsingProtectedPrice”Checks if the asset is currently using the protected (bounded) price
function currentlyUsingProtectedPrice(address asset) external view returns (bool)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| [0] | bool | True if the asset is currently using the protected price instead of spot |
getAllBoundedPricingEnabledAssets
Section titled “getAllBoundedPricingEnabledAssets”Returns all currently whitelisted asset addresses
function getAllBoundedPricingEnabledAssets() external view returns (address[])Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| [0] | address[] | result Array of whitelisted asset addresses |
canExitProtection
Section titled “canExitProtection”Checks if protection can be exited for an asset
function canExitProtection(address asset) external view returns (bool)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| asset | address | The underlying asset address |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| [0] | bool | True if protection can be disabled |
checkAndGetWindowDrift
Section titled “checkAndGetWindowDrift”Batch-checks which assets’ on-chain min/max have drifted beyond the deadband from the keeper’s proposed window values
function checkAndGetWindowDrift(address[] assets, uint128[] proposedMins, uint128[] proposedMaxs) external view returns (bool[] needsMinUpdate, bool[] needsMaxUpdate)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| assets | address[] | Array of asset addresses to check |
| proposedMins | uint128[] | Keeper’s off-chain window minimum prices |
| proposedMaxs | uint128[] | Keeper’s off-chain window maximum prices |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| needsMinUpdate | bool[] | Whether minPrice drift exceeds deadband for each asset |
| needsMaxUpdate | bool[] | Whether maxPrice drift exceeds deadband for each asset |
❌ Errors
Section titled “❌ Errors”- InvalidArrayLength if the input array lengths do not match