Emergency Procedures (Vaults V2)
This document outlines procedures for handling emergency situations in Morpho Vaults V2. These actions should be executed with extreme care, as they can have significant consequences for the vault and its depositors.
Before proceeding, ensure you are familiar with Roles & Capabilities, Timelocks, and Adapters.
You can perform most emergency actions directly in the Curator app. Select your vault and open the Emergency Actions tab. For maxRate changes, use the Max Rate section on the main vault overview page. The UI prepares the same onchain transactions; the role requirements and timelock rules below still apply.
If you are acting as a Sentinel, see Act as a Sentinel in the Curator App for the dedicated Sentinel workflow.
Quick Reference
Key V2 design principle: Emergency functions that reduce risk (revoking, decreasing caps, deallocating) are never timelocked. Only functions that could increase risk are timelocked.
| Action | Timelocked? | Who Can Execute |
|---|---|---|
| Revoke any pending timelocked action | No | Curator, Sentinel |
| Decrease absolute/relative caps to 0 | No | Curator, Sentinel |
| Deallocate assets to idle | No | Allocator, Sentinel |
Set maxRate to 0 | No | Allocator |
| Force deallocate (in-kind redemption) | No | Anyone (permissionless, subject to penalty) |
Remove allocator role (setIsAllocator) | Yes (configurable) | Curator via submit |
Remove adapter (removeAdapter) | Yes | Curator via submit |
| Burn shares (adapter-level, MarketV1AdapterV2) | Yes (adapter timelock) | Curator via adapter submit |
Unsafe Market: Soft Deprecation
Use this procedure when a specific market (or all markets sharing a collateral type) is deemed too risky, but the adapter itself is functioning correctly. The adapter remains active - you are only restricting and exiting the specific market.
This is the most common emergency action and should be the default response when a risk concern is identified at the market level rather than the adapter or protocol level.
Curator App procedure
This can be implemented via normal flows on the Curator App.
- On the Timelocks tab, under Vault Pending Actions, identify any pending cap increases for the affected market or collateral asset. Select and revoke them. The Sentinel can also use the Sentinel tab to revoke pending actions (see how here).
- Under Caps tab, find the affected market or collateral asset. Set the absolute and relative caps to
0and confirm.
- Under Allocation tab, find the affected market. Enter the amount to withdraw and click Deallocate to move assets back to idle. If the market is illiquid, repeat as liquidity becomes available.
Script procedure
Step 1 - Revoke Pending Cap Increases for the Affected Id(s)
If there are pending cap increases for the market-level or collateral-level id, the Sentinel or Curator should call revoke(bytes) to cancel them. Both absolute and relative cap increases should be revoked if pending.
// Revoke a pending absolute cap increase on a specific market id
bytes memory pendingAbsoluteData = abi.encodeCall(IVaultV2.increaseAbsoluteCap, (marketIdData, newCap));
vault.revoke(pendingAbsoluteData);
// Revoke a pending relative cap increase on a specific market id
bytes memory pendingRelativeData = abi.encodeCall(IVaultV2.increaseRelativeCap, (marketIdData, newRelativeCap));
vault.revoke(pendingRelativeData);Step 2 - Decrease the Market or Collateral Cap to Zero
The Curator or Sentinel calls decreaseAbsoluteCap and/or decreaseRelativeCap for the specific id associated with the affected market or collateral. This is an instant action - it is explicitly exempt from timelocks.
To deprecate a single market:
// idData targets the specific market
// e.g. keccak256(abi.encode("this/marketParams", adapterAddress, marketParams))
vault.decreaseAbsoluteCap(marketIdData, 0);
vault.decreaseRelativeCap(marketIdData, 0);To deprecate all markets sharing a collateral type:
// idData targets the collateral
// e.g. keccak256(abi.encode("collateralToken", collateralTokenAddress))
vault.decreaseAbsoluteCap(collateralIdData, 0);
vault.decreaseRelativeCap(collateralIdData, 0);The adapter-level cap and other unaffected market caps remain unchanged, allowing the adapter to continue operating normally for its other markets.
Step 3 - Reallocate Liquidity Out of the Affected Market
The Allocator or Sentinel calls deallocate to withdraw assets from the affected market. These assets can be:
- Moved as idle assets in the vault.
- Reallocated into other markets within the same adapter (via a subsequent
allocatecall), if those markets are healthy and have available cap room. - Deposited into the Liquidity Adapter, if it has available cap room.
// Deallocate from the affected market into vault idle assets
vault.deallocate(adapter, affectedMarketData, assets);
// Optionally reallocate into a healthy market on the same adapter
vault.allocate(adapter, healthyMarketData, assets);The assets parameter requires an exact amount - neither the vault nor the MorphoMarketV1AdapterV2 adapter interprets type(uint256).max as "withdraw all." You must query the current allocation and pass the precise value.
If the market is illiquid, this may need to be done in stages as liquidity becomes available. In this case, monitoring should be set up to deallocate progressively.
Phantom Interest Accrual: Freeze the Share Price
Use this procedure when an allocated market keeps reporting accrued interest that will not be recoverable. This happens when the collateral is illiquid or insolvent, the borrower position is heading toward bad debt, and liquidations are broken (liquidate function is reverting) or aren’t economical (no liquidators are liquidating unhealthy positions). In this case, the adapter's realAssets() will continue to climb from interest accrual on the underlying market, lifting the vault share price even though that interest will never be recovered by the vault, resulting in phantom interest.
This is dangerous even after you have zeroed caps and started deallocating. The inflated share price creates a first-mover advantage: lenders who withdraw while idle liquidity lasts redeem at the inflated price, extracting interest that was never backed by recoverable assets. They leave with their principal plus the phantom interest, draining the vault's liquidity and leaving the remaining lenders unable to withdraw and exposed to a greater share of the eventual loss.
Setting maxRate to 0 caps future totalAssets growth, freezing the share price against further unrealizable interest. It does not unwind phantom interest that already accrued before the change, so freeze before moving more liquidity to idle whenever possible; any liquidity that is already idle while the share price is inflated can still be withdrawn by early exiters.
How maxRate = 0 works
The vault bounds interest accrual by maxRate in accrueInterestView():
maxTotalAssets = totalAssets + totalAssets * elapsed * maxRate / WAD
newTotalAssets = min(realAssets, maxTotalAssets)- With
maxRate = 0,maxTotalAssets = totalAssets, sonewTotalAssets = min(realAssets, totalAssets). Any valuerealAssets()reports above the currenttotalAssetsis ignored: upward accrual is frozen. - The cap is one-directional. If
realAssets()falls belowtotalAssets(a realized or socialized loss),newTotalAssets = realAssetsand the loss is still booked down to all depositors. FreezingmaxRatestops phantom gains from being distributed; it does not prevent real losses from being socialized. setMaxRatecallsaccrueInterest()before updating the value, so interest already accrued under the previous cap is locked in. Only future growth is stopped, so set it as early as possible.
maxRate is a single vault-level parameter, not per-market. Setting it to 0 halts yield accrual for the entire vault, including any healthy positions it still holds. This is the intended trade-off during remediation. Restore a non-zero maxRate once the unsafe exposure has been fully removed.
maxRate = 0 neither realizes nor hides bad debt. If liquidations socialize a loss, the share price still moves down. The action stops further unrealizable interest from being added to the share price; it does not remove any already-accrued inflation, so execute it before deallocating additional liquidity to idle when possible.
Curator App procedure
- Follow the Unsafe Market: Soft Deprecation Curator App procedure for the affected market, but only complete step 1 and step 2 first: revoke pending cap increases, then set the absolute and relative caps to
0. Do not complete the deallocation step yet. - Stay on the main vault overview page. In the Max Rate section, set Max Rate to
0and confirm the transaction.
- After the
maxRate = 0transaction is confirmed, return to step 3 of the Unsafe Market: Soft Deprecation Curator App procedure: use the Allocation tab to deallocate available liquidity to idle. If the market is illiquid, repeat as liquidity becomes available. - Once the unsafe exposure has been removed and the share price again reflects only recoverable assets, return to the Max Rate section on the main vault overview page and restore an appropriate non-zero value.
setMaxRate is restricted to the Allocator role. The Curator app prepares the transaction, but the signing wallet must have the Allocator role.
Script procedure
Step 1 - Revoke pending cap increases and set caps to zero
Follow the first two parts of Unsafe Market: Soft Deprecation: in that section's Script procedure, use Step 1 to revoke any pending cap increases, then Step 2 to set the absolute and relative caps to 0 for the affected id(s). This stops new allocation to the unsafe market.
Do not deallocate available liquidity to idle before freezing accrual unless there is an overriding operational reason. Moving liquidity to idle while the share price is still inflated can increase the amount early withdrawers can redeem at the inflated price.
Step 2 - Freeze accrual with maxRate = 0
An Allocator calls setMaxRate on the vault. This is instant and is not timelocked.
// Freeze totalAssets growth: no further interest is distributed to suppliers
vault.setMaxRate(0);setMaxRate is restricted to the Allocator role. The Sentinel cannot set it. If no trusted allocator is available, the Curator must first assign one via setIsAllocator, which is subject to its own timelock.
Step 3 - Deallocate liquidity after the freeze
After maxRate is set to 0, follow Step 3 - Reallocate Liquidity Out of the Affected Market in the Unsafe Market: Soft Deprecation Script procedure. The soft-deprecation substep does not have its own anchor; look for the vault.deallocate(adapter, affectedMarketData, assets) example in that section.
// Deallocate from the affected market into vault idle assets
vault.deallocate(adapter, affectedMarketData, assets);
// Optionally reallocate into a healthy market on the same adapter
vault.allocate(adapter, healthyMarketData, assets);This begins exiting the position without first adding more withdrawable liquidity at an inflated share price. If the market is illiquid, repeat as liquidity becomes available.
The action is reversible: raise maxRate back to a non-zero value once the unsafe exposure has been removed and the share price again reflects only recoverable assets.
Unsafe Adapter: Soft Deprecation
Use this procedure when an adapter is deemed too risky for continued allocation, but all contracts are still functioning correctly and assets can be withdrawn normally.
If the adapter is working properly and the markets are deemed risky for allocation, the removal should happen at the market level, not at the adapter level.
Do not submit removeAdapter until all caps are at zero and all assets are deallocated.
First, zero all caps for the adapter's IDs so that during the timelock window any allocate
call will revert (ZeroAbsoluteCap), preventing frontrunning.
Then deallocate all existing assets from the adapter before submitting removeAdapter.
If you remove an adapter that still holds assets, those assets are permanently lost.
Script procedure
Step 1 - Unset the Liquidity Adapter (if applicable)
If this adapter is currently set as the vault's liquidityAdapter, the Allocator must unset it before proceeding. Leaving it set will cause all subsequent deposits into the vault to revert.
// Pass address(0) to unset the liquidity adapter
vault.setLiquidityAdapterAndData(address(0), "");Step 2 - Revoke Pending Cap Increases
If there are any pending cap increases for ids associated with the adapter, the Sentinel or Curator should call revoke(bytes) on the vault to cancel them. Both absolute and relative cap increases should be revoked if pending.
// Revoke a pending absolute cap increase
bytes memory pendingAbsoluteData = abi.encodeCall(IVaultV2.increaseAbsoluteCap, (idData, newCap));
vault.revoke(pendingAbsoluteData);
// Revoke a pending relative cap increase
bytes memory pendingRelativeData = abi.encodeCall(IVaultV2.increaseRelativeCap, (idData, newRelativeCap));
vault.revoke(pendingRelativeData);Step 3 - Set Caps to Zero
The Curator or Sentinel calls decreaseAbsoluteCap and decreaseRelativeCap for all ids associated with the adapter, setting them to 0. This prevents any new allocations to the adapter.
vault.decreaseAbsoluteCap(idData, 0);
vault.decreaseRelativeCap(idData, 0);Step 4 - Deallocate Liquidity to Idle
The Allocator or Sentinel calls deallocate on the vault to withdraw all available assets from the adapter back to idle. If the underlying market is illiquid, this may need to be done in stages as liquidity becomes available.
vault.deallocate(adapter, data, assets);The assets parameter requires an exact amount - neither the vault nor the MorphoMarketV1AdapterV2 adapter interprets type(uint256).max as "withdraw all." You must query the current allocation and pass the precise value.
Step 5 - Remove the Adapter
Once the adapter's allocation reaches zero, the Curator calls submit to propose removeAdapter. This action is timelocked. After the timelock expires, anyone can execute the removal.
// Submit removal (timelocked)
vault.submit(abi.encodeCall(IVaultV2.removeAdapter, (adapterAddress)));
// After timelock expires, execute
vault.removeAdapter(adapterAddress);Market Reverts: Hard Deprecation
Use this procedure when an underlying market is malfunctioning (e.g., its functions consistently revert), making it impossible to withdraw assets normally. This action involves accepting the loss of any assets stuck in the market.
Curator App procedure
Requires Curator role.
- Open the Curator app, select your Vault V2, and go to the Emergency tab.
- Trigger the "Hard Market Removal" flow with the "Start" button.
"Hard Market Removal" permanently abandon capital stuck in a reverting market. Across three transactions, pending cap increases are revoked, caps are zeroed, and the adapter's shares for this market are burned. Lost funds cannot be recovered.
MorphoMarketV1AdapterV2 - Script procedure
The MorphoMarketV1AdapterV2 has its own independent timelock system. Forced market removal happens at the adapter level via burnShares, which zeroes out the adapter's internal share accounting for a specific market.
Step 1 - Set Caps to Zero
As with soft deprecation, the Curator or Sentinel should immediately decrease all caps to zero for ids associated with the market.
Critical: Complete this step before burnShares executes. If the affected market's adapter is set as the vault's liquidityAdapter, deposits into the vault will
automatically re-allocate to that market, thus recreating the position you just burned. Setting caps to zero blocks this.
Step 2 - Submit burnShares (Timelocked at Adapter Level)
The Curator calls submit on the adapter itself (not the vault) to propose burning the shares for the broken market.
// Submit to the adapter (not the vault)
adapter.submit(abi.encodeCall(IMorphoMarketV1AdapterV2.burnShares, (marketId)));The mandatory waiting period must elapse. During this time, the Sentinel or Curator can revoke via the adapter's revoke function if needed.
Step 3 - Execute burnShares
After the adapter timelock expires, anyone can execute the burn.
adapter.burnShares(marketId);Step 4 - Sync Vault Accounting
Deallocate 0 from the vault to update its internal allocation tracking.
vault.deallocate(adapter, data, 0);Warning: Loss of Assets. Burnt shares are lost forever. This procedure should only be used when the market consistently reverts and assets are considered irrecoverable.
MorphoVaultV1Adapter
For the MorphoVaultV1Adapter, forced removal happens at the vault level since this adapter wraps an entire Vault V1 position rather than individual markets. In this scenario, follow the procedure in V1 Emergency Actions.
Impact on Depositors
Morpho Vault V2 implements automatic loss socialization: when the adapter's realAssets() reports a value lower than previously recorded totalAssets, the vault updates its accounting downward, and the loss is reflected proportionally in the vault receipt token price for all depositors. For a detailed breakdown of how this accounting update is computed, see Handling Bad Debt.
If the underlying adapter wraps a Vault V1.1, note that V1.1 does not realize bad debt internally - so the Morpho Vault V2 will also not reflect those specific losses.
Allocator Compromise
If an Allocator is compromised or acting maliciously, the Curator should act to remove the role and correct any misallocations. The Allocator can only operate within the bounds set by the Curator (enabled adapters and caps), so the blast radius is limited to misallocation within the allowed set.
Curator App procedure
Requires Curator role.
- Open the Curator app, select your Vault V2, and go to the Emergency tab.
- Trigger the "Allocator Compromised" flow with the "Start" button.
- Select the compromised allocator address and proceed.
Remove the compromised allocator and zero all adapter caps. The exact steps depend on the current timelock state. Reversing this requires manually reconfiguring the vault.
Script procedure
Step 1 - Remove the Allocator Role
The Curator calls submit to propose setIsAllocator(compromisedAddress, false).
vault.submit(abi.encodeCall(IVaultV2.setIsAllocator, (compromisedAddress, false)));
// If timelock is 0, execute immediately
vault.setIsAllocator(compromisedAddress, false);If the setIsAllocator timelock is non-zero, proceed to Step 2 while waiting.
Step 2 - Set Caps to Zero
The Sentinel (or Curator) should immediately decrease all caps to zero. This is instant (cap decreases are exempt from timelocks) and neutralizes the allocator regardless of whether the role removal is timelocked.
vault.decreaseAbsoluteCap(idData, 0);
vault.decreaseRelativeCap(idData, 0);Step 3 - Correct Misallocations
A trusted Allocator or the Curator should deallocate from any wrongly allocated positions and reallocate according to the vault's intended strategy.
vault.deallocate(adapter, data, assets);Once the compromised allocator is removed, the Curator re-establishes caps and assigns a new allocator.
Curator Compromise
If the Curator begins acting maliciously (submitting caps for unsafe adapters or markets, adding untrusted markets or caps, changing fees or gates), the Owner and Sentinel must coordinate a response.
Curator App procedure
- The
Owneropens the Curator app, selects the vault, goes to the Roles tab, and replaces the Curator with a new trusted address (setCurator). This is instant and immediately strips the compromised address of all Curator capabilities.
- The
Sentinelopens theSentineltab and revokes all pending actions submitted by the compromised curator. Use Batch Action to cancel multiple proposals at once. More on the Sentinel page. - The new
Curatorreviews any malicious changes that were already executed and addresses them from the Emergency Actions tab: zero affected caps, deallocate assets, and submit adapter removal if needed.
Script procedure
Step 1 - Owner Replaces the Curator (Instant)
The Owner immediately calls setCurator to transfer control to a new, trusted address. This is not timelocked - the Owner can execute this instantly.
vault.setCurator(newTrustedCurator);This instantly strips the compromised address of all Curator capabilities.
Step 2 - Sentinel Revokes All Pending Actions (Instant)
The Sentinel must call revoke on every pending timelocked action submitted by the compromised curator. In V2, revoke(bytes) can cancel any pending timelocked action - adapter additions, cap increases, fee changes, gate changes, allocator changes, timelock decreases, etc.
vault.revoke(pendingMaliciousData);Step 3 - Assess Accepted Malicious Actions
If any malicious changes were executed before they could be revoked:
- Malicious adapter was added: The new Curator follows the Soft Deprecation procedure to safely exit. Set caps to zero, deallocate all assets, then submit
removeAdapter. - Caps were increased on unsafe ids: The new Curator or Sentinel instantly decreases caps to zero.
- Fees were changed: The new Curator submits corrected fee values (timelocked).
- Gates were changed: The new Curator submits corrected gate values (timelocked).
Key protection: Depositors are protected by the timelock window. Even if the Curator is compromised, all risk-increasing actions (adding adapters, increasing caps, changing gates) must go through the timelock, giving the Sentinel and depositors time to react.
Adapter-Level Remediation (MorphoMarketV1AdapterV2)
If the vault uses MorphoMarketV1AdapterV2, the adapter has its own timelock system and checks IVaultV2(parentVault).curator() for authorization. Replacing the curator at the vault level automatically revokes the compromised address's access to adapter-level submit calls.
However, any actions the compromised curator already submitted to the adapter remain pending. The new curator (or Sentinel) should revoke those at the adapter level as well:
adapter.revoke(pendingAdapterData);Owner Compromise
Owner compromise is the most severe scenario. In Morpho Vault V2, the Owner's powers are intentionally limited - they can only set the Curator and Sentinels. They cannot directly modify caps, adapters, fees, or allocations. However, a compromised Owner can appoint a malicious Curator, which cascades into a Curator compromise scenario.
Depositors must exit the vault before malicious configuration changes take effect. The vault should be considered permanently compromised.
Curator App procedure
Requires Sentinel role.
- The
Sentinel(if not yet replaced) opens the Curator app, goes to theSentineltab, and immediately revokes all suspicious pending actions. More on the Sentinel page. - The
Sentinelthen opens the Emergency tab, sets all caps to0, and deallocates all assets to idle. - Depositors should withdraw from the vault interface before any malicious timelocked actions expire. The timelock window is depositors' primary defense.
- If idle liquidity is insufficient for withdrawals, any user can trigger Force Deallocate from the Emergency Actions tab to move assets from adapters to idle, then withdraw normally.
Script procedure
Step 1 - Sentinel Blocks Immediate Damage (Instant)
If the compromised Owner sets a malicious Curator who begins submitting harmful proposals, the Sentinel (if not yet replaced) can revoke all pending actions.
The Sentinel should also proactively:
- Decrease all caps to zero (preventing new allocations).
- Deallocate all assets to idle (moving assets to the safest position).
Step 2 - Depositors Exit Within the Timelock Window
All depositors should withdraw their assets before any malicious timelocked actions expire. The timelock is the depositors' primary defense.
Step 3 - Last Resort: forceDeallocate
If the vault lacks idle liquidity for normal withdrawals, depositors can use the permissionless forceDeallocate to move assets from adapters to idle, then withdraw.
Warning: Full Loss of Vault. Once the Owner is compromised and all depositors have exited, the vault should be considered permanently compromised. A new vault must be deployed.
Sentinel Compromise
Sentinel compromise is the least severe role compromise, because the Sentinel can only perform risk-reducing actions: revoking pending actions, decreasing caps, and deallocating.
Impact
A compromised Sentinel could:
- Revoke legitimate pending proposals (denial of service, not loss of assets).
- Decrease caps to zero (forces vault to idle, no loss of assets).
- Deallocate assets to idle (moves everything to idle, no loss of assets).
Curator App procedure
- The
Owneropens the Curator app, selects the vault, and goes to the Roles tab. - Remove the compromised Sentinel.
- The
Curatorre-submits any legitimate proposals that were revoked by the compromised sentinel.
Script procedure
The Owner calls setIsSentinel(compromisedAddress, false) to remove the compromised sentinel and appoint a new one.
vault.setIsSentinel(compromisedAddress, false);
vault.setIsSentinel(newSentinel, true);The Curator then re-submits any legitimate proposals that were revoked by the compromised sentinel.