(De)List Markets
Market Listing
Overview of what listing a market means:
- Submit a cap for a given market
- Accept the cap (after timelock)
- Set the supply queue
- Optional but recommended: perform a small deposit
Submit the cap
Fill the arguments of the submitCap
.
On the addresses section of the documentation, you have the markets created on Morpho, let’s take as an example the market:
WETH/wstETH (94.5%, ChainlinkOracle, AdaptiveCurveIRM).
Execute
submitCap
as in the picture below. Keep in mind that tenewSupplyCap
is in decimals of the asset (loan token).

Accept the cap
Wait for timelock to elapse and execute
acceptCap()
Execute the acceptCap()
with the market parameters of the market, which in this case are retrievable thanks to the id
of the market: 0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41

Do this for as many markets as you expect the vault to deposit liquidity.
In the end, do not forget to submit and accept the cap for what we call the "idle" market.
The idle market is a Morpho market with the asset of the Morpho Vault as loanToken
, the address(0)
as the collateralToken
, the address(0)
as irm
, the address(0)
as oracle
and 0 as lltv
so that it is possible to supply on this market, but not to borrow. You might have to create a such market (with the createMarket
function of the Morpho contract) if none of the already created markets of Morpho matches these parameters.
The cap for this market is supposed to be type(uint184).max
, to always allow deposits into the vault.
Set the supplyQueue
Now one has to set the supplyQueue
accordingly via the setSupplyQueue
function, by giving as input a list of Ids of markets as follows:
[0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41,0x_MARKET_ID_2,...]
And execute with an address that has the onlyAllocatorRole
:
- Owner,
- Curator,
- Allocator.
Deposit liquidity
It is important to deposit a bit of liquidity (can be even 1$) such that the native rate of the vault is not 0 if the markets where liquidity flows is not 0. Any interface, scripts, or bots reading the market APYs will thus have a rate different than 0.
Market Delisting
Delisting a market from your MetaMorpho vault requires careful planning and execution. There are two levels of delisting:
- Basic delisting: Removing a market from the supply queue (while keeping it in the withdraw queue)
- Complete delisting: Removing a market from both supply and withdraw queues
This tutorial will guide you through both processes, focusing on best practices to ensure a smooth transition for all stakeholders.
Planning the Delisting Process
Before beginning the technical steps, consider the following:
- Communicate with stakeholders about the planned delisting
- Ensure there's sufficient liquidity in other markets to absorb reallocated funds
- Plan a gradual transition to minimize market impact
Basic Delisting (Supply Queue Removal)
To stop new deposits from flowing to a specific market, you can remove it from the supply queue while keeping it in the withdraw queue. This approach allows existing positions to be maintained.
Execute
setSupplyQueue
with a new array that excludes the market you wish to delist.
For example, if your current supply queue is:
0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41; // 0: wstETH/WETH(94.5%)
0x3c83f77bde9541f8d3d82533b19bbc1f97eb2f1098bb991728acbfbede09cc5d; // 1: rETH/WETH(94.5%)
0x58e212060645d18eab6d9b2af3d56fbc906a92ff5667385f616f662c70372284; // 2: Idle Market - WETH
And you want to remove the wstETH/WETH market, you would call:
setSupplyQueue([0x3c83f77bde9541f8d3d82533b19bbc1f97eb2f1098bb991728acbfbede09cc5d,0x58e212060645d18eab6d9b2af3d56fbc906a92ff5667385f616f662c70372284])
This will prevent new deposits from being allocated to the removed market, but allows existing funds to remain there.
Reduce the Market Cap
To prepare for a complete delisting, you should first reduce the market cap to zero.
Execute
submitCap
with a value of 0 for the market you wish to delist.
input:
[
[ // marketParams tuple
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
"0x2a01EB9496094dA03c4E364Def50f5aD1280AD72",
"0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC",
"945000000000000000"
]
,0 // cap value, 0
]
Wait for the timelock to elapse and execute
acceptCap()
with the market parameters.
This step is necessary because a market with a non-zero cap cannot be removed from the withdraw queue.
Reallocate Liquidity
Before removing the market from the withdraw queue, you must withdraw all funds from it. Use the reallocate
function to move funds from the market being delisted to other markets.
Execute
reallocate
with the appropriate market allocations.
Here's an example of how to reallocate all funds from a market being delisted to other markets:
[
// First market to allocate funds to
{
"marketParams": {
"loanToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"collateralToken": "0x3c83f77bde9541f8d3d82533b19bbc1f97eb2f1098bb991728acbfbede09cc5d",
"oracle": "0x2a01EB9496094dA03c4E364Def50f5aD1280AD72",
"irm": "0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC",
"lltv": "945000000000000000"
},
"assets": "TARGET_ASSET_AMOUNT" // Amount to allocate to this market
},
// Idle market (to catch any remaining assets)
{
"marketParams": {
"loanToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"collateralToken": "0x0000000000000000000000000000000000000000",
"oracle": "0x0000000000000000000000000000000000000000",
"irm": "0x0000000000000000000000000000000000000000",
"lltv": "0"
},
"assets": "115792089237316195423570985008687907853269984665640564039457584007913129639935" // Max value to catch all remaining assets
}
]
Complete Delisting (Withdraw Queue Removal)
Once the market has a zero cap and no funds, you can remove it from the withdraw queue.
Execute
updateWithdrawQueue
with an array of indexes that excludes the market you wish to delist.
For example, if your current withdraw queue is:
0x58e212060645d18eab6d9b2af3d56fbc906a92ff5667385f616f662c70372284; // 0: Idle Market - WETH
0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41; // 1: wstETH/WETH(94.5%) - Market to remove
0x3c83f77bde9541f8d3d82533b19bbc1f97eb2f1098bb991728acbfbede09cc5d; // 2: rETH/WETH(94.5%)
And you want to remove the market at index 1 (wstETH/WETH), you would call:
updateWithdrawQueue([0,2])
This will keep the markets at index 0 and 2 in the new withdraw queue, and remove the market at index 1.
Emergency Market Removal
In exceptional cases where a market is malfunctioning (e.g., constantly reverting), you may need to force remove it.
Execute
submitMarketRemoval
with the market parameters of the market to remove.
input:
[
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // loanToken
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", // collateralToken
"0x2a01EB9496094dA03c4E364Def50f5aD1280AD72", // oracle
"0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC", // irm
"945000000000000000" // lltv
]
Wait for the timelock to elapse, then update the withdraw queue using
updateWithdrawQueue
as described in step 4.
Delisting Process Summary
For safe market delisting:
- Remove the market from the supply queue
- Reduce the market cap to zero
- Reallocate all funds from the market to other markets
- Remove the market from the withdraw queue
For emergency situations:
- Submit market removal
- Wait for timelock to elapse
- Update the withdraw queue
Always prioritize the safety of depositor funds and provide clear communication throughout the delisting process.