Morpho Public Allocator Integration Guide - Solidity
Understanding Market Parameters
Each Morpho market is defined by a set of parameters contained in the MarketParams
structure:
struct MarketParams {
address loanToken; // Token that can be borrowed and supplied
address collateralToken; // Token that can be used as collateral
address oracle; // Oracle that can be used to price loan and collateral token
address irm; // Interest rate model
uint256 lltv; // Liquidation loan-to-value ratio
}
Every market is uniquely identified by an Id
derived from these parameters.
Public Allocator Structures
The Public Allocator uses these key data structures:
struct FlowCaps {
uint128 maxIn; // Maximum allowed inflow to a market
uint128 maxOut; // Maximum allowed outflow from a market
}
struct Withdrawal {
MarketParams marketParams; // The market from which to withdraw
uint128 amount; // The amount to withdraw
}
Reallocating Liquidity
The core functionality of the Public Allocator is the reallocateTo
function, which moves liquidity from multiple source markets to a single destination market.
Function Signature
function reallocateTo(
address vault,
Withdrawal[] calldata withdrawals,
MarketParams calldata supplyMarketParams
) external payable;
Parameters
vault
: Address of the MetaMorpho vault to reallocate liquidity withinwithdrawals
: Array of market withdrawals, each specifying a market and an amountsupplyMarketParams
: The destination market where all withdrawn funds will be supplied
Required Steps
-
Check prerequisites:
// Check if the PublicAllocator has allocator role bool isAllocator = IMetaMorpho(vault).isAllocator(address(publicAllocator)); require(isAllocator, "Public Allocator not enabled for this vault"); // Get the fee for reallocation uint256 requiredFee = publicAllocator.fee(vault);
-
Prepare the withdrawal parameters:
// Create withdrawal array (must be sorted by market ID) Withdrawal[] memory withdrawals = new Withdrawal[](2); // First withdrawal withdrawals[0] = Withdrawal({ marketParams: idleMarketParams, amount: 70000000000000000000 // 70 units of a token with 18 decimals }); // Second withdrawal (must have a greater market ID than the first) withdrawals[1] = Withdrawal({ marketParams: wstETHMarketParams, amount: 800000000000000000000 // 800 units of a token with 18 decimals });
-
Call the reallocateTo function:
// Execute reallocation with required fee IPublicAllocator(publicAllocatorAddress).reallocateTo{value: requiredFee}( vaultAddress, withdrawals, supplyMarketParams // Destination market );
Important Requirements
- The markets in the
withdrawals
array must be sorted by their IDs in ascending order - The destination market (
supplyMarketParams
) cannot be included in thewithdrawals
array - All markets must be enabled in the vault's configuration
- The withdrawal amounts must respect the flow caps set for each market
- The exact fee amount must be sent with the transaction
Flow Caps Management
Flow caps control how much liquidity can move between markets:
- When liquidity is withdrawn from a market, its
maxOut
decreases andmaxIn
increases by the withdrawn amount - When liquidity is supplied to a market, its
maxIn
decreases andmaxOut
increases by the supplied amount
// Before reallocation
Market A: maxIn = 1000, maxOut = 500
Market B: maxIn = 2000, maxOut = 1000
// After reallocating 300 from Market A to Market B
Market A: maxIn = 1300, maxOut = 200
Market B: maxIn = 1700, maxOut = 1300
Handling Errors
Here are common errors and how to handle them:
Error | Description | Solution |
---|---|---|
NotAdminNorVaultOwner | Caller is not vault admin or owner | Only vault admin or owner can call admin functions |
IncorrectFee | Wrong ETH amount sent | Send the exact fee amount as configured |
MaxOutflowExceeded | Trying to withdraw more than allowed | Reduce withdrawal amount or wait for cap reset |
MaxInflowExceeded | Trying to supply more than allowed | Reduce supply amount or wait for cap reset |
InconsistentWithdrawals | Withdrawals not sorted by ID | Sort withdrawals by market ID in ascending order |
DepositMarketInWithdrawals | Supply market in withdrawals | Remove supply market from withdrawals |
MarketNotEnabled | Market not enabled in vault | Only use markets enabled in vault configuration |
EmptyWithdrawals | No withdrawals provided | Provide at least one withdrawal |
WithdrawZero | Withdrawal amount is zero | Provide non-zero withdrawal amounts |
Best Practices
For Efficient Reallocation
- Check available flow caps before attempting reallocation
- Monitor flow cap changes after reallocation
- Ensure markets are sorted correctly by ID
- Verify all markets are enabled in the vault configuration
For Cost Optimization
- Batch multiple reallocations when possible
- Check fee requirements before submitting transactions
- Consider gas costs when determining reallocation frequency
Function Selection Guide
Need | Function | Parameters | Description |
---|---|---|---|
Reallocate Liquidity | reallocateTo | vault, withdrawals, supplyMarketParams | Move liquidity from multiple markets to one market |
Check Flow Caps | flowCaps | vault, marketId | Get current flow caps for a market |
Check Fee | fee | vault | Get current fee required for reallocation |
By following these patterns, you can effectively integrate with Morpho's Public Allocator to optimize liquidity across markets.