EBrake
EBrake
Section titled “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, and from v1.3.0 three Liquidity Hub pause forwarders, 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.
Version scope: This API reference follows
venus-peripheryv1.3.0. EBrake is deployed behind upgradeable proxies. Its effective behavior depends on the current implementation, immutable Comptroller/type pair, ACM grants, and the Comptroller version on each network; verify those values from the deployment registry and explorer before incident use.
Overview
Section titled “Overview”During a security incident, every block of delay can increase potential losses. EBrake provides a fast path for selected protective actions without waiting for a governance proposal: pausing market actions, reducing collateral factors, lowering supply/borrow caps, and pausing a Liquidity Hub, one of its YieldGroups, or a resource. The contract restricts these mutators to tightening configured parameters, but a mistaken or compromised caller can still block user actions, reduce borrowing capacity, or prolong an incident. The contract does not guarantee that downstream economic loss is impossible.
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
Section titled “Callers and Integration Patterns”EBrake is designed to be called from three types of principals:
| Caller | Access Method | Description |
|---|---|---|
| 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
Section titled “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 invariant - Lower 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
Actions available to a compromised authorized caller include:
- Pausing minting, borrowing, redeeming, or transfers, which can delay entry and exit operations
- Zeroing supply/borrow caps, which blocks additional exposure and can affect later account actions
- Decreasing collateral factor, which does not directly change liquidation eligibility while liquidation threshold is preserved, but can restrict later borrows or redemptions
- Pausing flash loans, which can block integrations that depend on that facility
- Pausing a whole Liquidity Hub (
pauseHub), which blocks every lender deposit and withdrawal on that Hub until it is unpaused - Pausing one of a Hub’s YieldGroups or a single resource, which closes only that route: the Hub’s outer queues skip a paused YieldGroup and its inner queues skip a paused resource, so deposits and withdrawals continue through healthy sibling routes while they have the capacity and liquidity. A paused resource is still counted in the Hub’s NAV, and shares still trade against that NAV, which is why the NAV sentinel pauses the whole Hub rather than the resource
Recovery requires a governance VIP that restores the affected parameters and clears the corresponding snapshots. Operational and economic consequences depend on the affected markets and recovery time.
Pre-Incident Snapshots
Section titled “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
Section titled “BSC vs Non-BSC Differences”EBrake supports two Comptroller families. The currently published registry lists deployments on only a subset of Venus networks, and behavior differs by the configured 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 |
pauseHub, pauseHubYieldGroup, pauseHubResource | Supported, where the deployed implementation has them | 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
Section titled “Inheritance”AccessControlledV8— privileged state-changing functions are gated through the Venus Access Control Manager; initialization and public views are not ACM actions
State Variables
Section titled “State Variables”Immutable
Section titled “Immutable”| Variable | Type | Description |
|---|---|---|
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
Section titled “Mutable”| Variable | Type | Description |
|---|---|---|
marketStates | mapping(address => MarketState) | Pre-incident snapshots keyed by vToken market address, captured on the first tightening. |
Structs
Section titled “Structs”MarketState
Section titled “MarketState”struct MarketState { uint256 borrowCap; uint256 supplyCap; bool borrowCapSnapshotted; bool supplyCapSnapshotted; mapping(uint96 => uint256) poolCFs; mapping(uint96 => uint256) poolLTs;}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.
| Field | Description |
|---|---|
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
Section titled “Solidity API”EBrake
Section titled “EBrake”initialize
Section titled “initialize”Initializes the proxy with its Access Control Manager. The implementation constructor fixes COMPTROLLER and IS_ISOLATED_POOL and disables direct initialization of the implementation.
function initialize(address accessControlManager_) external initializerThis is a one-time proxy initialization function; it is not an ACM-gated incident action.
pauseActions
Section titled “pauseActions”Pause multiple actions on multiple markets in a single call.
function pauseActions(address[] calldata markets, IComptroller.Action[] calldata actions) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| markets | address[] | The vToken market addresses to pause actions on. |
| actions | IComptroller.Action[] | The actions to pause. |
Behavior
Section titled “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
Section titled “Access Requirements”- ACM permission required:
pauseActions(address[],uint8[])
Errors
Section titled “Errors”EmptyArrayifmarketsoractionsis emptyForbiddenActionif any action is not one of the four permitted actions
Events
Section titled “Events”ActionsPausedemitted on success
pauseSupply
Section titled “pauseSupply”Pause supply (mint) on a single market. Blocks new deposits; existing suppliers can still redeem.
function pauseSupply(address market) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address. |
Access Requirements
Section titled “Access Requirements”- ACM permission required:
pauseSupply(address)
Events
Section titled “Events”ActionPausedemitted withaction = MINT
pauseRedeem
Section titled “pauseRedeem”Pause redeem on a single market. Blocks withdrawals. Use when draining must be stopped immediately.
function pauseRedeem(address market) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address. |
Access Requirements
Section titled “Access Requirements”- ACM permission required:
pauseRedeem(address)
Events
Section titled “Events”ActionPausedemitted withaction = REDEEM
pauseBorrow
Section titled “pauseBorrow”Pause borrowing on a single market. Blocks new borrows; existing borrowers can still repay.
function pauseBorrow(address market) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address. |
Access Requirements
Section titled “Access Requirements”- ACM permission required:
pauseBorrow(address)
Events
Section titled “Events”ActionPausedemitted withaction = BORROW
pauseTransfer
Section titled “pauseTransfer”Pause vToken transfers on a single market. Blocks vToken movement, preventing an attacker from moving stolen collateral.
function pauseTransfer(address market) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address. |
Access Requirements
Section titled “Access Requirements”- ACM permission required:
pauseTransfer(address)
Events
Section titled “Events”ActionPausedemitted withaction = TRANSFER
pauseFlashLoan
Section titled “pauseFlashLoan”Pause flash loans across the core pool.
function pauseFlashLoan() externalBehavior
Section titled “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
Section titled “Access Requirements”- ACM permission required:
pauseFlashLoan() - BSC (Diamond) only — not ACM-granted on IL chains
Events
Section titled “Events”FlashLoanPausedemitted on state change (not emitted if already paused)
disablePoolBorrow
Section titled “disablePoolBorrow”Disable borrowing for a market in a specific pool, leaving all other pools unaffected.
function disablePoolBorrow(uint96 poolId, address market) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| poolId | uint96 | The pool identifier (0 = core pool, >0 = e-mode pools). |
| market | address | The vToken market address. |
Behavior
Section titled “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
Section titled “Access Requirements”- ACM permission required:
disablePoolBorrow(uint96,address) - BSC (Diamond) only — not ACM-granted on IL chains
Events
Section titled “Events”PoolBorrowDisabledemitted on success
revokeFlashLoanAccess
Section titled “revokeFlashLoanAccess”Remove a single account from the flash loan whitelist.
function revokeFlashLoanAccess(address account) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| account | address | The account whose flash loan access is revoked. |
Behavior
Section titled “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
Section titled “Access Requirements”- ACM permission required:
revokeFlashLoanAccess(address) - BSC (Diamond) only — not ACM-granted on IL chains
Errors
Section titled “Errors”ZeroAddressifaccountis the zero address
Events
Section titled “Events”FlashLoanAccessRevokedemitted on success
pauseHub
Section titled “pauseHub”Pause an entire Liquidity Hub.
Not in the BNB Chain mainnet implementation yet. This function and the two below shipped in v1.3.0. The BNB Chain testnet implementation already has them. The live mainnet implementation 0x2D36677EcA318c9536011D53aa752F042dd01DE8 predates them and carries none of their selectors, so no Hub can be paused through EBrake until the proxy is upgraded.
function pauseHub(address hub) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| hub | address | The Hub to pause. |
Behavior
Section titled “Behavior”Calls pauseHub() on the Hub, which blocks deposits, withdrawals and reallocate across every Source it owns; emergencyReallocate and sweep still work. Idempotent: returns without emitting when hubPaused() is already true. Reverts ZeroAddress on a zero address.
Access Requirements
Section titled “Access Requirements”- ACM permission required:
pauseHub(address) - EBrake must additionally hold the Hub’s own
pauseHub()role, granted per Hub address
Events
Section titled “Events”HubPausedemitted on state change (not emitted if already paused)
pauseHubYieldGroup
Section titled “pauseHubYieldGroup”Pause one Source on the Hub that owns it, leaving the rest of the Hub running.
function pauseHubYieldGroup(address yieldGroup) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| yieldGroup | address | The Source to pause. |
Behavior
Section titled “Behavior”Reads the owning Hub from yieldGroup.hub(), so the caller does not pass it. Calls pauseYieldGroup(yieldGroup) on that Hub. Idempotent: returns without emitting when the Hub’s yieldGroupConfig(yieldGroup).paused is already true. Reverts ZeroAddress on a zero address.
Access Requirements
Section titled “Access Requirements”- ACM permission required:
pauseHubYieldGroup(address) - EBrake must additionally hold the Hub’s own
pauseYieldGroup(address)role
Events
Section titled “Events”HubYieldGroupPausedemitted on state change (not emitted if already paused)
pauseHubResource
Section titled “pauseHubResource”Pause one resource inside a Source, the narrowest of the three.
function pauseHubResource(address yieldGroup, address resource) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| yieldGroup | address | The Source holding the resource. |
| resource | address | The resource to pause. |
Behavior
Section titled “Behavior”Reads the resource’s paused flag from yieldGroup.resourceConfig(resource) and returns without emitting when it is already set. Otherwise calls pauseResource(resource) on the Source. Reverts ZeroAddress if either address is zero.
Note the Hub’s totalAssets() still counts a paused resource, so pausing a resource stops new flow through it without removing its value from the share price.
Access Requirements
Section titled “Access Requirements”- ACM permission required:
pauseHubResource(address,address) - EBrake must additionally hold the Source’s own
pauseResource(address)role
Events
Section titled “Events”HubResourcePausedemitted on state change (not emitted if already paused)
decreaseCF (batch)
Section titled “decreaseCF (batch)”Decrease collateral factor to newCF for a market across all relevant pools. Liquidation threshold is left unchanged.
function decreaseCF(address market, uint256 newCF) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address whose CF should be decreased. |
| newCF | uint256 | The new collateral factor value. |
Behavior
Section titled “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
Section titled “Access Requirements”- ACM permission required:
decreaseCF(address,uint256)
Errors
Section titled “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
Section titled “Events”CollateralFactorDecreasedemitted per pool where CF was actually changed
decreaseCF (per pool)
Section titled “decreaseCF (per pool)”Decrease collateral factor to newCF for a market in a specific pool.
function decreaseCF(address market, uint96 poolId, uint256 newCF) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| 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
Section titled “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
Section titled “Access Requirements”- ACM permission required:
decreaseCF(address,uint96,uint256) - BSC (Diamond) only — reverts with
NotSupportedOnIsolatedPoolon IL chains
Errors
Section titled “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
Section titled “Events”CollateralFactorDecreasedemitted on success
setMarketBorrowCaps
Section titled “setMarketBorrowCaps”Decrease borrow caps on one or more markets. Setting a cap to 0 blocks additional borrowing; it does not change debt already recorded, although the account remains subject to normal interest and liquidation rules.
function setMarketBorrowCaps(address[] calldata markets, uint256[] calldata newBorrowCaps) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| 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
Section titled “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
Section titled “Access Requirements”- ACM permission required:
setMarketBorrowCaps(address[],uint256[])
Errors
Section titled “Errors”EmptyArrayifmarketsis emptyArrayLengthMismatchifmarketsandnewBorrowCapshave different lengthsCapExceedsCurrentif any new cap is strictly greater than the current cap
Events
Section titled “Events”BorrowCapsDecreasedemitted when at least one cap was actually decreased
setMarketSupplyCaps
Section titled “setMarketSupplyCaps”Decrease supply caps on one or more markets. Setting a cap to 0 blocks additional deposits; it does not change an existing supplied balance, although a separate redeem pause can still block withdrawals.
function setMarketSupplyCaps(address[] calldata markets, uint256[] calldata newSupplyCaps) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| 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
Section titled “Behavior”Identical to setMarketBorrowCaps but operates on supply caps.
Access Requirements
Section titled “Access Requirements”- ACM permission required:
setMarketSupplyCaps(address[],uint256[])
Errors
Section titled “Errors”EmptyArrayifmarketsis emptyArrayLengthMismatchifmarketsandnewSupplyCapshave different lengthsCapExceedsCurrentif any new cap is strictly greater than the current cap
Events
Section titled “Events”SupplyCapsDecreasedemitted when at least one cap was actually decreased
resetCFSnapshot
Section titled “resetCFSnapshot”Reset the stored CF/LT snapshot for a market. Called by governance as part of a recovery VIP after restoring collateral factors.
function resetCFSnapshot(address market) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address whose CF snapshot to clear. |
Behavior
Section titled “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
Section titled “Access Requirements”- ACM permission required:
resetCFSnapshot(address)
Events
Section titled “Events”CFSnapshotResetemitted on success
resetBorrowCapSnapshot
Section titled “resetBorrowCapSnapshot”Reset the stored borrow cap snapshot for a market. Called by governance after restoring the borrow cap.
function resetBorrowCapSnapshot(address market) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address whose borrow cap snapshot to clear. |
Behavior
Section titled “Behavior”Clears borrowCap and sets borrowCapSnapshotted = false. Does not touch supply cap or CF snapshots.
Access Requirements
Section titled “Access Requirements”- ACM permission required:
resetBorrowCapSnapshot(address)
Events
Section titled “Events”BorrowCapSnapshotResetemitted on success
resetSupplyCapSnapshot
Section titled “resetSupplyCapSnapshot”Reset the stored supply cap snapshot for a market. Called by governance after restoring the supply cap.
function resetSupplyCapSnapshot(address market) externalParameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address whose supply cap snapshot to clear. |
Behavior
Section titled “Behavior”Clears supplyCap and sets supplyCapSnapshotted = false. Does not touch borrow cap or CF snapshots.
Access Requirements
Section titled “Access Requirements”- ACM permission required:
resetSupplyCapSnapshot(address)
Events
Section titled “Events”SupplyCapSnapshotResetemitted on success
getMarketCFSnapshot
Section titled “getMarketCFSnapshot”Read the stored collateral factor and liquidation threshold snapshot for a market in a specific pool.
function getMarketCFSnapshot(address market, uint96 poolId) external view returns (uint256 cf, uint256 lt)Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
| market | address | The vToken market address. |
| poolId | uint96 | The pool ID (0 for IL chains or the core pool on Diamond). |
Return Values
Section titled “Return Values”| Name | Type | Description |
|---|---|---|
| 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
Section titled “Events”| Event | Parameters | Description |
|---|---|---|
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). |
HubPaused | caller, hub | Emitted when a Liquidity Hub is paused. |
HubYieldGroupPaused | caller, hub, yieldGroup | Emitted when one Hub Source is paused. |
HubResourcePaused | caller, yieldGroup, resource | Emitted when one resource inside a Source is paused. |
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
Section titled “Errors”| Error | Parameters | Description |
|---|---|---|
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
Section titled “Security Considerations”Access Control
Section titled “Access Control”Privileged EBrake mutators require an explicit Venus ACM grant for their exact signature. Public view functions such as getMarketCFSnapshot are ungated, and initialize is protected by one-time initialization rather than ACM. The set of mutator grants differs between BSC and non-BSC chains: Diamond-only functions (pauseFlashLoan, disablePoolBorrow, revokeFlashLoanAccess, decreaseCF(address,uint96,uint256)) are not intended for IL chains. The three Hub forwarders need two grants, not one: the caller’s grant on EBrake, and EBrake’s own grant on the target, which is pauseHub() or pauseYieldGroup(address) on the Hub and pauseResource(address) on the Source. Liquidity Hubs exist only on BNB Chain.
Snapshot Integrity
Section titled “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
Section titled “Collateral Factor vs Liquidation Threshold”EBrake decreases CF but always preserves LT when calling setCollateralFactor. This is intentional:
- Decreasing CF does not directly lower LT or make an account liquidatable by itself, but it can reduce available liquidity and restrict later borrow or redeem operations for existing accounts.
- 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)
Section titled “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
Section titled “Deployment”EBrake is deployed behind a TransparentUpgradeableProxy. The implementation constructor fixes COMPTROLLER and IS_ISOLATED_POOL, so every proxy-to-implementation mapping must use an implementation built for that network and Comptroller family. On the documented BSC deployment IS_ISOLATED_POOL = false; the documented IL Comptroller deployments use true.
BNB Chain Mainnet
Section titled “BNB Chain Mainnet”| Contract | Address |
|---|---|
| EBrake (Proxy) | 0x35eBaBB99c7Fb7ba0C90bCc26e5d55Cdf89C23Ec |
| EBrake (Implementation) | 0x2D36677EcA318c9536011D53aa752F042dd01DE8 |
BNB Chain Testnet
Section titled “BNB Chain Testnet”| Contract | Address |
|---|---|
| EBrake (Proxy) | 0x957c09e3Ac3d9e689244DC74307c94111FBa8B42 |
| EBrake (Implementation) | 0xAC54A4D148690b7FDA22B1D29c4439aCBF668fb2 |
Audits
Section titled “Audits”Published EBrake and DeviationSentinel audit reports are indexed in the venus-periphery v1.3.0 release, including the HashDit report on the Hub pause forwarders and HubNavDeviationSentinel. A report’s scope and reviewed commit should be checked against the current proxy implementation.