Skip to content

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 within
  • withdrawals: Array of market withdrawals, each specifying a market and an amount
  • supplyMarketParams: The destination market where all withdrawn funds will be supplied

Required Steps

  1. 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);
  2. 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
    });
  3. 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 the withdrawals 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 and maxIn increases by the withdrawn amount
  • When liquidity is supplied to a market, its maxIn decreases and maxOut 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:

ErrorDescriptionSolution
NotAdminNorVaultOwnerCaller is not vault admin or ownerOnly vault admin or owner can call admin functions
IncorrectFeeWrong ETH amount sentSend the exact fee amount as configured
MaxOutflowExceededTrying to withdraw more than allowedReduce withdrawal amount or wait for cap reset
MaxInflowExceededTrying to supply more than allowedReduce supply amount or wait for cap reset
InconsistentWithdrawalsWithdrawals not sorted by IDSort withdrawals by market ID in ascending order
DepositMarketInWithdrawalsSupply market in withdrawalsRemove supply market from withdrawals
MarketNotEnabledMarket not enabled in vaultOnly use markets enabled in vault configuration
EmptyWithdrawalsNo withdrawals providedProvide at least one withdrawal
WithdrawZeroWithdrawal amount is zeroProvide 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

NeedFunctionParametersDescription
Reallocate LiquidityreallocateTovault, withdrawals, supplyMarketParamsMove liquidity from multiple markets to one market
Check Flow CapsflowCapsvault, marketIdGet current flow caps for a market
Check FeefeevaultGet current fee required for reallocation

By following these patterns, you can effectively integrate with Morpho's Public Allocator to optimize liquidity across markets.