Skip to content

DeviationBoundedOracle

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.

enum PriceBoundType {
MIN,
MAX
}
enum KeeperAction {
SetMinPrice,
SetMaxPrice,
ExitProtectionMode
}

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;
}

One item in a syncPriceBoundsAndProtections payload


struct KeeperActionItem {
address asset;
enum IDeviationBoundedOracle.KeeperAction action;
uint256 value;
}

One item in a setTokenConfigs payload


struct TokenConfigInput {
address asset;
uint64 cooldownPeriod;
uint256 triggerThreshold;
uint256 resetThreshold;
bool enableBoundedPricing;
bool enableCaching;
}

Minimum allowed threshold value (5%) to account for keeper deadband

uint256 MIN_THRESHOLD

Maximum allowed threshold value (50%)

uint256 MAX_THRESHOLD

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_DEADBAND

Resilient Oracle used to fetch spot prices

contract ResilientOracleInterface RESILIENT_ORACLE

Native market address

address nativeMarket

VAI address

address vai

Transient storage slot for caching final collateral prices within a transaction

bytes32 COLLATERAL_PRICE_CACHE_SLOT

Transient storage slot for caching final debt prices within a transaction

bytes32 DEBT_PRICE_CACHE_SLOT

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_ADDR

Per-asset protection state

mapping(address => struct IDeviationBoundedOracle.MarketProtectionState) assetProtectionConfig

Append-only array of all assets ever initialized, used for enumeration

address[] allAssets

Constructor for the implementation contract. Sets immutable variables.

constructor(contract ResilientOracleInterface _resilientOracle, address nativeMarketAddress, address vaiAddress) public
NameTypeDescription
_resilientOraclecontract ResilientOracleInterfaceAddress of the ResilientOracle contract
nativeMarketAddressaddressThe address of a native market (for bsc it would be vBNB address)
vaiAddressaddressThe address of the VAI token, or address(0) if VAI is not deployed on the chain.

Initializes the contract admin

function initialize(address accessControlManager_) external
NameTypeDescription
accessControlManager_addressAddress of the access control manager contract

Gets the bounded collateral price for a given vToken, updating protection state

function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice)
NameTypeDescription
vTokenaddressvToken address
NameTypeDescription
collateralPriceuint256The bounded collateral price
  • 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

Gets the bounded debt price for a given vToken, updating protection state

function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice)
NameTypeDescription
vTokenaddressvToken address
NameTypeDescription
debtPriceuint256The bounded debt price
  • 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

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)
NameTypeDescription
vTokenaddressvToken address
NameTypeDescription
collateralPriceuint256The bounded collateral price
debtPriceuint256The bounded debt price
  • 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

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) external
NameTypeDescription
vTokenaddressvToken address
  • 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

Gets the bounded collateral price for a given vToken (view variant)

function getBoundedCollateralPriceView(address vToken) external view returns (uint256 collateralPrice)
NameTypeDescription
vTokenaddressvToken address
NameTypeDescription
collateralPriceuint256The bounded collateral price

Gets the bounded debt price for a given vToken (view variant)

function getBoundedDebtPriceView(address vToken) external view returns (uint256 debtPrice)
NameTypeDescription
vTokenaddressvToken address
NameTypeDescription
debtPriceuint256The bounded debt price

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)
NameTypeDescription
vTokenaddressvToken address
NameTypeDescription
collateralPriceuint256The bounded collateral price
debtPriceuint256The bounded debt price

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) external
NameTypeDescription
assetaddressThe underlying asset address
newMinuint128The new minimum price
  • MinPriceUpdated
  • Only authorized keeper addresses
  • 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

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) external
NameTypeDescription
assetaddressThe underlying asset address
newMaxuint128The new maximum price
  • MaxPriceUpdated
  • Only authorized keeper addresses
  • 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

Exits protection mode for a given asset

function exitProtectionMode(address asset) external
NameTypeDescription
assetaddressThe underlying asset address
  • ProtectionModeExited
  • Only authorized monitor/keeper addresses
  • ProtectedPriceInactive if protection is not currently active
  • CooldownNotElapsed if cooldown period has not elapsed
  • PriceRangeNotConverged if window range is still above exit threshold

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) external
NameTypeDescription
actionsstruct IDeviationBoundedOracle.KeeperActionItem[]The list of keeper actions to apply
  • MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited
  • Only authorized keeper addresses
  • InvalidKeeperAction if an item carries an unsupported action enum value

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_) external
NameTypeDescription
tokenConfig_struct IDeviationBoundedOracle.TokenConfigInputToken config input for the asset
  • ProtectionInitialized
  • BoundedPricingWhitelistUpdated
  • Only Governance
  • 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

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_) external
NameTypeDescription
tokenConfigs_struct IDeviationBoundedOracle.TokenConfigInput[]Array of token config inputs, one per asset
  • ProtectionInitialized for each asset
  • BoundedPricingWhitelistUpdated for each asset
  • Only Governance
  • InvalidArrayLength if the input array is empty
  • Any error raised by per-item validation (see setTokenConfig)

Sets the cooldown period for an asset

function setCooldownPeriod(address asset, uint64 newCooldown) external
NameTypeDescription
assetaddressThe underlying asset address
newCooldownuint64The new cooldown period in seconds
  • CooldownPeriodSet
  • Only Governance

Sets the trigger and reset thresholds for an asset

function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external
NameTypeDescription
assetaddressThe underlying asset address
newTriggerThresholduint256The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.
newResetThresholduint256The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.
  • TriggerThresholdSet if the trigger threshold changed
  • ResetThresholdSet if the reset threshold changed
  • Only Governance
  • ThresholdBelowMinimum if newTriggerThreshold is below 5%
  • ThresholdAboveMaximum if newTriggerThreshold is above 50%
  • InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold

Sets whether an asset is enabled for bounded pricing

function setAssetBoundedPricingEnabled(address asset, bool enabled) external
NameTypeDescription
assetaddressThe underlying asset address
enabledboolWhether bounded pricing should be enabled for the asset
  • BoundedPricingWhitelistUpdated
  • Only Governance
  • ProtectedPriceActive if trying to disable an asset while protection is active

Toggles transient caching of the bounded (collateral, debt) pair for an asset

function setCachingEnabled(address asset, bool enabled) external
NameTypeDescription
assetaddressThe underlying asset address
enabledboolWhether transient caching is enabled for this asset
  • CachingEnabledUpdated
  • Only Governance
  • MarketNotInitialized if the asset has not been initialized

Returns all asset addresses that have ever been initialized

function getInitializedAssets() external view returns (address[])
NameTypeDescription
[0]address[]Array of all initialized asset addresses

Checks if an asset is whitelisted for bounded pricing

function isBoundedPricingEnabled(address asset) external view returns (bool)
NameTypeDescription
assetaddressThe underlying asset address
NameTypeDescription
[0]boolTrue if the asset is whitelisted

Checks if the asset is currently using the protected (bounded) price

function currentlyUsingProtectedPrice(address asset) external view returns (bool)
NameTypeDescription
assetaddressThe underlying asset address
NameTypeDescription
[0]boolTrue if the asset is currently using the protected price instead of spot

Returns all currently whitelisted asset addresses

function getAllBoundedPricingEnabledAssets() external view returns (address[])
NameTypeDescription
[0]address[]result Array of whitelisted asset addresses

Checks if protection can be exited for an asset

function canExitProtection(address asset) external view returns (bool)
NameTypeDescription
assetaddressThe underlying asset address
NameTypeDescription
[0]boolTrue if protection can be disabled

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)
NameTypeDescription
assetsaddress[]Array of asset addresses to check
proposedMinsuint128[]Keeper’s off-chain window minimum prices
proposedMaxsuint128[]Keeper’s off-chain window maximum prices
NameTypeDescription
needsMinUpdatebool[]Whether minPrice drift exceeds deadband for each asset
needsMaxUpdatebool[]Whether maxPrice drift exceeds deadband for each asset
  • InvalidArrayLength if the input array lengths do not match