Curate Adapters (Vaults V2)
Adapters are the core of a Morpho Vault V2's extensibility. They are smart contracts that act as bridges, allowing your vault to connect to and allocate assets in any version of the Morpho protocol. As a Curator, enabling and configuring adapters is how you define your vault's allocation universe.
This guide will walk you through the process of deploying, listing, and configuring adapters, with a focus on the MorphoMarketV1AdapterV2 that connects your Morpho Vault V2 directly to Morpho Variable Rate Markets. It also covers configuring adapter caps after deployment.
Setting Up the MorphoMarketV1AdapterV2
The MorphoMarketV1AdapterV2 allows your Morpho Vault V2 to allocate directly to variable rate markets. It is deployed via the MorphoMarketV1AdapterV2Factory, which takes the parent vault address and automatically connects to the Morpho Blue contract.
Method 1: via the Curator App V2 (Recommended)
On your Morpho Vault V2 page, navigate to the Adapters tab. If no adapter is configured yet, the interface will guide you through the setup flow.
For production use, pause after deploying the adapter and complete adapter hardening before submitting or accepting its addition to the vault.
The flow will implement the steps below:
- Deploy adapter
- Submit adapter
- Approve adapter timelock (if any)
- Set adapter caps
The adapter's burnShares timelock and the vault's addAdapter timelock are separate settings. If you cannot complete the adapter-level hardening in the UI, use the Etherscan procedure below before enabling it.
Before allocating, configure the required collateral-token and market caps in (De)List Markets.
Method 2: via Etherscan
1. Deploy the Adapter
Deploy MorphoMarketV1AdapterV2 via its factory by calling:
factory.createMorphoMarketV1AdapterV2(vaultV2Address)where factory is the deployed MorphoMarketV1AdapterV2Factory contract.
2. Configure and Verify Adapter Timelocks
Prerequisite: the encoding commands below require Foundry, including cast. Follow the official Foundry installation guide and confirm that cast --version works before proceeding.
Keep the adapter disabled and unfunded until this step is complete. Perform these calls on the adapter contract, not the vault. Check that parentVault() is your intended vault on the selected chain.
- Choose a reviewed production timelock for
burnShares(bytes32), in seconds. Obtain its selector withcast sig "burnShares(bytes32)". - Encode the adapter's
increaseTimelock(bytes4,uint256)call. For the three-day example, this command only encodes calldata; it sends no transaction:
cast calldata "increaseTimelock(bytes4,uint256)" \
"$(cast sig 'burnShares(bytes32)')" 259200- As Curator, call the adapter's
submit(bytes)with that calldata. ReadexecutableAt(bytes)using the identical calldata. Once the nonzero execution timestamp has been reached, executeincreaseTimelock(burnSharesSelector, timelockSeconds)on the adapter with the same arguments, and confirm the transaction. TheincreaseTimelockcall is itself subject to the adapter's current timelock for that function; submission alone does not change the setting. - Review the adapter's pending actions from its
Submit,AcceptandRevokeevents, starting at deployment. Check each candidate's exact calldata with the adapter'sexecutableAt(bytes). Revoke pending burns and any queued timelock reductions that could undermine the chosen timelock using the adapter'srevoke(bytes)as Curator or Sentinel. Do not inspect only the vault's pending actions. - Read back
timelock(burnSharesSelector)on the adapter and confirm it matches the reviewed timelock. Confirm that the unsafe pending actions are no longer executable (executableAt(data) == 0). Only then continue to adapter enablement. Recheck these conditions before the first allocation or user deposit.
3. Enable the Adapter
- As Curator, encode:
abi.encodeCall(IVaultV2.addAdapter, (adapterAddress)). - Call
submit(bytes)with the encoded data. - After timelock, call
addAdapter(adapterAddress).
4. Set Risk Caps
The adapter's ID is computed as:
bytes memory idData = abi.encode("this", adapterAddress);
bytes32 id = keccak256(idData);Submit and execute cap increases:
increaseAbsoluteCap(idData, capAmount)increaseRelativeCap(idData, relativeCapWad)(where 1e18 = 100%)
5. Set as Liquidity Adapter (if needed)
As Allocator, call with the default MarketParams encoded as data. The encoded market params identify which Morpho Variable Rate Market will receive new user deposits and serve withdrawals:
bytes memory liquidityData = abi.encode(marketParams);
vault.setLiquidityAdapterAndData(adapterAddress, liquidityData);Configuring Adapter Caps
Method 1: via the Curator App V2 (Recommended)
Directly on the Caps page of your Morpho Vault V2 by clicking on the "Edit Caps" button.
Cap increases with a non-zero timelock are submitted as pending actions. Once the timelock has elapsed, execute them from the vault's Timelocks page. If the timelock is zero, the Curator App submits and executes the cap changes in the same transaction. Cap decreases take effect immediately.
Method 2: via Script
Each adapter uses the following cap IDs:
- MorphoMarketV1AdapterV2:
- Adapter:
keccak256(abi.encode("this", adapterAddress)) - Collateral:
keccak256(abi.encode("collateralToken", marketParams.collateralToken)) - Market:
keccak256(abi.encode("this/marketParams", adapterAddress, marketParams))
- Adapter:
- MorphoVaultV1Adapter:
keccak256(abi.encode("this", adapterAddress))
Collateral caps are shared by markets with the same collateral token within the vault, including across adapters that use this ID.
Cap setters take the unhashed idData; getters such as absoluteCap and relativeCap take keccak256(idData). For example, to lower an adapter-wide cap:
bytes memory idData = abi.encode("this", adapterAddress);
vault.decreaseAbsoluteCap(idData, newLowerCap);
vault.decreaseRelativeCap(idData, newLowerRelativeCap);The caller must be the Curator or a Sentinel. Neither call is timelocked, and each new value must be less than or equal to the corresponding current cap. Absolute caps use raw units of the vault's underlying asset; relative caps use WAD units (1e18 = 100%). Lowering caps limits new allocations; it does not withdraw existing assets.
Delisting an Adapter
Before delisting, follow the full Adapter Soft Deprecation procedure, which covers both deallocating existing assets and zeroing caps to prevent frontrunning.
Setting Force Deallocate Penalty
When the vault's normal withdrawal liquidity - its idle assets and configured liquidity adapter - is insufficient, anyone can call forceDeallocate to move available assets from a selected adapter into the vault's idle balance. Set a force-deallocation penalty for that adapter to discourage unnecessary or disruptive use of this permissionless function:
// As Curator, submit proposal (max 2% = 0.02e18)
vault.submit(abi.encodeCall(IVaultV2.setForceDeallocatePenalty, (adapterAddress, 0.01e18)));
// After timelock
vault.setForceDeallocatePenalty(adapterAddress, 0.01e18); // 1% penaltyThe penalty is configured per adapter, is scaled by 1e18, and cannot exceed 2% (0.02e18). For example, 0.01e18 applies a 1% penalty to the amount force-deallocated.
A zero penalty burns no shares, but it also allows permissionless force-deallocation to move available assets from the adapter into the vault's idle balance without an economic deterrent.