DeviationSentinel
DeviationSentinel
The DeviationSentinel is a Venus periphery contract that monitors price deviations between the ResilientOracle and a DEX-based SentinelOracle. When deviations exceed configured thresholds, it routes emergency actions through the EBrake contract to pause market actions and zero collateral factors, protecting the protocol from price manipulation or oracle failures.
Overview
Price oracle reliability is critical for lending protocols. A compromised or malfunctioning oracle can lead to undercollateralized borrows or improper liquidations. The DeviationSentinel mitigates this risk by continuously comparing prices from two independent sources and taking protective action when they diverge beyond acceptable limits.
The system consists of five contracts:
DeviationSentinel
Detects price deviations and routes emergency actions through EBrake
EBrake
Executes emergency actions (pauses, CF decrease) on the Comptroller
SentinelOracle
Aggregator oracle routing to DEX oracles or direct prices
UniswapOracle
Fetches prices from Uniswap V3 pools
PancakeSwapOracle
Fetches prices from PancakeSwap V3 pools
Economic Rationale
The deviation response logic is designed to counter specific attack vectors that arise when oracle prices diverge from real market prices.
When DEX Price > Oracle Price (borrow attack):
Attacker deposits an asset (e.g., BNB) as collateral
Borrows the mispriced token at its undervalued oracle price
Sells the borrowed token on DEX at the higher DEX price
Repeats until protocol liquidity is drained
Action: Pause borrowing for the affected asset.
When DEX Price < Oracle Price (collateral attack):
Attacker deposits the mispriced token as collateral, valued at the higher oracle price
Borrows other assets up to the loan-to-value limit
Sells or hedges the collateral token at the lower DEX price
Walks away with profit if the protocol later realigns, leaving bad debt
Action: Set collateral factor to 0 and pause supply for the affected asset.
Pauses trigger only for large price deviations (e.g., 15%-50%), not for minor discrepancies (1%-10%), to avoid unnecessary interruptions from normal pool volatility. Small deviations are not economically viable for attackers.
Deviation Response Logic
When a deviation is detected, the response depends on the direction:
Sentinel price > Oracle price
Pause borrowing via EBrake
Prevents borrowing out undervalued assets
Sentinel price ≤ Oracle price
Zero collateral factor and pause supply via EBrake
Prevents supplying overvalued assets as collateral
DeviationSentinel can only tighten restrictions. Recovery (unpausing, restoring collateral factors) is handled exclusively via a governance VIP, which calls the corresponding EBrake snapshot reset functions after restoring Comptroller parameters.
Off-Chain Monitoring
An off-chain monitoring service continuously compares the ResilientOracle price with on-chain swap prices from PancakeSwap and Uniswap. When the deviation exceeds a configured threshold, the monitor calls handleDeviation via a trusted keeper address, which routes the emergency action through EBrake to pause the affected market.
The on-chain contract includes its own price validation checks to protect against false pauses caused by compromised or faulty off-chain monitors. Once the incident is resolved, a governance VIP restores all parameters on the Comptroller and calls the EBrake snapshot reset functions to prepare for future incidents.
Architecture

Inheritance
DeviationSentinel
AccessControlledV8- Governance-controlled access
SentinelOracle
AccessControlledV8- Governance-controlled access
UniswapOracle / PancakeSwapOracle
AccessControlledV8- Governance-controlled access
State Variables
DeviationSentinel
Immutable
EBRAKE
IEBrake
EBrake contract through which all emergency actions are executed
RESILIENT_ORACLE
ResilientOracleInterface
Primary oracle for reference prices
SENTINEL_ORACLE
OracleInterface
DEX-based oracle for comparison prices
Mutable
tokenConfigs
mapping(address => DeviationConfig)
Deviation threshold and enabled status per token
trustedKeepers
mapping(address => bool)
Addresses authorized to call handleDeviation
Constants
MAX_DEVIATION
100
Maximum configurable deviation (100%)
SentinelOracle
tokenConfigs
mapping(address => TokenConfig)
Maps tokens to their DEX oracle address
directPrices
mapping(address => uint256)
Direct price overrides (0 means use DEX oracle)
UniswapOracle / PancakeSwapOracle
RESILIENT_ORACLE
ResilientOracleInterface
Immutable reference for pair token prices
tokenPools
mapping(address => address)
Maps tokens to their DEX pool address
Structs
DeviationConfig
DeviationAction
TokenConfig (SentinelOracle)
Solidity API
DeviationSentinel
handleDeviation
Checks for price deviation on a market and takes protective action. This is the core function called by trusted keepers.
Parameters
market
IVToken
The vToken market to check and act on
Behavior
Retrieves the underlying token and its deviation config
Calls
checkPriceDeviationto compare oracle pricesReturns early if no deviation is detected (prices within configured threshold)
If deviation detected:
If sentinel price > oracle price: calls
EBRAKE.pauseBorrow(market)If sentinel price ≤ oracle price: calls
EBRAKE.decreaseCF(market, 0)thenEBRAKE.pauseSupply(market)
Emits
DeviationHandledwith the prices and the action taken
Idempotency is handled by EBrake — duplicate calls for an already-paused market are no-ops on the EBrake side.
Access Requirements
Caller must be a trusted keeper
Errors
UnauthorizedKeeperif caller is not a trusted keeperMarketNotConfiguredif token has no deviation configTokenMonitoringDisabledif monitoring is disabled for the token
checkPriceDeviation
View function that checks whether a market's underlying token has a price deviation exceeding its configured threshold.
Parameters
market
IVToken
The vToken market to check
Return Values
hasDeviation
bool
True if deviation exceeds the configured threshold
oraclePrice
uint256
Price from the ResilientOracle
sentinelPrice
uint256
Price from the SentinelOracle
deviationPercent
uint256
Calculated deviation as a percentage
Deviation Calculation
If either price is 0, the function sets hasDeviation to true and deviationPercent to type(uint256).max.
setTokenConfig
Configures deviation monitoring parameters for a token.
Parameters
token
address
The underlying token address
config
DeviationConfig
Deviation threshold and status
Access Requirements
Governance only (via AccessControlManager)
Errors
ZeroAddressiftokenis the zero addressZeroDeviationifconfig.deviationis 0ExceedsMaxDeviationifconfig.deviationexceeds 100
Events
TokenConfigUpdatedemitted on success
setTokenMonitoringEnabled
Enables or disables deviation monitoring for a previously configured token.
Parameters
token
address
The underlying token address
enabled
bool
Whether monitoring should be active
Access Requirements
Governance only
Errors
ZeroAddressiftokenis the zero addressMarketNotConfiguredif token has no existing config
Events
TokenMonitoringStatusChangedemitted on success
setTrustedKeeper
Adds or removes an address from the trusted keepers list.
Parameters
keeper
address
The keeper address
isTrusted
bool
Whether the address should be trusted
Access Requirements
Governance only
Errors
ZeroAddressif keeper is the zero address
Events
TrustedKeeperUpdatedemitted on success
resetMarketState
Removed. This function no longer exists. Pre-incident state snapshots (CF, caps) are now tracked by EBrake. Use EBrake's
resetCFSnapshot,resetBorrowCapSnapshot, andresetSupplyCapSnapshotfunctions in recovery VIPs instead.
SentinelOracle
getPrice
Returns the price of an asset from the configured DEX oracle or a direct price override.
Parameters
asset
address
The token address
Return Values
uint256
Asset price in (36 - asset decimals) format
Price Resolution Order
If
directPrices[asset]is non-zero, return itOtherwise, fetch from the configured DEX oracle
Errors
TokenNotConfiguredif no oracle is configured and no direct price is set
setTokenOracleConfig
Associates a token with a DEX oracle for price fetching.
Parameters
token
address
The underlying token address
oracle
address
The DEX oracle address
Access Requirements
Governance only
Errors
ZeroAddressif either address is zero
Events
TokenOracleConfigUpdatedemitted on success
setDirectPrice
Sets a direct price override for a token. Set to 0 to revert to DEX oracle pricing.
Parameters
token
address
The underlying token address
price
uint256
The price override (0 to use DEX oracle)
Access Requirements
Governance only
Events
DirectPriceUpdatedemitted on success
UniswapOracle
getPrice
Returns the price of a token derived from its Uniswap V3 pool.
Parameters
asset
address
The token address
Return Values
uint256
Asset price in (36 - asset decimals) format
Price Calculation
Reads
sqrtPriceX96from the Uniswap V3 pool'sslot0Computes
priceX96 = (sqrtPriceX96)² / Q96Determines target token position (token0 or token1)
Fetches the reference token price from ResilientOracle
Converts the pool ratio to a USD price using the reference price
Errors
TokenNotConfiguredif no pool is configured for the tokenInvalidPoolif the configured pool does not contain the token
setPoolConfig
Associates a token with a Uniswap V3 pool.
Parameters
token
address
The underlying token address
pool
address
The Uniswap V3 pool address
Access Requirements
Governance only
Errors
ZeroAddressif either address is zero
Events
PoolConfigUpdatedemitted on success
PancakeSwapOracle
getPrice
Returns the price of a token derived from its PancakeSwap V3 pool. Identical behavior to UniswapOracle.getPrice.
setPoolConfig
Associates a token with a PancakeSwap V3 pool. Identical behavior to UniswapOracle.setPoolConfig.
Events
DeviationSentinel Events
TokenConfigUpdated
token, config
Deviation config set for a token
TokenMonitoringStatusChanged
token, enabled
Monitoring toggled for a token
TrustedKeeperUpdated
keeper, isTrusted
Keeper added or removed
DeviationHandled
market, oraclePrice, sentinelPrice, action
Deviation detected and acted on; action is a DeviationAction enum value
Pause and collateral factor events are now emitted by EBrake (ActionPaused, CollateralFactorDecreased) rather than by DeviationSentinel directly.
SentinelOracle Events
TokenOracleConfigUpdated
token, oracle
Token associated with DEX oracle
DirectPriceUpdated
token, price
Direct price override set
UniswapOracle / PancakeSwapOracle Events
PoolConfigUpdated
token, pool
Token associated with DEX pool
Security Considerations
Access Control
Governance Functions: All configuration functions (
setTokenConfig,setTrustedKeeper,setTokenMonitoringEnabled) are restricted viaAccessControlManagerKeeper Functions:
handleDeviationis restricted to trusted keepers via theonlyKeepermodifierDirect Price Overrides: The
setDirectPricefunction onSentinelOracleis governance-controlled to prevent price manipulation
Separation of Detection and Execution
DeviationSentinel contains only detection logic. All Comptroller interactions (pausing, CF changes) are executed by EBrake. This means:
A compromised keeper can only trigger EBrake actions, not call the Comptroller directly
EBrake enforces its own "tighten only" invariant independently — the sentinel cannot unpause or restore CF even if its logic were modified
Pre-incident state snapshots (original CF, borrow caps, supply caps) are tracked by EBrake, not DeviationSentinel
Recovery
Recovery from a sentinel-triggered freeze requires a governance VIP that:
Restores Comptroller parameters (unpause actions, restore CF)
Calls the appropriate EBrake snapshot reset functions (
resetCFSnapshot,resetBorrowCapSnapshot,resetSupplyCapSnapshot) to clear the stored snapshots
Deployment
See Deployed Contracts for current addresses.
Audits
DeviationSentinel undergoes security audits before mainnet deployment. Audit reports are available in the venus-periphery repository.
Last updated

