EBrake
EBrake
EBrake (Emergency Brake) is a Venus periphery contract that acts as an emergency action router for the protocol. It exposes a curated set of Comptroller emergency functions behind Access Control Manager (ACM) permissions, allowing the multisig, automated monitoring contracts, and trusted third-party services to rapidly tighten protocol parameters during an incident — without waiting for a governance VIP.
Overview
During a security incident, every block of delay increases potential losses. EBrake provides a fast-path for protective actions that are safe to take without governance: pausing market actions, reducing collateral factors, and lowering supply/borrow caps. It enforces a strict "tighten only, never loosen" invariant — the worst outcome from a compromised EBrake caller is a temporary freeze, never fund loss.
Recovery from any EBrake action always goes through a governance VIP, which also calls the snapshot reset functions to prepare EBrake for future incidents.
Callers and Integration Patterns
EBrake is designed to be called from three types of principals:
Venus Multisig
Direct ACM whitelist
Full access to all EBrake functions. Used during manual incident response.
On-chain monitors
Direct ACM whitelist
Contracts like DeviationSentinel that contain their own detection logic and call EBrake on trigger.
Third-party monitors
Safe Module on multisig
External services (e.g. Hypernative) get a dedicated Safe Module that scopes which functions they can call.
This architecture keeps detection logic isolated from execution. EBrake only handles execution — it holds no detection logic of its own.
Safety Invariant
EBrake can only tighten restrictions, never loosen them. This means it intentionally cannot:
Unpause — recovery is always via governance VIP
Pause REPAY or SEIZE — users must always be able to repay to avoid liquidation, and liquidations must always work to prevent bad debt
Pause the protocol —
setProtocolPausedblocks repay and liquidation, which violates the safety invariantLower liquidation threshold — this would instantly make healthy positions liquidatable
Increase caps — caps can only be decreased to reduce exposure
Enable forced liquidation — this would make any borrower liquidatable regardless of their collateral ratio
Target individual users — prevents griefing specific addresses
Change the oracle or liquidation incentive — would cause mass mispricing or alter liquidation economics for all users
Worst-case if EBrake is compromised:
Pauses minting, borrowing, redeeming, or transfers (inconvenient, no fund loss)
Zeros supply/borrow caps (blocks new positions; existing positions are unaffected)
Decreases collateral factor (blocks new borrows against an asset; does not liquidate existing positions since LT is unchanged)
Pauses flash loans (blocks flash loan attack vector, no user impact)
Recovery is a governance VIP that restores all parameters — a temporary freeze, not a catastrophic loss.
Pre-Incident Snapshots
Whenever EBrake tightens a parameter for the first time, it snapshots the original value using a first-write-wins strategy. These snapshots are stored in marketStates and serve as a reference for governance to restore to when issuing a recovery VIP. After restoring values on-chain, governance calls the corresponding reset function (resetCFSnapshot, resetBorrowCapSnapshot, resetSupplyCapSnapshot) to clear the snapshot and prepare EBrake for future incidents.
BSC vs Non-BSC Differences
EBrake is deployed on all Venus chains, but its behavior differs based on the underlying comptroller:
Feature
BSC — Diamond Comptroller (IS_ISOLATED_POOL=false)
Non-BSC — IL Comptroller (IS_ISOLATED_POOL=true)
decreaseCF(market, newCF)
Iterates all pools (corePoolId to lastPoolId), silently skips pools already at or below newCF
Applies to the single market; reverts if newCF > currentCF
decreaseCF(market, poolId, newCF)
Supported — targets a single pool (core or e-mode)
Reverts with NotSupportedOnIsolatedPool
pauseFlashLoan()
Supported — flash loans only exist on Diamond
Not ACM-granted
disablePoolBorrow(poolId, market)
Supported — per-pool granular borrow disable
Not ACM-granted
revokeFlashLoanAccess(account)
Supported — removes account from flash loan whitelist
Not ACM-granted
E-mode pool support
Yes — via poolId > 0
No — no pool concept
All other functions (pauseActions, pauseSupply, pauseBorrow, pauseRedeem, pauseTransfer, setMarketBorrowCaps, setMarketSupplyCaps) are ABI-compatible across both comptroller types and work identically on all chains.
Inheritance
AccessControlledV8— All functions are gated via the Venus Access Control Manager
State Variables
Immutable
COMPTROLLER
ICorePoolComptroller
The Venus Comptroller this EBrake instance operates on. On BSC this is a Diamond proxy; on other chains it is an IL comptroller.
IS_ISOLATED_POOL
bool
Set at deployment. true for IL comptroller (isolated-pools); false for Diamond (BSC).
Mutable
marketStates
mapping(address => MarketState)
Pre-incident snapshots keyed by vToken market address, captured on the first tightening.
Structs
MarketState
Holds the pre-incident state captured by EBrake before any tightening action. Nested mapping fields (poolCFs, poolLTs) must be read via getMarketCFSnapshot(). Cap fields are accessible via the auto-generated marketStates() getter.
borrowCap
Borrow cap value before EBrake decreased it.
supplyCap
Supply cap value before EBrake decreased it.
borrowCapSnapshotted
True if a borrow cap snapshot has been recorded.
supplyCapSnapshotted
True if a supply cap snapshot has been recorded.
poolCFs
Mapping of poolId to the collateral factor before EBrake decreased it.
poolLTs
Mapping of poolId to the liquidation threshold at snapshot time.
Solidity API
EBrake
pauseActions
Pause multiple actions on multiple markets in a single call.
Parameters
markets
address[]
The vToken market addresses to pause actions on.
actions
IComptroller.Action[]
The actions to pause.
Behavior
Calls setActionsPaused(markets, actions, true) on the comptroller for the provided markets and actions. Only MINT, REDEEM, BORROW, and TRANSFER are allowed. Passing REPAY, SEIZE, LIQUIDATE, ENTER_MARKET, or EXIT_MARKET reverts.
Access Requirements
ACM permission required:
pauseActions(address[],uint8[])
Errors
EmptyArrayifmarketsoractionsis emptyForbiddenActionif any action is not one of the four permitted actions
Events
ActionsPausedemitted on success
pauseSupply
Pause supply (mint) on a single market. Blocks new deposits; existing suppliers can still redeem.
Parameters
market
address
The vToken market address.
Access Requirements
ACM permission required:
pauseSupply(address)
Events
ActionPausedemitted withaction = MINT
pauseRedeem
Pause redeem on a single market. Blocks withdrawals. Use when draining must be stopped immediately.
Parameters
market
address
The vToken market address.
Access Requirements
ACM permission required:
pauseRedeem(address)
Events
ActionPausedemitted withaction = REDEEM
pauseBorrow
Pause borrowing on a single market. Blocks new borrows; existing borrowers can still repay.
Parameters
market
address
The vToken market address.
Access Requirements
ACM permission required:
pauseBorrow(address)
Events
ActionPausedemitted withaction = BORROW
pauseTransfer
Pause vToken transfers on a single market. Blocks vToken movement, preventing an attacker from moving stolen collateral.
Parameters
market
address
The vToken market address.
Access Requirements
ACM permission required:
pauseTransfer(address)
Events
ActionPausedemitted withaction = TRANSFER
pauseFlashLoan
Pause flash loans across the core pool.
Behavior
Calls setFlashLoanPaused(true) on the Diamond comptroller. Idempotent: silently returns without emitting an event when flash loans are already paused, so FlashLoanPaused is always a true state-change signal.
Access Requirements
ACM permission required:
pauseFlashLoan()BSC (Diamond) only — not ACM-granted on IL chains
Events
FlashLoanPausedemitted on state change (not emitted if already paused)
disablePoolBorrow
Disable borrowing for a market in a specific pool, leaving all other pools unaffected.
Parameters
poolId
uint96
The pool identifier (0 = core pool, >0 = e-mode pools).
market
address
The vToken market address.
Behavior
Calls setIsBorrowAllowed(poolId, market, false) on the Diamond comptroller. The false argument is hardcoded — EBrake can only disable, never re-enable. This flag is independent of pauseBorrow(market), which flips the global _actionPaused[market][BORROW] flag across every pool. Both flags must allow borrowing for borrows to proceed in a given pool/market; recovery therefore requires governance to clear both if both were set.
Access Requirements
ACM permission required:
disablePoolBorrow(uint96,address)BSC (Diamond) only — not ACM-granted on IL chains
Events
PoolBorrowDisabledemitted on success
revokeFlashLoanAccess
Remove a single account from the flash loan whitelist.
Parameters
account
address
The account whose flash loan access is revoked.
Behavior
Calls setWhiteListFlashLoanAccount(account, false) on the Diamond comptroller. The surgical alternative to pauseFlashLoan() — use when a single whitelisted integrator is compromised and a full flash loan pause would harm innocent users. The false is hardcoded; re-granting access requires governance.
Access Requirements
ACM permission required:
revokeFlashLoanAccess(address)BSC (Diamond) only — not ACM-granted on IL chains
Errors
ZeroAddressifaccountis the zero address
Events
FlashLoanAccessRevokedemitted on success
decreaseCF (batch)
Decrease collateral factor to newCF for a market across all relevant pools. Liquidation threshold is left unchanged.
Parameters
market
address
The vToken market address whose CF should be decreased.
newCF
uint256
The new collateral factor value.
Behavior
Diamond (BSC): Iterates all pools from
corePoolIdtolastPoolId. AppliesnewCFonly to pools wherecurrentCF > newCF; silently skips pools already at or belownewCFand unlisted pools. Does not revert due to CF comparison — use the per-pool overload for strict enforcement on a specific pool.IL (non-BSC): Applies to the single market entry. Reverts with
CFExceedsCurrentifnewCF > currentCF. No-ops (returns without event) ifnewCF == currentCF.
Decreasing CF blocks or limits new borrows against the asset. It does not make existing positions liquidatable — that would require lowering LT, which EBrake cannot do.
Access Requirements
ACM permission required:
decreaseCF(address,uint256)
Errors
MarketNotListedif the market is not listed in the core pool (Diamond) or the comptroller (IL)CFExceedsCurrentifnewCF > currentCF(IL only; Diamond silently skips)SetCollateralFactorFailedif the comptroller returns a non-zero error code (Diamond only)
Events
CollateralFactorDecreasedemitted per pool where CF was actually changed
decreaseCF (per pool)
Decrease collateral factor to newCF for a market in a specific pool.
Parameters
market
address
The vToken market address whose CF should be decreased.
poolId
uint96
The pool ID (0 for core pool, >0 for e-mode pools).
newCF
uint256
The new collateral factor value. Must be ≤ current CF in the pool.
Behavior
Targets a single pool. No-ops (returns without event) if newCF == currentCF. Unlike the batch overload, this reverts with CFExceedsCurrent if newCF > currentCF, making it suitable for multisig use where strict enforcement per pool is required.
Access Requirements
ACM permission required:
decreaseCF(address,uint96,uint256)BSC (Diamond) only — reverts with
NotSupportedOnIsolatedPoolon IL chains
Errors
NotSupportedOnIsolatedPoolif called on an IL comptroller deploymentMarketNotListedif the market is not listed in the given poolCFExceedsCurrentifnewCF > currentCFSetCollateralFactorFailedif the comptroller returns a non-zero error code
Events
CollateralFactorDecreasedemitted on success
setMarketBorrowCaps
Decrease borrow caps on one or more markets. Setting to 0 blocks all new borrows. Existing borrows are never affected by caps.
Parameters
markets
address[]
The vToken market addresses to adjust borrow caps on.
newBorrowCaps
uint256[]
The new borrow cap values. Each must be ≤ current cap (equality is a no-op; greater reverts).
Behavior
Iterates the markets array. Elements equal to the current cap are silently skipped (no snapshot pollution). Elements strictly lower than the current cap trigger a cap decrease and record a first-write-wins snapshot. Only calls the comptroller if at least one element actually decreased.
Access Requirements
ACM permission required:
setMarketBorrowCaps(address[],uint256[])
Errors
EmptyArrayifmarketsis emptyArrayLengthMismatchifmarketsandnewBorrowCapshave different lengthsCapExceedsCurrentif any new cap is strictly greater than the current cap
Events
BorrowCapsDecreasedemitted when at least one cap was actually decreased
setMarketSupplyCaps
Decrease supply caps on one or more markets. Setting to 0 blocks all new deposits. Existing deposits are never affected by caps.
Parameters
markets
address[]
The vToken market addresses to adjust supply caps on.
newSupplyCaps
uint256[]
The new supply cap values. Each must be ≤ current cap (equality is a no-op; greater reverts).
Behavior
Identical to setMarketBorrowCaps but operates on supply caps.
Access Requirements
ACM permission required:
setMarketSupplyCaps(address[],uint256[])
Errors
EmptyArrayifmarketsis emptyArrayLengthMismatchifmarketsandnewSupplyCapshave different lengthsCapExceedsCurrentif any new cap is strictly greater than the current cap
Events
SupplyCapsDecreasedemitted when at least one cap was actually decreased
resetCFSnapshot
Reset the stored CF/LT snapshot for a market. Called by governance as part of a recovery VIP after restoring collateral factors.
Parameters
market
address
The vToken market address whose CF snapshot to clear.
Behavior
Clears poolCFs and poolLTs for all relevant pools (all pools on Diamond; pool 0 on IL). Does not touch cap snapshots. After this call, the next decreaseCF call will capture a fresh pre-incident value.
Access Requirements
ACM permission required:
resetCFSnapshot(address)
Events
CFSnapshotResetemitted on success
resetBorrowCapSnapshot
Reset the stored borrow cap snapshot for a market. Called by governance after restoring the borrow cap.
Parameters
market
address
The vToken market address whose borrow cap snapshot to clear.
Behavior
Clears borrowCap and sets borrowCapSnapshotted = false. Does not touch supply cap or CF snapshots.
Access Requirements
ACM permission required:
resetBorrowCapSnapshot(address)
Events
BorrowCapSnapshotResetemitted on success
resetSupplyCapSnapshot
Reset the stored supply cap snapshot for a market. Called by governance after restoring the supply cap.
Parameters
market
address
The vToken market address whose supply cap snapshot to clear.
Behavior
Clears supplyCap and sets supplyCapSnapshotted = false. Does not touch borrow cap or CF snapshots.
Access Requirements
ACM permission required:
resetSupplyCapSnapshot(address)
Events
SupplyCapSnapshotResetemitted on success
getMarketCFSnapshot
Read the stored collateral factor and liquidation threshold snapshot for a market in a specific pool.
Parameters
market
address
The vToken market address.
poolId
uint96
The pool ID (0 for IL chains or the core pool on Diamond).
Return Values
cf
uint256
The collateral factor stored before EBrake decreased it. 0 if no snapshot exists.
lt
uint256
The liquidation threshold at the time of the snapshot. 0 if no snapshot exists.
Events
ActionsPaused
caller, markets[], actions[]
Emitted when actions are batch-paused on markets.
ActionPaused
caller, market, action
Emitted when a single action is paused on a market.
FlashLoanPaused
caller
Emitted when flash loans are paused (BSC only).
PoolBorrowDisabled
caller, poolId, market
Emitted when pool-level borrow is disabled (BSC only).
FlashLoanAccessRevoked
caller, account
Emitted when an account's flash loan access is revoked (BSC only).
CollateralFactorDecreased
caller, market, poolId, newCF
Emitted per pool where CF was actually decreased.
BorrowCapsDecreased
caller, markets[], newBorrowCaps[]
Emitted when at least one borrow cap was decreased.
SupplyCapsDecreased
caller, markets[], newSupplyCaps[]
Emitted when at least one supply cap was decreased.
CFSnapshotReset
market
Emitted when a market's CF/LT snapshot is cleared.
BorrowCapSnapshotReset
market
Emitted when a market's borrow cap snapshot is cleared.
SupplyCapSnapshotReset
market
Emitted when a market's supply cap snapshot is cleared.
Errors
ForbiddenAction
action
A forbidden action (REPAY, SEIZE, etc.) was passed to batch pause.
ZeroAddress
—
A zero address was passed where a valid address is required.
MarketNotListed
poolId, market
The market is not listed in the given pool.
SetCollateralFactorFailed
errorCode
setCollateralFactor returned a non-zero error code (Diamond only).
EmptyArray
—
An empty array was passed where at least one element is required.
ArrayLengthMismatch
expected, actual
Array lengths do not match.
CapExceedsCurrent
market, currentCap, requestedCap
Attempted to set a cap higher than the current value.
NotSupportedOnIsolatedPool
—
A Diamond-only function was called on an IL comptroller deployment.
CFExceedsCurrent
market, poolId, currentCF, requestedCF
Attempted to set a collateral factor higher than the current value.
Security Considerations
Access Control
All functions are gated via the Venus ACM. No function can be called without an explicit ACM permission grant. The set of permissions granted at deployment differs between BSC and non-BSC chains — Diamond-only functions (pauseFlashLoan, disablePoolBorrow, revokeFlashLoanAccess, decreaseCF(address,uint96,uint256)) are not granted on IL chains.
Snapshot Integrity
EBrake uses first-write-wins snapshots to capture the pre-incident state:
CF/LT snapshots:
_snapshotCFonly writes ifpoolCFs[poolId] == 0andcurrentCF > 0. If the CF was already 0 before EBrake acted, nothing is recorded.Cap snapshots: written only on the first actual decrease (equality skipped to avoid polluting the snapshot with a no-op call).
Each snapshot type (CF, borrow cap, supply cap) is independent and has its own reset function. Resetting one does not affect the others.
Collateral Factor vs Liquidation Threshold
EBrake decreases CF but always preserves LT when calling setCollateralFactor. This is intentional:
Decreasing CF prevents new borrows against the asset but does not affect existing positions.
Decreasing LT would instantly make previously healthy positions liquidatable, harming innocent users.
Recovery VIPs may restore both CF and LT to their original values, which is why both are included in the snapshot.
Per-Pool vs Global Borrow Disable (BSC)
On BSC there are two independent borrow flags:
Global pause (
pauseBorrow→_actionPaused[market][BORROW]): applies across every pool for the market.Per-pool disable (
disablePoolBorrow→isBorrowAllowed[poolId][market]): applies only to the targeted pool, leaving other pools unaffected.
Both flags must allow borrowing for borrows to actually proceed. A recovery VIP must clear both flags if both were set by EBrake.
Deployment
EBrake is deployed behind a TransparentUpgradeableProxy. The IS_ISOLATED_POOL flag is set in the constructor and cannot be changed. On BSC, IS_ISOLATED_POOL = false; on all other chains, IS_ISOLATED_POOL = true.
BNB Chain Mainnet
EBrake (Proxy)
EBrake (Implementation)
BNB Chain Testnet
EBrake (Proxy)
EBrake (Implementation)
Audits
EBrake undergoes security audits before mainnet deployment. Audit reports are available in the venus-periphery repository.
Last updated

