# Table of Contents - [Morpho Overview – Morpho Docs](#morpho-overview-morpho-docs) - [Morpho Docs](#morpho-docs) - [Morpho Market V1 – Morpho Docs](#morpho-market-v1-morpho-docs) - [Morpho Vault V1 – Morpho Docs](#morpho-vault-v1-morpho-docs) - [Curator – Morpho Docs](#curator-morpho-docs) - [Oracle – Morpho Docs](#oracle-morpho-docs) - [Vault V2 – Morpho Docs](#vault-v2-morpho-docs) - [Liquidation on Morpho – Morpho Docs](#liquidation-on-morpho-morpho-docs) - [Rewards on Morpho – Morpho Docs](#rewards-on-morpho-morpho-docs) - [Flash Loans – Morpho Docs](#flash-loans-morpho-docs) - [Morpho Governance – Morpho Docs](#morpho-governance-morpho-docs) - [Risk & Security Documentation – Morpho Docs](#risk-security-documentation-morpho-docs) - [The MORPHO token – Morpho Docs](#the-morpho-token-morpho-docs) - [Audits - Security Reviews – Morpho Docs](#audits-security-reviews-morpho-docs) - [Morpho Docs](#morpho-docs) - [Morpho Docs](#morpho-docs) - [Introduction – Morpho Docs](#introduction-morpho-docs) - [Build Earn & Borrow Products on Morpho – Morpho Docs](#build-earn-borrow-products-on-morpho-morpho-docs) - [Morpho Curation – Morpho Docs](#morpho-curation-morpho-docs) - [Public Allocator – Morpho Docs](#public-allocator-morpho-docs) - [Morpho Bundlers – Morpho Docs](#morpho-bundlers-morpho-docs) - [Interest Rate Model – Morpho Docs](#interest-rate-model-morpho-docs) - [Products – Morpho Docs](#products-morpho-docs) - [Use Cases on the Morpho Stack – Morpho Docs](#use-cases-on-the-morpho-stack-morpho-docs) - [Addresses – Morpho Docs](#addresses-morpho-docs) - [Developers Hub – Morpho Docs](#developers-hub-morpho-docs) - [Morpho Apps – Morpho Docs](#morpho-apps-morpho-docs) - [Morpho Contracts – Morpho Docs](#morpho-contracts-morpho-docs) - [Morpho Docs](#morpho-docs) - [Deploy an Oracle for Morpho Markets – Morpho Docs](#deploy-an-oracle-for-morpho-markets-morpho-docs) - [Morpho Docs](#morpho-docs) - [Integrating Morpho Rewards – Morpho Docs](#integrating-morpho-rewards-morpho-docs) - [Reward Campaigns on Morpho – Morpho Docs](#reward-campaigns-on-morpho-morpho-docs) - [Merkl Distribution System – Morpho Docs](#merkl-distribution-system-morpho-docs) - [Morpho API – Morpho Docs](#morpho-api-morpho-docs) - [Morpho Markets – Morpho Docs](#morpho-markets-morpho-docs) - [Public Allocator – Morpho Docs](#public-allocator-morpho-docs) - [Morpho Vaults for Earn products – Morpho Docs](#morpho-vaults-for-earn-products-morpho-docs) - [Morpho Markets for Borrow products – Morpho Docs](#morpho-markets-for-borrow-products-morpho-docs) - [Morpho Vaults – Morpho Docs](#morpho-vaults-morpho-docs) - [Morpho Subgraphs – Morpho Docs](#morpho-subgraphs-morpho-docs) - [Guide: Integrating One-Click Yield with OnchainKit – Morpho Docs](#guide-integrating-one-click-yield-with-onchainkit-morpho-docs) - [Dune – Morpho Docs](#dune-morpho-docs) - [How Bundlers Work – Morpho Docs](#how-bundlers-work-morpho-docs) - [Earn: Developer Resources – Morpho Docs](#earn-developer-resources-morpho-docs) - [Rewards – Morpho Docs](#rewards-morpho-docs) - [Morpho Docs](#morpho-docs) - [Guide: Integrating Gasless Crypto-Backed Loans with Gelato – Morpho Docs](#guide-integrating-gasless-crypto-backed-loans-with-gelato-morpho-docs) - [Create a Rewards Program – Morpho Docs](#create-a-rewards-program-morpho-docs) - [Combining Actions – Morpho Docs](#combining-actions-morpho-docs) - [Bundler Resources – Morpho Docs](#bundler-resources-morpho-docs) - [Using LLMs – Morpho Docs](#using-llms-morpho-docs) - [Morpho Docs](#morpho-docs) - [Morpho Docs](#morpho-docs) - [Morpho Bundlers – Morpho Docs](#morpho-bundlers-morpho-docs) - [Borrow: Developer Resources – Morpho Docs](#borrow-developer-resources-morpho-docs) - [Morpho Apps – Morpho Docs](#morpho-apps-morpho-docs) - [Complete Integration Example – Morpho Docs](#complete-integration-example-morpho-docs) - [Public Allocator – Morpho Docs](#public-allocator-morpho-docs) - [App Integration – Morpho Docs](#app-integration-morpho-docs) - [Yield Generation – Morpho Docs](#yield-generation-morpho-docs) - [Fees – Morpho Docs](#fees-morpho-docs) - [Roles & Capabilities – Morpho Docs](#roles-capabilities-morpho-docs) - [Liquidity Curation – Morpho Docs](#liquidity-curation-morpho-docs) - [Adapter Registry – Morpho Docs](#adapter-registry-morpho-docs) - [Timelock – Morpho Docs](#timelock-morpho-docs) - [Vault as asset – Morpho Docs](#vault-as-asset-morpho-docs) - [Manage Vault V2 Roles – Morpho Docs](#manage-vault-v2-roles-morpho-docs) - [Checklist to Validate Vault V1 Configuration – Morpho Docs](#checklist-to-validate-vault-v1-configuration-morpho-docs) - [Bundler3 & Bundler2 – Morpho Docs](#bundler3-bundler2-morpho-docs) - [Manage Vault Roles – Morpho Docs](#manage-vault-roles-morpho-docs) - [Manage Allocations (Vaults V1) – Morpho Docs](#manage-allocations-vaults-v1-morpho-docs) - [Manage Adapters (Vaults V2) – Morpho Docs](#manage-adapters-vaults-v2-morpho-docs) - [Manage Markets & Liquidity (Vaults V1) – Morpho Docs](#manage-markets-liquidity-vaults-v1-morpho-docs) - [Set the Rate at Target – Morpho Docs](#set-the-rate-at-target-morpho-docs) - [Gates in Morpho Vaults – Morpho Docs](#gates-in-morpho-vaults-morpho-docs) - [Create a Vault – Morpho Docs](#create-a-vault-morpho-docs) - [Handling Permissioned Tokens in the Morpho App – Morpho Docs](#handling-permissioned-tokens-in-the-morpho-app-morpho-docs) - [Managing Bad Debt: How-to Guide – Morpho Docs](#managing-bad-debt-how-to-guide-morpho-docs) - [Emergency Procedures – Morpho Docs](#emergency-procedures-morpho-docs) - [Vaults & ERC4626 Mechanics – Morpho Docs](#vaults-erc4626-mechanics-morpho-docs) - [Rewards: Developer Resources – Morpho Docs](#rewards-developer-resources-morpho-docs) - [Set Up Public Allocator – Morpho Docs](#set-up-public-allocator-morpho-docs) - [Create a Morpho Vault V2 – Morpho Docs](#create-a-morpho-vault-v2-morpho-docs) - [Create a Market – Morpho Docs](#create-a-market-morpho-docs) - [Supply Collateral, Borrow, Repay & Withdraw Collateral – Morpho Docs](#supply-collateral-borrow-repay-withdraw-collateral-morpho-docs) - [Depositing & Withdrawing from Vaults – Morpho Docs](#depositing-withdrawing-from-vaults-morpho-docs) - [Morpho SDKs – Morpho Docs](#morpho-sdks-morpho-docs) - [Market Mechanics – Morpho Docs](#market-mechanics-morpho-docs) - [Interest Rate Models – Morpho Docs](#interest-rate-models-morpho-docs) - [Oracles – Morpho Docs](#oracles-morpho-docs) - [Universal Rewards Distributors – Morpho Docs](#universal-rewards-distributors-morpho-docs) - [Morpho Vaults V2 – Morpho Docs](#morpho-vaults-v2-morpho-docs) - [Public Allocator – Morpho Docs](#public-allocator-morpho-docs) - [Morpho Vaults – Morpho Docs](#morpho-vaults-morpho-docs) - [Morpho – Morpho Docs](#morpho-morpho-docs) - [Fetch Rewards Data – Morpho Docs](#fetch-rewards-data-morpho-docs) - [Claim Rewards – Morpho Docs](#claim-rewards-morpho-docs) - [Integrate Rewards Display – Morpho Docs](#integrate-rewards-display-morpho-docs) - [Get Data – Morpho Docs](#get-data-morpho-docs) - [Triggering the Public Allocator – Morpho Docs](#triggering-the-public-allocator-morpho-docs) - [Get Data – Morpho Docs](#get-data-morpho-docs) - [Yield & Fees – Morpho Docs](#yield-fees-morpho-docs) - [Integrate Rewards for Earn Products – Morpho Docs](#integrate-rewards-for-earn-products-morpho-docs) - [Rewards for Lenders – Morpho Docs](#rewards-for-lenders-morpho-docs) - [Multicall – Morpho Docs](#multicall-morpho-docs) - [Use Bundlers for Vaults – Morpho Docs](#use-bundlers-for-vaults-morpho-docs) - [Integrate Rewards for Borrow Products – Morpho Docs](#integrate-rewards-for-borrow-products-morpho-docs) - [How can distributors generate revenue on Morpho? – Morpho Docs](#how-can-distributors-generate-revenue-on-morpho-morpho-docs) - [Collateral, LTV & Health – Morpho Docs](#collateral-ltv-health-morpho-docs) - [Pre-Liquidation (Auto-Deleveraging) – Morpho Docs](#pre-liquidation-auto-deleveraging-morpho-docs) - [Public Allocator: Just-in-Time Liquidity – Morpho Docs](#public-allocator-just-in-time-liquidity-morpho-docs) - [Rewards for Borrowers – Morpho Docs](#rewards-for-borrowers-morpho-docs) - [Morpho Documentation – Morpho Docs](#morpho-documentation-morpho-docs) - [App Integration – Morpho Docs](#app-integration-morpho-docs) - [Combining Actions – Morpho Docs](#combining-actions-morpho-docs) - [Morpho Bundlers – Morpho Docs](#morpho-bundlers-morpho-docs) - [Interest Rates – Morpho Docs](#interest-rates-morpho-docs) - [Use Bundlers for Complex Borrows – Morpho Docs](#use-bundlers-for-complex-borrows-morpho-docs) - [Liquidation – Morpho Docs](#liquidation-morpho-docs) --- # Morpho Overview – Morpho Docs [Skip to content](https://docs.morpho.org/learn/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Morpho Overview On this page Chevron Right Introduction[](https://docs.morpho.org/learn/#introduction) -------------------------------------------------------------- **Morpho** is a decentralized lending protocol with different entities and individuals contributing to its development and adoption. As a result, the documentation refers to different areas of “Morpho” which are worth distinguishing. * **The Morpho Protocol**: A decentralized, noncustodial lending protocol implemented for the Ethereum Virtual Machine. * **The Morpho Interfaces**: Multiple web interfaces allowing easy interaction with the Morpho protocol. Those interfaces are ways to interact with the Morpho protocol. * **Morpho Governance**: A governance system for governing the Morpho Protocol, enabled by the [MORPHO token](https://docs.morpho.org/learn/governance/morpho-token#1) . * **Morpho Association**: A France-registered association that regroups the main contributors to promote the development and the decentralization of the Morpho Protocol. [The Morpho Association](https://docs.morpho.org/learn/governance/organization#morpho-association) hosts one of the Morpho Interfaces. Morpho[](https://docs.morpho.org/learn/#morpho) -------------------------------------------------- Morpho is a simple lending primitive layer that allows the creation of immutable and efficient lending markets in a permissionless way. The protocol comes with EVM smart contracts which facilitate interactions and integrations. ### Overview[](https://docs.morpho.org/learn/#overview) Morpho is a decentralized protocol enabling the overcollateralized lending and borrowing of crypto assets (ERC20 & ERC4626 Tokens) on the [Ethereum Virtual Machine](https://ethereum.org/en/developers/docs/evm/) . The protocol is implemented as an immutable smart contract, engineered to serve as a trustless base layer for lenders, borrowers, and applications. Morpho is licensed under a dual license (BUSL-1.1 and GPLv2) which you can find [here](https://github.com/morpho-org/morpho-blue/blob/main/LICENSE) . Once deployed, Morpho will function in perpetuity, provided by the existence of the blockchain. ### Key Concepts[](https://docs.morpho.org/learn/#key-concepts) Overcollateralized lending in Morpho involves: * **Collateralization**: Users provide collateral to borrow other assets * **Risk Protection**: Liquidation mechanisms protect the protocol through loan-to-value ratios * **Interest Accrual**: Dynamic interest rates based on market conditions * **Open Participation**: Anyone can lend or borrow through the protocol * **Non-custodial Design**: Users maintain ownership of their assets at all times --- # Morpho Docs [Skip to content](https://docs.morpho.org/get-started/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Open infrastructure On this page Chevron Right Open infrastructure ======================= for onchain loans ===================== Connect to the most trusted lending network ----------------------------------------------- ![Build](https://docs.morpho.org/img/get-started/home/group-1.svg) ### Build Create DeFi applications with Morpho Vaults and Markets using our SDKs and APIs. [→](https://docs.morpho.org/build/) ![Curate](https://docs.morpho.org/img/get-started/home/group-2.svg) ### Curate Manage vault performance by balancing stakeholder needs and optimizing liquidity allocation. [→](https://docs.morpho.org/curate/) ![Learn](https://docs.morpho.org/img/get-started/home/group-3.svg) ### Learn Understand Morpho's decentralized lending protocol concepts and ecosystem fundamentals. [→](https://docs.morpho.org/learn/) --- # Morpho Market V1 – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/market/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Morpho Market V1 On this page Chevron Right ![Morpho Market Concept](https://docs.morpho.org/img/homepage/concepts/concepts_market_light.png) What is a Morpho Market (V1)?[](https://docs.morpho.org/learn/concepts/market/#what-is-a-morpho-market-v1) ------------------------------------------------------------------------------------------------------------- A Morpho Market V1 is a primitive lending pool that pairs one collateral asset with one loan asset. Each market is isolated (meaning risks are contained within each individual market), immutable (cannot be changed after deployment), and will persist as long as the blockchain it deployed on is live. This design ensures predictable behavior and eliminates systematic for lenders and borrowers. Creating a Morpho Market is **permissionless**. Key Features[](https://docs.morpho.org/learn/concepts/market/#key-features) ------------------------------------------------------------------------------ * **Simple Structure**: One collateral asset, one loan asset per market * **Permanent Parameters**: Once created, rules never change * **Isolated Risk**: Each market operates independently * **Permission-less**: New market doesn’t require governance vote to be created - more [here](https://docs.morpho.org/learn/concepts/market#permissionless-market-creation) * **Transparent Rules**: Clear conditions for lending and borrowing Market Identification[](https://docs.morpho.org/learn/concepts/market/#market-identification) ------------------------------------------------------------------------------------------------ Markets follow this naming format: `CollateralAsset/LoanAsset (LLTV%, OracleAddress, IRMAddress)` For example: `wstETH/WETH (94.5%, ChainlinkOracleV2-wstETHToWETH, AdaptiveCurveIRM)` The Five Parameters[](https://docs.morpho.org/learn/concepts/market/#the-five-parameters) -------------------------------------------------------------------------------------------- 1. **Collateral Asset** that should be [ERC20 compliant](https://docs.openzeppelin.com/contracts/4.x/erc20) (except that it can omit return values on `transfer` and `transferFrom`.) 2. **Loan Asset** sharing same properties as collateral asset. However, the Loan asset should not be [ERC4626 compliant](https://docs.openzeppelin.com/contracts/4.x/erc4626) . 3. **LLTV (Liquidation Loan-To-Value)**: Maximum borrowing percentage before liquidation risk. E.g: LLTV of 80% means for a collateral value equivalent of $100, the maximum one can borrow in value is $80. If above like $80.0001, the position is liquidatable. 4. **Oracle**: Smart contract address pricing the collateral against the loan asset. 5. **IRM (Interest Rate Model)**: Smart contract address containing the formula for determining interest rate paid by borrowers. Governance-Approved LLTV & IRM[](https://docs.morpho.org/learn/concepts/market/#governance-approved-lltv--irm) ----------------------------------------------------------------------------------------------------------------- ### LLTVs[](https://docs.morpho.org/learn/concepts/market/#lltvs) | LLTV (%) | Solidity Values (scaled by 1e18) | | --- | --- | | 0 | 0 | | 38.5 | 385000000000000000 | | 62.5 | 625000000000000000 | | 77.0 | 770000000000000000 | | 86.0 | 860000000000000000 | | 91.5 | 915000000000000000 | | 94.5 | 945000000000000000 | | 96.5 | 965000000000000000 | | 98.0 | 980000000000000000 | ### IRM[](https://docs.morpho.org/learn/concepts/market/#irm) The only Interest Rate Model (IRM) that has been governance-approved is the [AdaptiveCurveIRM](https://docs.morpho.org/learn/concepts/irm) . Market ID Generator[](https://docs.morpho.org/learn/concepts/market/#market-id-generator) -------------------------------------------------------------------------------------------- Use this tool to generate a unique market ID from your market parameters: Loan Token Address Collateral Token Address Oracle Address IRM Address LLTV (in wei, e.g., 915000000000000000 for 91.5%) Reset Generated Market ID `0xbc15a1782163f4be46c23ac61f5da50fed96ad40293f86a5ce0501ce4a246b32`Copy Permissionless market creation[](https://docs.morpho.org/learn/concepts/market/#permissionless-market-creation) ------------------------------------------------------------------------------------------------------------------ A distinctive feature of Morpho is permissionless market creation: the protocol allows users to create isolated markets consisting of the five aforementioned parameters. This a departure from the existing paradigm and traditional lending platforms which: 1. Require governance approval for asset listing and parameter changes. 2. Pool assets into a single lending pool, sharing risk across the entire protocol. In Morpho, each parameter is selected at market creation and persists in perpetuity. Or, in other words, are immutable. The LLTV and interest rate model must be chosen from a set of options approved by Morpho Governance. Core Interactions[](https://docs.morpho.org/learn/concepts/market/#core-interactions) ---------------------------------------------------------------------------------------- * **Supply**: Lenders deposit loan assets into a specific market to earn interest. * **Borrow**: Borrowers supply collateral to the same market and borrow loan assets against it, up to the LLTV limit. * **Withdraw**: Lenders can withdraw their supplied assets and accrued interest, provided there is enough liquidity in the market. * **Repay**: Borrowers can repay their loan to reclaim their collateral. * **Liquidate**: If a borrower's position exceeds the LLTV, anyone can liquidate it by repaying a portion of the debt in exchange for a discounted portion of the collateral. --- # Morpho Vault V1 – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/vault/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Morpho Vault V1 On this page Chevron Right ![Morpho Vault Concept](https://docs.morpho.org/img/homepage/concepts/concepts_vault_light.png) **Morpho Vault V1** is a protocol for permissionless lending vaults built on top of the [Morpho Markets V1](https://docs.morpho.org/learn/concepts/market) . What is a Morpho Vault V1?[](https://docs.morpho.org/learn/concepts/vault/#what-is-a-morpho-vault-v1) -------------------------------------------------------------------------------------------------------- A Morpho Vault V1 has one loan asset and can allocate deposits to multiple Morpho Markets V1. Users can deposit into a vault to start earning passive yield from interest paid by borrowers. Vaults feature automated risk curation, actively curating risk exposure for all deposited assets so users don't need to make these decisions themselves. Users maintain full control over their assets, can monitor the vault's state at any time, and withdraw their liquidity at their discretion. Key Features[](https://docs.morpho.org/learn/concepts/vault/#key-features) ----------------------------------------------------------------------------- * **ERC-4626 Compatibility**: Morpho Vaults implement the [ERC-4626 "Tokenized Vault"](https://eips.ethereum.org/EIPS/eip-4626) standard, providing a consistent and interoperable way to interact with lending positions across the DeFi ecosystem. * **Simplified Yield Generation**: Vaults abstract away the complexity of managing positions across multiple lending markets, allowing users to deposit once and earn optimized yields. * **Automated risk curation**: Each vault is managed by specialized [roles](https://docs.morpho.org/learn/concepts/curator) that handle market selection, risk assessment, and capital allocation to protect depositors. * **Permissionless Liquidity**: Users can deposit and withdraw at any time, with no lock-up periods, subject only to the available liquidity on the underlying markets. * **Transparent Operations**: All vault actions and allocations are visible onchain, with role-based management to ensure proper oversight and risk control. Morpho Vaults serve as an accessible entry point for users who want to participate in DeFi lending markets without directly managing the complexities of individual positions, risk assessment, and market selection. How It Works[](https://docs.morpho.org/learn/concepts/vault/#how-it-works) ----------------------------------------------------------------------------- 1. **Curation and Market Selection**: The `Curator` of the vault is responsible for risk curation. They select a set of Morpho V1 markets that are appropriate for the vault's strategy and set an absolute **supply cap** for each one. This cap limits the vault's maximum exposure to any single market. All risk-altering actions are subject to a **timelock**. 2. **Capital Allocation**: The `Allocator` is responsible for optimizing yield. They manage two queues: * **Supply Queue**: Defines the priority order for depositing new capital into the enabled markets. * **Withdraw Queue**: Defines the priority order for withdrawing capital to meet user redemption requests. The allocator can also `reallocate` funds between enabled markets to optimize utilization and yield. 3. **User Deposits and Withdrawals**: When a user deposits, the vault routes the assets to markets in the `supplyQueue` up to their respective caps. When a user withdraws, the vault pulls liquidity from markets in the `withdrawQueue`. Roles and Responsibilities[](https://docs.morpho.org/learn/concepts/vault/#roles-and-responsibilities) --------------------------------------------------------------------------------------------------------- Morpho Vaults V1 use a system of distinct roles to separate powers and responsibilities: * **Owner**: The highest level of control. The owner can appoint the Curator and Allocators and set vault-level parameters like fees. * **Curator**: The primary risk curator. The Curator decides which Morpho Markets V1 the vault can supply to and sets the supply cap for each. These actions are timelocked for security. * **Allocator**: The portfolio allocator. The Allocator actively manages the supply and withdraw queues and can reallocate capital between approved markets to optimize for yield and liquidity. * **Guardian**: A safety role with the power to revoke pending timelocked actions proposed by the Owner or Curator, acting as a final check against malicious or erroneous changes. A Note on V1.0 vs V1.1[](https://docs.morpho.org/learn/concepts/vault/#a-note-on-v10-vs-v11) ----------------------------------------------------------------------------------------------- The initial version of Morpho Vaults V1 was V1.0. An update, V1.1, was later released with a key change in how it handles bad debt from the underlying Morpho V1 markets. * **Morpho Vault V1.0**: Realized bad debt from an underlying market atomically. This meant if a market suffered a loss, the vault's share price would immediately drop. * **Morpho Vault V1.1**: Does not automatically realize bad debt. Instead, losses remain within the underlying Morpho V1 market, and the `lostAssets` variable tracks them. This prevents flash loan-based share price manipulation attacks. --- # Curator – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/curator/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Curator On this page Chevron Right ![Morpho Curator Concept](https://docs.morpho.org/img/homepage/concepts/concepts_curator_light.png) A **Curator** in the Morpho ecosystem is an entity or individuals who aims to optimize the risk-adjusted returns for depositors based on a given strategy. Curators are specifically responsible for the strategic [curation of vaults](https://docs.morpho.org/learn/concepts/vault) , making key decisions about which markets to include, how capital is allocated, and how risk is curated within the vault structure. Their expertise directly impacts vault performance and security. The Curator's Responsibilities[](https://docs.morpho.org/learn/concepts/curator/#the-curators-responsibilities) ------------------------------------------------------------------------------------------------------------------ A Curator's duties revolve around high-level strategic decisions and risk curation. While the specifics of their toolkit have evolved from Vault V1 to V2, the core responsibilities remain consistent: * **Strategic Curation**: Defining the vault's overall investment thesis. This includes selecting which protocols, markets, or asset types are permissible for allocation. * **Risk Parameterization**: Setting and maintaining the risk boundaries for the vault. This involves defining exposure limits (caps) to various risk factors to protect depositor capital. * **Appointing Managers**: In Vault V2, the Curator is responsible for appointing the `Allocator(s)` who will actively manage the portfolio within the established risk framework. * **Setting Core Vault Mechanics**: In Vault V2, the Curator also controls crucial mechanisms like fees and compliance gating. Crucially, nearly all of a Curator's significant actions are subject to a **timelock**, providing transparency and giving depositors a window to exit if they disagree with a proposed change. The Curator's Toolkit: V1 vs. V2[](https://docs.morpho.org/learn/concepts/curator/#the-curators-toolkit-v1-vs-v2) -------------------------------------------------------------------------------------------------------------------- The tools available to a Curator have significantly expanded with Vaults V2, enabling far more sophisticated and granular risk curation. | Feature / Tool | **In Morpho Vault V1** | **In Morpho Vault V2** | | --- | --- | --- | | **Protocol Selection** | Limited to selecting individual **Morpho Market V1** instances. | Can enable any protocol via **Adapters**, making the vault a universal gateway to yield (e.g., Morpho Market V1, Morpho Vault V1, more... ). | | **Risk Curation** | Simple **absolute supply caps** per market. (e.g., "max 10M USDC in this specific market"). | Granular **ID & Cap System**. Can set both **absolute** and **relative** caps on abstract risk factors (e.g., "max 15M total exposure to stETH collateral across all markets" or "no more than 20% of the vault in protocols using Oracle X"). | | **Yield Management** | N/A. Interest was automatically accrued from the underlying markets. | Can set **interest rate limits** via `maxRate` to cap how quickly vault assets can grow, while adapters automatically report current asset values. | | **Fee Structure** | N/A. Fees were managed by the `Owner`. | Sets the **performance and management fees** and their respective recipients. | | **Compliance** | Not natively supported. | Can implement onchain compliance by setting **Gate Contracts** to control deposits, withdrawals, and share transfers. | Curation within the Vault Role System[](https://docs.morpho.org/learn/concepts/curator/#curation-within-the-vault-role-system) --------------------------------------------------------------------------------------------------------------------------------- The Curator role is designed to be distinct from other vault management functions, creating a clear separation of duties. * The **Owner** is the ultimate authority, with the power to appoint the `Curator` and `Sentinels`. The Owner's role is primarily administrative. * The **Curator** defines the _strategy_ and _risk boundaries_. They decide **what** is possible within the vault (which protocols, what max exposure). * The **Allocator** is the _tactical portfolio manager_. Appointed by the Curator, they operate **within** the boundaries set by the Curator, deciding **how** to allocate capital among the permitted options to optimize yield. * The **Sentinel** (the evolution of V1's `Guardian`) is a _safety mechanism_. It can reactively reduce risk by decreasing caps or deallocating funds, and it can revoke pending timelocked actions from the Curator, acting as a crucial check on their power. This structure ensures that strategic risk curation is separate from daily portfolio management (Allocation), leading to a more robust and secure system. --- # Oracle – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/oracle/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Oracle On this page Chevron Right ![Morpho IRM Concept](https://docs.morpho.org/img/homepage/concepts/concepts_oracle_light.png) What is an Oracle?[](https://docs.morpho.org/learn/concepts/oracle/#what-is-an-oracle) ----------------------------------------------------------------------------------------- Oracles are smart contracts that provide external data, particularly price information, to blockchain applications. In lending protocols like Morpho, oracles provide price data needed to determine what one token is worth relative to another. For example, the oracle of a market is supposedly answering the question: "How many USDC is 1 BTC worth right now?” Oracles in Lending Markets[](https://docs.morpho.org/learn/concepts/oracle/#oracles-in-lending-markets) ---------------------------------------------------------------------------------------------------------- Traditional lending protocols rely on oracles to: * Determine the value of collateral assets * Calculate borrowing capacity * Trigger liquidations when positions become undercollateralized * Enable accurate interest rate calculations Oracle Implementation in Morpho[](https://docs.morpho.org/learn/concepts/oracle/#oracle-implementation-in-morpho) -------------------------------------------------------------------------------------------------------------------- Morpho takes an **oracle-agnostic approach**, allowing market creators to select the most appropriate price feed mechanisms based on specific market requirements. Each Morpho market specifies its oracle in the market parameters, ensuring that oracle implementations can be tailored to specific asset pairs. All oracles used in Morpho markets implement the `IOracle` [interface](https://docs.morpho.org/get-started/resources/contracts/oracles#price) , which has a single, standardized function: Copy `function price() external view returns (uint256);` This function returns the price of 1 unit of collateral token quoted in the loan token, with appropriate scaling to account for decimal differences between tokens. Types of Oracles Compatible with Morpho[](https://docs.morpho.org/learn/concepts/oracle/#types-of-oracles-compatible-with-morpho) ------------------------------------------------------------------------------------------------------------------------------------ Various oracle implementations can be used with Morpho markets: 1. **Price Feed Oracles**: Utilize external price feeds (like Chainlink, Redstone, API3, Pyth, Chronicle) to calculate asset exchange rates. 2. **Exchange Rate Oracles**: Specialized for wrapped tokens or rebasing tokens where the exchange rate is deterministic (like wstETH/stETH). 3. **Fixed-Price Oracles**: Used for assets with known or predefined exchange rates, such as stablecoins pegged to the same value. MorphoChainlinkOracleV2: A Reference Implementation[](https://docs.morpho.org/learn/concepts/oracle/#morphochainlinkoraclev2-a-reference-implementation) ----------------------------------------------------------------------------------------------------------------------------------------------------------- One reference implementation available is `MorphoChainlinkOracleV2`, which leverages Chainlink-compliant price feeds while supporting multiple routing configurations: * Direct feeds (e.g., stETH/ETH) * Inverse feeds (e.g., ETH/USDC → USDC/ETH) * Multiple feed routes (e.g., stETH/USD and USDC/USD) * Complex routing with multiple hops This implementation demonstrates the flexibility of the oracle system within Morpho, allowing markets to maintain accurate pricing even when direct price feeds aren't available. Deploy an Oracle[](https://docs.morpho.org/learn/concepts/oracle/#deploy-an-oracle) -------------------------------------------------------------------------------------- Key Oracle Characteristics in Morpho Markets[](https://docs.morpho.org/learn/concepts/oracle/#key-oracle-characteristics-in-morpho-markets) ---------------------------------------------------------------------------------------------------------------------------------------------- * **Purpose-Built**: Each oracle returns the specific exchange rate between a collateral asset and a loan asset * **Immutable**: Once a market is deployed, its oracle address cannot be modified * **Independent**: Each oracle operates autonomously and can use different pricing sources * **Flexible Implementation**: Curators can leverage various data sources while maintaining a consistent interface Oracle Selection by Market Curators[](https://docs.morpho.org/learn/concepts/oracle/#oracle-selection-by-market-curators) ---------------------------------------------------------------------------------------------------------------------------- Market curators (not Morpho) are responsible for selecting and implementing appropriate oracles for their markets. Each Morpho market specifies its oracle in the market parameters: `CollateralAsset/LoanAsset (LLTV%, OracleAddress, IRMAddress)` Oracle Security Considerations[](https://docs.morpho.org/learn/concepts/oracle/#oracle-security-considerations) ------------------------------------------------------------------------------------------------------------------ The security of an oracle is critical to the safety of a Morpho Market. Users should: * Verify the oracle implementation for any market they interact with * Understand the price sources being used * Consider potential manipulation vectors or failure modes The immutable nature of Morpho Markets means oracle selection is a permanent decision that defines the market's [risk profile](https://docs.morpho.org/learn/resources/risks) Oracle community section[](https://docs.morpho.org/learn/concepts/oracle/#oracle-community-section) ------------------------------------------------------------------------------------------------------ --- # Vault V2 – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/vault-v2/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Vault V2 On this page Chevron Right ![Morpho Market Concept](https://docs.morpho.org/img/learn/concepts/vault-v2.png) **Vault V2** is a protocol for permissionless lending vaults built on top of the Morpho Markets V1, Morpho Vaults V1 and more. They represent a major evolution of the vault concept, transforming them from a simple layer on Morpho Market V1 into a **universal gateway to onchain yield**. While retaining the core principle of simplifying yield generation for passive depositors, Vaults V2 are designed to be future-proof, with a powerful new architecture centered around **Adapters**, a more granular **ID & Cap System**, and automatic interest accrual through real-time asset reporting. Vault V2 Types[](https://docs.morpho.org/learn/concepts/vault-v2/#vault-v2-types) ------------------------------------------------------------------------------------ ![Morpho Vaults and Basic Vaults](https://docs.morpho.org/img/learn/concepts/morpho-vault-basic-vault.png) Vault V2 instances are distinguished between: **Basic Vaults**: Vaults V2 that can supply to any protocol via Adapter contracts. In particular, Vault V2 has been developed and audited only in the context of the Morpho Market V1 and Morpho Vault V1 adapters. **Morpho Vaults**: Vaults V2 that are set up with the [Morpho registry](https://docs.morpho.org/learn/concepts/vault-v2#adapter-registry) , which establishes a list Morpho governance-approved adapters that can be used by the vault. Morpho Vaults enjoy the full support of Morpho's infrastructure: * **Full app integration**: Listed in the [Full Morpho app](https://app.morpho.org/) (subject to whitelisting process). * **Management tools**: Configurable through the [Curator app](https://curator.morpho.org/) . * **Data utilities**: [Morpho GraphQL API](https://api.morpho.org/graphql) , [Dune Analytics Dashboards](https://dune.com/morpho) . * [Security audits](https://docs.morpho.org/get-started/resources/audits) for all supported contracts and flows. * Thorough product and technical documentation. * Peripheral utilities like the [Oracle tester and decoder](https://oracles.morpho.dev/) (non-exclusive to Morpho Vaults). Basic Vaults can become Morpho Vaults by abdicating to the Morpho registry. The Evolution from V1 to V2[](https://docs.morpho.org/learn/concepts/vault-v2/#the-evolution-from-v1-to-v2) -------------------------------------------------------------------------------------------------------------- Vaults V2 are a significant leap forward, designed for maximum flexibility and control. * **From Specific to Universal**: Vaults V1 were tightly coupled to Morpho Market V1. Vaults V2 can connect to _any_ protocol via Adapters. * **From Simple to Automatic Yield Aggregation**: While V1 calculated interest automatically from Morpho Market V1, V2 aggregates yield from diverse sources through adapters that report their current assets in real-time. * **From Simple to Granular Risk**: V1 had simple, per-market caps. V2 introduces a multi-dimensional ID & Cap system, allowing risk curation across abstract factors like a specific collateral type, oracle, or protocol. Core Concepts of Vaults V2[](https://docs.morpho.org/learn/concepts/vault-v2/#core-concepts-of-vaults-v2) ------------------------------------------------------------------------------------------------------------ ### 1\. The Adapter Model: A Universal Gateway to Yield[](https://docs.morpho.org/learn/concepts/vault-v2/#1-the-adapter-model-a-universal-gateway-to-yield) The central innovation of Vaults V2 is the **Adapter** system. An adapter is a smart contract that acts as a translator, containing the logic to interact with a specific external protocol and automatically report the current value of investments. * **How it works**: The `Allocator` calls `allocate` on the vault, specifying a target adapter, an amount, and any protocol-specific data. The vault then transfers assets to the adapter, which executes the supply logic on the target protocol (e.g., supplying to a Morpho Market V1 or depositing into a Morpho Vault V1). * **Automatic Asset Reporting**: Each adapter implements a `realAssets()` function that returns the current value of all investments it manages. This allows the vault to automatically calculate total assets by aggregating across all adapters. * **Future-Proof**: New adapters can be developed and enabled by the `Curator` at any time, allowing the vault to integrate with any new source of onchain yield without requiring an upgrade to the vault itself. Initial adapters include `MorphoMarketV1Adapter` and `MorphoVaultV1Adapter`. ### 2\. Granular Risk Curation: The ID & Cap System[](https://docs.morpho.org/learn/concepts/vault-v2/#2-granular-risk-curation-the-id--cap-system) Vaults V2 introduce a far more sophisticated system for curating risk. Instead of a single cap per market, Curators can now define and cap risk based on abstract identifiers (`ids`), where each `id` represents a common risk factor. For example, the `MorphoMarketV1Adapter` can generate `ids` for: * A specific collateral asset (e.g., `keccak256("collateralToken", stETH_address)`) * A specific market configuration (e.g., `keccak256("collateralToken/oracle/lltv", ...)`). The `Curator` can then set both **absolute caps** (a fixed asset amount) and **relative caps** (a percentage of the vault's total assets) on these `ids`. This allows for multi-dimensional risk policies, such as: * Max total exposure to `stETH` as collateral: 15M (absolute cap on the collateral `id`). * Max 20% of the vault allocated to any market using a specific, new oracle (relative cap). ### 3\. Advanced Liquidity Management[](https://docs.morpho.org/learn/concepts/vault-v2/#3-advanced-liquidity-management) Vaults V2 separate idle liquidity from allocated capital more explicitly. * **Idle Assets**: All user deposits and withdrawals flow through the main vault contract, which holds the idle assets. * **Liquidity Adapter**: The `Allocator` can designate a specific, highly liquid adapter as the `liquidityAdapter`. If idle assets are insufficient to cover a withdrawal, the vault will automatically pull funds from this market. This adapter also receives all new deposits, ensuring capital is immediately put to work. * **In-Kind Redemptions (`forceDeallocate`)**: As a final non-custodial guarantee, users can `forceDeallocate` assets from any adapter back to the vault's idle pool. By combining this with a flash loan, a user can always exit the vault by exchanging their vault shares for a direct position in an underlying protocol, even if the vault is illiquid. A small penalty applies to disincentivize misuse of this emergency function. Key Feature Comparison: Vaults V1 vs. Vaults V2[](https://docs.morpho.org/learn/concepts/vault-v2/#key-feature-comparison-vaults-v1-vs-vaults-v2) ---------------------------------------------------------------------------------------------------------------------------------------------------- | Feature | Morpho Vault V1 (Vaults V1) | Vaults V2 | | --- | --- | --- | | **Protocol Support** | Exclusively Morpho Market V1. | **Future-Proof**. Connects to any protocol via Adapters. | | **Interest Accrual** | **Automatic**. Calculated onchain from Morpho Market V1. | **Automatic aggregation**. Each adapter reports current assets via `realAssets()`. | | **Risk Curation** | **Simple**. Absolute supply cap per market. | **Granular**. Absolute and relative caps on abstract `ids` (e.g., collateral type, oracle, protocol). | | **Roles & Permissions** | Owner is powerful; Guardian is a safety net. | **Separated roles** (Owner, Curator, Allocator, Sentinel) for better separation of duties. | | **Bad Debt** | (V1.1) Not realized by the vault; remains in Morpho Market V1. | **Automatically tracked**. Adapters report losses in real-time through `realAssets()`. | | **Liquidity** | Liquidity is a single pool across all markets. | Distinct **idle assets** and an optional, dedicated **`liquidityAdapter`**. | | **Compliance / Gating** | Not natively supported. | Native support for onchain **Gating** via gate contracts for shares and asset transfers. | | **ERC-4626 Compliance** | Fully compliant. | Mostly compliant, with shares remaining fully ERC-20. | Advanced Role System[](https://docs.morpho.org/learn/concepts/vault-v2/#advanced-role-system) ------------------------------------------------------------------------------------------------ Vaults V2 refine the role system for greater security and flexibility: * **Owner**: Manages top-level permissions. Can appoint the Curator and Sentinels. Has no direct control over funds or risk parameters. * **Curator**: The primary risk manager. Sets adapters, caps, fees, and interest rate limits. Most actions are timelocked. * **Allocator**: The active portfolio manager. Allocates funds to enabled adapters and manages the `liquidityAdapter`. * **Sentinel**: The safety-focused role that can reactively reduce risk by deallocating funds, decreasing caps, or revoking pending timelocked actions. Other Key Features[](https://docs.morpho.org/learn/concepts/vault-v2/#other-key-features) -------------------------------------------------------------------------------------------- * **New Fee Structure**: Supports both a **performance fee** (up to 50% on yield) and a **management fee** (up to 5% on total assets). * **Interest Rate Controls**: The Curator can set a `maxRate` that caps how quickly `totalAssets` can grow, useful for implementing fixed-rate distributions. * **Gating & Compliance**: Optional `Gate` contracts can be set by the Curator to enforce onchain rules for deposits, withdrawals, and share transfers (e.g., for KYC/whitelisting). Are Vaults V2 Non-Custodial?[](https://docs.morpho.org/learn/concepts/vault-v2/#are-vaults-v2-non-custodial) --------------------------------------------------------------------------------------------------------------- **Yes, Vault V2 maintains non-custodial guarantees through three fundamental mechanisms: in-kind redemptions, timelocks, and role-based access control.** ### Core Non-Custodial Mechanisms[](https://docs.morpho.org/learn/concepts/vault-v2/#core-non-custodial-mechanisms) #### 1\. In-Kind Redemptions with `forceDeallocate`[](https://docs.morpho.org/learn/concepts/vault-v2/#1-in-kind-redemptions-with-forcedeallocate) In-kind redemption in Vault V2 transfers a user’s position from the Vault V2 itself to one of its underlying adapters (such as Vault V1 or Market V1). It does not withdraw assets out of the Morpho protocol; instead, it shifts the user’s exposure from Vault V2 to the underlying markets, even when those markets are illiquid. This transition happens through the permissionless `forceDeallocate` function. This mechanism enables: * **Guaranteed exits**: Users can redeem their vault shares directly for underlying positions in protocols, similar to ETF redemptions * **Permissionless operation**: Anyone can call `forceDeallocate` to move assets from adapters back to the vault's idle assets * **Flashloan-enabled exits**: Users can flashloan liquidity, supply it to an adapter's market, then withdraw through `forceDeallocate` before repaying the flashloan **Complete In-Kind Redemption Workflow:** When a vault lacks sufficient idle liquidity for withdrawals, users can perform an in-kind redemption through flashloan-enabled exits: 1. **User flashloans the required liquidity amount** 2. **User deposits flashloaned assets directly into the underlying market/protocol** 3. **User calls `forceDeallocate` to withdraw equivalent assets from the adapter** 4. **User withdraws their vault shares for the deallocated assets** 5. **User repays the flashloan with the withdrawn assets** 6. **User retains their position in the underlying market as compensation** A small penalty (up to 2%) may apply to discourage manipulation, but this doesn't prevent exits—it only adds a minor cost. This mechanism ensures that even if a vault's underlying markets become illiquid, users are never permanently locked in the Vault V2. They can always exit by effectively swapping their vault shares for direct positions in the underlying protocols. #### 2\. Comprehensive Timelock System[](https://docs.morpho.org/learn/concepts/vault-v2/#2-comprehensive-timelock-system) All potentially harmful curator actions are protected by configurable timelocks (0 to 3 weeks), giving users time to react: **Timelocked actions include:** * Increasing allocation caps (absolute and relative) * Enabling new adapters or allocators * Setting performance/management fees (capped at 50% and 5% respectively) * Configuring access gates * Modifying fee recipients **Timelock properties:** * Users can monitor pending changes via the `submit` function, which records proposal timestamps in the `executableAt` mapping * Sentinels can revoke malicious proposals before execution * Emergency functions like decreasing caps can be called immediately by curators or sentinels for protective risk management * Some timelocks can be made infinite through `abdicateSubmit`, permanently preventing certain actions **Key protection:** The timelock system ensures that users always have advance notice of changes that could affect their funds, with emergency overrides only available for actions that reduce risk exposure (like lowering caps), never for actions that could increase risk. #### 3\. Role Separation and Limitations[](https://docs.morpho.org/learn/concepts/vault-v2/#3-role-separation-and-limitations) The vault's V2 role-based architecture ensures no single party can unilaterally harm users through strict separation of concerns, ensuring that even if one role is compromised, user funds remain protected by the constraints and oversight of other roles, combined with timelock protection for any potentially harmful changes. Check the roles declination on the related [section](https://docs.morpho.org/curate/concepts/roles#morpho-vaults-v2-roles) . ### Additional Safety Mechanisms[](https://docs.morpho.org/learn/concepts/vault-v2/#additional-safety-mechanisms) #### Caps and Risk Controls[](https://docs.morpho.org/learn/concepts/vault-v2/#caps-and-risk-controls) * **Absolute caps**: Hard limits on allocation to specific protocols/markets * **Relative caps**: Percentage-based limits relative to total vault assets * **Id system**: Groups related risks (e.g., same collateral) under unified caps #### Gates (Optional Access Control)[](https://docs.morpho.org/learn/concepts/vault-v2/#gates-optional-access-control) When enabled, gates control: * Share transfers (who can send/receive vault shares) * Asset deposits (who can deposit into vault) * Asset withdrawals (who can receive assets from vault) Gates are timelocked and can be permanently disabled through abdication. ### Adapter Registry[](https://docs.morpho.org/learn/concepts/vault-v2/#adapter-registry) Vault V2 lets anyone create non-custodial vaults that earn yield by depositing assets into different DeFi protocols through adapters. Because Vault V2 is flexible, a curator can add adapters to connect the vault to almost any protocol. This is powerful — but also risky: a vault could move your deposits to other protocols that may be less safe or not reviewed by Morpho. **Morpho Registry** solves this. A registry is a list of approved adapters that a vault is allowed to use. * If a vault has no registry, it can add any adapter. * If a vault uses a registry, it can only add adapters approved in that registry. * If the curator locks (abdicates) the registry, it can never be changed — giving users a strong guarantee. The **Morpho Registry** is the official registry maintained by the Morpho governance. Vaults V2 that set their registry to the Morpho Registry and lock it are called **Morpho Vaults V2**. These Morpho Vaults V2 get Morpho’s ecosystem benefits and give users confidence that deposits stay within Morpho-reviewed protocols. #### Immutable Contracts[](https://docs.morpho.org/learn/concepts/vault-v2/#immutable-contracts) All vault contracts are immutable—no upgrades can change the core non-custodial guarantees after deployment. ### Why This Matters[](https://docs.morpho.org/learn/concepts/vault-v2/#why-this-matters) These mechanisms ensure that: 1. **No entity can permanently lock user funds** (guaranteed via `forceDeallocate`) 2. **No surprise changes can harm users** (guaranteed via timelocks) 3. **No single party controls user assets** (guaranteed via role separation) The combination of guaranteed exits, transparent timelocks, and distributed control makes Morpho Vault V2 genuinely non-custodial—users retain ultimate control over their assets even when delegating management to curators and allocators. --- # Liquidation on Morpho – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/liquidation/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Liquidation on Morpho On this page Chevron Right ![Morpho Liquidation Concept](https://docs.morpho.org/img/homepage/concepts/concepts_liquidation_light.png) Overview[](https://docs.morpho.org/learn/concepts/liquidation/#overview) --------------------------------------------------------------------------- Liquidation is a critical mechanism in the Morpho protocol that protects lenders' capital by ensuring borrowers maintain healthy collateral positions. Morpho offers two liquidation approaches: 1. **Standard Liquidation**: A built-in mechanism at the protocol core that allows full or partial position liquidation when a borrower's Loan-To-Value (LTV) exceeds the Liquidation Loan-To-Value (LLTV) threshold. 2. **Pre-Liquidation**: An opt-in mechanism implemented in an external contract that enables smaller, incremental liquidations before reaching the standard liquidation threshold, creating a safety cushion for borrowers. Understanding Loan-To-Value (LTV)[](https://docs.morpho.org/learn/concepts/liquidation/#understanding-loan-to-value-ltv) --------------------------------------------------------------------------------------------------------------------------- Before exploring the liquidation mechanisms, it's essential to understand how LTV is calculated and what it represents. ### How to Calculate LTV[](https://docs.morpho.org/learn/concepts/liquidation/#how-to-calculate-ltv) The Loan-To-Value (LTV) ratio is a key risk metric that measures the proportion of debt relative to collateral value. To calculate the LTV of a position on Morpho, use the following formula: LTV\=BORROWED\_AMOUNTCOLLATERAL\_VALUE\_IN\_LOAN\_TOKEN×100%\\text{LTV} = \\frac{\\text{BORROWED\\\_AMOUNT}}{\\text{COLLATERAL\\\_VALUE\\\_IN\\\_LOAN\\\_TOKEN}} \\times 100\\% LTV\=COLLATERAL\_VALUE\_IN\_LOAN\_TOKENBORROWED\_AMOUNT​×100% The collateral value in loan token units is calculated as: COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN\=COLLATERAL\_AMOUNT × ORACLE\_PRICEORACLE\_PRICE\_SCALE\\text{COLLATERAL\\\_VALUE\\\_IN\\\_LOAN\\\_TOKEN} = \\frac{\\text{COLLATERAL\\\_AMOUNT } \\times \\text{ ORACLE\\\_PRICE}}{\\text{ORACLE\\\_PRICE\\\_SCALE}} COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN\=ORACLE\_PRICE\_SCALECOLLATERAL\_AMOUNT × ORACLE\_PRICE​ ### Health Factor[](https://docs.morpho.org/learn/concepts/liquidation/#health-factor) The Health Factor is another crucial metric that indicates how close a position is to liquidation: HEALTH\_FACTOR\=COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN×LLTVBORROWED\_AMOUNT\\text{HEALTH\\\_FACTOR} = \\frac{\\text{COLLATERAL\\\_VALUE\\\_IN\\\_LOAN\\\_TOKEN} \\times \\text{LLTV}}{\\text{BORROWED\\\_AMOUNT}} HEALTH\_FACTOR\=BORROWED\_AMOUNTCOLLATERAL\_VALUE\_IN\_LOAN\_TOKEN×LLTV​ A position is healthy when the Health Factor is greater than 1.0. When it falls below 1.0, the position becomes eligible for liquidation. Standard Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#standard-liquidation) --------------------------------------------------------------------------------------------------- The standard liquidation mechanism is the primary defense against borrower defaults and is built directly into the Morpho core contracts. ### When Is a Position Liquidatable?[](https://docs.morpho.org/learn/concepts/liquidation/#when-is-a-position-liquidatable) A position becomes liquidatable when its LTV exceeds the market's Liquidation Loan-To-Value (LLTV) which can happen due to: * Collateral value decreasing * Debt increasing due to accrued interest * A combination of both factors ### How Standard Liquidation Works[](https://docs.morpho.org/learn/concepts/liquidation/#how-standard-liquidation-works) When a position becomes liquidatable, any external party (a liquidator) can repay part or all of the borrower's debt in exchange for an equivalent amount of collateral plus a liquidation bonus. #### Liquidation Incentive Factor (LIF)[](https://docs.morpho.org/learn/concepts/liquidation/#liquidation-incentive-factor-lif) The liquidation bonus is determined by the Liquidation Incentive Factor (LIF), which depends on the market's LLTV: LIF\=min⁡(M,1β∗LLTV+(1−β)), with β\=0.3 and M\=1.15.\\text{LIF} = \\min(M, \\frac{1}{\\beta\*\\text{LLTV}+(1-\\beta)}), \\text{ with } \\beta = 0.3 \\text{ and } M= 1.15. LIF\=min(M,β∗LLTV+(1−β)1​), with β\=0.3 and M\=1.15. ![LIF vs LLTV graph](https://docs.morpho.org/img/morpho-blue/lif-lltv.png) Liquidation Incentive Factor in relation to the Liquidation Loan-To-Value ### Standard Liquidation Step-by-Step[](https://docs.morpho.org/learn/concepts/liquidation/#standard-liquidation-step-by-step) #### Initial Position[](https://docs.morpho.org/learn/concepts/liquidation/#initial-position) A borrower deposits $100k of collateral in a market with LLTV = 86% and borrows $70k. Due to accrued interest (an example could be provided with only collateral price depreciation), the loan value increases to $86.01k. * Position status: LTV = 86.01% > LLTV (86%) → **Liquidatable** #### Liquidation Process[](https://docs.morpho.org/learn/concepts/liquidation/#liquidation-process) * Liquidator identifies the unhealthy position * Liquidator repays the $86.01k debt * LIF calculation: 1.05 (for 86% LLTV market) * Seized collateral: $86.01k × 1.05 = $90.31k #### After Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#after-liquidation) * Borrower: Debt cleared, retains $9.69k of collateral * Liquidator: Spent $86.01k, received $90.31k in collateral * Profit for liquidator: $4.3k minus gas fees and any swap costs #### Practical Consideration[](https://docs.morpho.org/learn/concepts/liquidation/#practical-consideration) For this liquidation to be profitable, the liquidator must ensure: $4.3k > (Gas fees + potential swap fees + potential price slippage costs) ### Key Features of Standard Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#key-features-of-standard-liquidation) * **Liquidation Amount**: Liquidators can repay up to 100% of the borrower's debt in a single transaction * **Trigger**: Only activates when LTV > LLTV * **Incentive**: Fixed LIF based on the market's LLTV * **Borrower Impact**: Potentially significant one-time liquidation * **Implementation**: Built into the Morpho core contract Pre-Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#pre-liquidation) ----------------------------------------------------------------------------------------- The pre-liquidation mechanism, also called Auto-Deleverage, is an optional, opt-in feature that provides a safety buffer between healthy positions and standard liquidation. ### What Is Pre-Liquidation (also known as Auto-Deleverage)[](https://docs.morpho.org/learn/concepts/liquidation/#what-is-pre-liquidation-also-known-as-auto-deleverage) Pre-liquidation allows partial position closure when a borrower's LTV exceeds a pre-defined threshold (preLLTV) but remains below the market's LLTV. This creates a cushion zone where borrowers face smaller, incremental liquidations rather than a single full liquidation. ### How Pre-Liquidation Parameters Work[](https://docs.morpho.org/learn/concepts/liquidation/#how-pre-liquidation-parameters-work) Pre-liquidation operates with 6 key parameters: #### Pre-Liquidation Loan-To-Value (preLLTV)[](https://docs.morpho.org/learn/concepts/liquidation/#pre-liquidation-loan-to-value-prelltv) The threshold at which pre-liquidation becomes possible #### Pre-Liquidation Close Factors (preLCF₁ & preLCF₂)[](https://docs.morpho.org/learn/concepts/liquidation/#pre-liquidation-close-factors-prelcf--prelcf) The maximum percentage of debt that can be repaid in a single pre-liquidation. This scales linearly between preLCF₁ and preLCF₂ based on the position's LTV: preLCF\=LLTV−LTVLLTV−preLLTV∗preLCF1+LTV−preLLTVLLTV−preLLTV∗preLCF2preLCF = \\frac{LLTV - LTV}{LLTV - preLLTV} \* preLCF\_1 + \\frac{LTV - preLLTV}{LLTV - preLLTV} \* preLCF\_2 preLCF\=LLTV−preLLTVLLTV−LTV​∗preLCF1​+LLTV−preLLTVLTV−preLLTV​∗preLCF2​ #### Pre-Liquidation Incentive Factors (preLIF₁ & preLIF₂)[](https://docs.morpho.org/learn/concepts/liquidation/#pre-liquidation-incentive-factors-prelif--prelif) The bonus received by pre-liquidators, which can scale linearly between preLIF₁ and preLIF₂ based on position health. #### Pre-Liquidation Oracle (PRE\_LIQUIDATION\_ORACLE)[](https://docs.morpho.org/learn/concepts/liquidation/#pre-liquidation-oracle-pre_liquidation_oracle) The oracle used to assess whether or not a position can be preliquidated. It could be the same oracle of the market, or another oracle. ### Pre-Liquidation Step-by-Step[](https://docs.morpho.org/learn/concepts/liquidation/#pre-liquidation-step-by-step) Let's walk through an example of how pre-liquidation works in practice: #### Step-by-Step Process[](https://docs.morpho.org/learn/concepts/liquidation/#step-by-step-process) ##### Case 1: Pre-Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#case-1-pre-liquidation) #### Initial Position Setup[](https://docs.morpho.org/learn/concepts/liquidation/#initial-position-setup) Alice deposits 1 WBTC as collateral valued at 100k USDC and borrows 70k USDC. Her initial LTV is calculated as: LTV\=70,000/100,000\=0.70(70%)LTV = 70,000 / 100,000 = 0.70 \\quad (70\\%) LTV\=70,000/100,000\=0.70(70%) #### Subscription to Pre-Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#subscription-to-pre-liquidation) Alice opts into the pre-liquidation feature. Her position is set to be pre-liquidated when her LTV exceeds the preLLTV threshold of approximately 83%. #### Market Price Movement to Pre-Liquidation Range[](https://docs.morpho.org/learn/concepts/liquidation/#market-price-movement-to-pre-liquidation-range) When the price of 1 WBTC falls to 84k USDC, the new collateral value becomes 84k USDC. Her LTV then becomes: LTV\=70,000/84,000≈0.83(83%)LTV = 70,000 / 84,000 \\approx 0.83 \\quad (83\\%) LTV\=70,000/84,000≈0.83(83%) At this stage, her position reaches the pre-liquidation trigger, yet the pre-liquidation close factor (preLCF) is very low – making liquidation at this point unprofitable. #### Price Drops Further and Pre-Liquidation Becomes Profitable[](https://docs.morpho.org/learn/concepts/liquidation/#price-drops-further-and-pre-liquidation-becomes-profitable) The market continues to move and 1 WBTC reaches 83k USDC, so the collateral value now is 83k USDC. Her updated LTV is: LTV\=70,000/83,000≈0.84(84%)LTV = 70,000 / 83,000 \\approx 0.84 \\quad (84\\%) LTV\=70,000/83,000≈0.84(84%) Now the position is clearly in the pre-liquidation range. Under these conditions, the pre-liquidation close factor is recalculated using the formula: preLCF\=LLTV−LTVLLTV−preLLTV×preLCF1+LTV−preLLTVLLTV−preLLTV×preLCF2≈0.12preLCF = \\frac{LLTV - LTV}{LLTV - preLLTV} \\times preLCF\_1 + \\frac{LTV - preLLTV}{LLTV - preLLTV} \\times preLCF\_2 \\approx 0.12 preLCF\=LLTV−preLLTVLLTV−LTV​×preLCF1​+LLTV−preLLTVLTV−preLLTV​×preLCF2​≈0.12 Under some assumptions, this means that approximately 12% of the debt becomes eligible for liquidation. #### Executing the Pre-Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#executing-the-pre-liquidation) A liquidator repays 12% of Alice’s outstanding debt: Debt Repaid\=0.12×70,000\=8,400 USDCDebt\\ Repaid = 0.12 \\times 70,000 = 8,400 \\, \\text{USDC} Debt Repaid\=0.12×70,000\=8,400USDC With a pre-liquidation incentive factor (preLIF) of roughly 1.04, the seized collateral is calculated as: Collateral Seized\=8,400×1.04≈8,736 USDC(≈8.7k USDC)Collateral\\ Seized = 8,400 \\times 1.04 \\approx 8,736 \\, \\text{USDC} \\quad (\\approx 8.7k \\, \\text{USDC}) Collateral Seized\=8,400×1.04≈8,736USDC(≈8.7kUSDC) After this pre-liquidation event, Alice’s remaining debt adjusts to about 61.6k USDC and her collateral rebalances to around 74.3k USDC, effectively returning her LTV to near the preLLTV of 83%. * * * ##### Case 2: Standard Liquidation (No Pre-Liquidation Executed)[](https://docs.morpho.org/learn/concepts/liquidation/#case-2-standard-liquidation-no-pre-liquidation-executed) #### Initial Position Setup[](https://docs.morpho.org/learn/concepts/liquidation/#initial-position-setup-1) Alice deposits 1 WBTC as collateral valued at 100k USDC and borrows 70k USDC, giving an initial LTV of 70%. #### No Pre-Liquidation Trigger[](https://docs.morpho.org/learn/concepts/liquidation/#no-pre-liquidation-trigger) If no liquidator acts during the pre-liquidation phase (for example, due to rapid market movement or other factors), Alice’s position remains unchanged while the market continues to decline. #### Market Price Movement to Trigger Standard Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#market-price-movement-to-trigger-standard-liquidation) When the price falls further to 81k USDC per WBTC, the collateral value is now 81k USDC and her LTV becomes: LTV\=70,000/81,000≈0.86(86%)LTV = 70,000 / 81,000 \\approx 0.86 \\quad (86\\%) LTV\=70,000/81,000≈0.86(86%) As her LTV now exceeds the Liquidation Loan-To-Value (LLTV) of 86%, her position becomes eligible for standard liquidation. #### Executing Standard Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#executing-standard-liquidation) A liquidator repays the full 70k USDC of debt. With a standard Liquidation Incentive Factor (LIF) of approximately 1.05, the collateral seized is computed as: Collateral Seized\=70,000×1.05\=73,500 USDCCollateral\\ Seized = 70,000 \\times 1.05 = 73,500 \\, \\text{USDC} Collateral Seized\=70,000×1.05\=73,500USDC Thus, the full liquidation of Alice's position is executed. #### After Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#after-liquidation-1) * **Alice:** Her debt is cleared but she loses her collateral, with the net effect of incurring a higher loss. * **Liquidator:** Gains the liquidation bonus (the difference between repaid debt and seized collateral), though fees and slippage costs apply. In this case, the total loss for Alice is estimated to be around 2k USDC. ### Key Features of Pre-Liquidation[](https://docs.morpho.org/learn/concepts/liquidation/#key-features-of-pre-liquidation) * **Trigger Zone**: Activates when preLLTV ≤ LTV < LLTV * **Position Closure**: Limited by preLCF (typically smaller than standard liquidation) * **Incentive**: Can be dynamic (preLIF), typically lower than the standard LIF * **Borrower Impact**: Smaller, incremental losses with position deleveraging * **Implementation**: Opt-in via PreLiquidation contract * **Position After**: Partially deleveraged, returns to potentially healthier LTV ratio (assuming parameters are wisely selected) ### Comparing the Examples[](https://docs.morpho.org/learn/concepts/liquidation/#comparing-the-examples) | **Aspect** | **Case 1: Pre-Liquidation Executed** | **Case 2: No Pre-Liquidation, Standard Liquidation** | | --- | --- | --- | | **Trigger Point** | LTV climbs to ≈84% (with preLLTV at 83%) | LTV reaches 86% (LLTV threshold) | | **Liquidated Debt Portion** | Partial: 12% of the debt (8.4k USDC) | Full: 100% of the debt (70k USDC) | | **Liquidation Incentive** | PreLIF ≈ 1.04 (4% bonus) | Standard LIF ≈ 1.05 (5% bonus) | | **Collateral Seized** | ≈8.7k USDC worth for the liquidated portion | ≈72k USDC worth of collateral seized total | | **Post-Liquidation Position** | Position remains open; new debt ~61.6k USDC with ~74.3k USDC collateral; LTV restored to ≈83% | Position is fully closed | | **Borrower’s Loss** | Approximately $300 loss during partial liquidation | Higher loss; approximately $2k incurred at full liquidation | | **Potential Future Outcome** | If price recovers, Alice’s position may improve | No recovery as the position is closed | Comparing Liquidation Mechanisms[](https://docs.morpho.org/learn/concepts/liquidation/#comparing-liquidation-mechanisms) --------------------------------------------------------------------------------------------------------------------------- | Aspect | Pre-Liquidation | Standard Liquidation | | --- | --- | --- | | Trigger Threshold | preLLTV ≤ LTV < LLTV | LTV ≥ LLTV | | Position Closure | Limited by preLCF (typically less than 50% at preLLTV) | Up to 100% of debt | | Incentive | Can be dynamic, typically lower than LIF | Fixed LIF | | Borrower Impact | Smaller, incremental losses | Full one-time loss | | Position After | Partially deleveraged, returns to healthier LTV | Usually fully closed | | Implementation | Opt-in via PreLiquidation contract | Built into Morpho core | | Oracle | Market oracle or specialized oracle | Market oracle | | Opt-in Required | Yes (additional protection) | No (default protection) | Bad Debt Consideration[](https://docs.morpho.org/learn/concepts/liquidation/#bad-debt-consideration) ------------------------------------------------------------------------------------------------------- Morpho has different mechanisms for accounting for bad debts depending on the vault version. ### Morpho Vaults V1.0 - Bad Debt Realization[](https://docs.morpho.org/learn/concepts/liquidation/#morpho-vaults-v10---bad-debt-realization) The Morpho Vaults created with [the MetaMorpho FactoryV1.0](https://github.com/morpho-org/metamorpho) have a mechanism to account for and realize bad debt in the event it arises. Typically, in other lending pool designs, accrued bad debt remains in the market forever until manual intervention to pay down the bad debt. If small enough, the markets can continue functioning. If it is significant, the market becomes unusable. Morpho Vaults V1.0 treat bad debt differently. When a liquidation leaves an account with some remaining debt, and without collateral to cover it, the loss is realized and shared proportionally between all lenders. As bad debt is realized at the time it occurs, a market can be used in perpetuity. ### Morpho Vaults V1.1 - No Bad Debt Realization[](https://docs.morpho.org/learn/concepts/liquidation/#morpho-vaults-v11---no-bad-debt-realization) The Morpho Vaults created with [the MetaMorpho Factory V1.1](https://github.com/morpho-org/metamorpho-v1.1) have a different mechanism as they do not realize bad debt and behave as other lending pools with accrued debt remaining in the market forever until manual intervention to pay down the bad debt. Liquidation FAQ[](https://docs.morpho.org/learn/concepts/liquidation/#liquidation-faq) ----------------------------------------------------------------------------------------- #### At what price are liquidations done?[](https://docs.morpho.org/learn/concepts/liquidation/#at-what-price-are-liquidations-done) Liquidations occur at the current oracle price when a position's LTV exceeds the market's LLTV. The oracle price determines both when a position becomes liquidatable and the exchange rate during the liquidation process. The liquidator receives collateral valued at debt amount × LIF according to this oracle price, regardless of market conditions or price volatility elsewhere. #### What happens if the collateral price continues to fall?[](https://docs.morpho.org/learn/concepts/liquidation/#what-happens-if-the-collateral-price-continues-to-fall) If the collateral price continues to fall after a position becomes liquidatable: * The position becomes increasingly attractive for liquidators as they can seize a larger percentage of the collateral relative to its real market value * Liquidators are incentivized to act quickly to capture this value * The protocol's design encourages prompt liquidations to minimize systemic risk * There is no price floor - the position remains liquidatable until someone repays the debt #### What happens if the price recovers before liquidation happens?[](https://docs.morpho.org/learn/concepts/liquidation/#what-happens-if-the-price-recovers-before-liquidation-happens) If the collateral price recovers sufficiently before liquidation occurs: * The position's LTV may drop below the LLTV threshold * The position will no longer be liquidatable * The borrower retains their full collateral and remains responsible for their debt * This scenario highlights why borrowers should maintain a safety buffer below the LLTV #### How do competing liquidators interact? Is it first-come-first-served?[](https://docs.morpho.org/learn/concepts/liquidation/#how-do-competing-liquidators-interact-is-it-first-come-first-served) Yes, liquidations operate on a first-come-first-served basis: * The first transaction that successfully executes the liquidation claims the opportunity * There is no auction or bidding mechanism * In competitive environments, this can lead to MEV (Maximal Extractable Value) opportunities and potential gas price wars * Advanced liquidators may use flashbots or other private transaction methods to secure their liquidation #### Is there partial liquidation?[](https://docs.morpho.org/learn/concepts/liquidation/#is-there-partial-liquidation) Yes. Liquidators can choose to liquidate any amount of the borrower's debt up to the full amount. This allows for optimizing gas costs against liquidation profits, especially for large positions where full liquidation might cause significant market impact. #### How are liquidations guaranteed for assets like cbBTC/stETH?[](https://docs.morpho.org/learn/concepts/liquidation/#how-are-liquidations-guaranteed-for-assets-like-cbbtcsteth) Liquidations in Morpho are driven by economic incentives rather than absolute guarantees. The protocol doesn't perform liquidations itself; instead, when a position becomes unhealthy, it becomes eligible for liquidation by external actors. The system is designed with incentives (via the Liquidation Incentive Factor) to make liquidations profitable enough that third parties will consistently execute them. For assets like cbBTC or stETH, the key factor is whether the market's specific LIF provides enough incentive to outweigh potential costs associated with liquidating that particular collateral type. The ability to perform partial liquidations also helps with larger positions, as they can be liquidated incrementally by multiple parties or in several steps. #### Who are the liquidators and what tools do they use?[](https://docs.morpho.org/learn/concepts/liquidation/#who-are-the-liquidators-and-what-tools-do-they-use) Liquidators are permissionless participants in the Morpho ecosystem. Anyone who identifies an eligible position and has the necessary funds can perform a liquidation. The ecosystem includes a diverse range of participants, from sophisticated teams running automated bots to individuals. At a basic level, performing a liquidation only requires access to an RPC node and a wallet with sufficient funds. However, competitive liquidators typically utilize automated bots that continuously monitor onchain data (loan positions, oracle prices) to identify and execute liquidations efficiently. Some liquidators implement swap systems allowing them to seize collateral and repay loans without needing to hold the loan asset beforehand, effectively acting as a liquidity venue. The Morpho ecosystem also includes open-source liquidation bots that community members can deploy. Pre-Liquidation FAQ[](https://docs.morpho.org/learn/concepts/liquidation/#pre-liquidation-faq) ------------------------------------------------------------------------------------------------- #### Do I need to enable pre-liquidation manually?[](https://docs.morpho.org/learn/concepts/liquidation/#do-i-need-to-enable-pre-liquidation-manually) Yes, pre-liquidation is an opt-in feature. Borrowers must explicitly authorize it and set their preferred parameters. #### How much capital can pre-liquidation save?[](https://docs.morpho.org/learn/concepts/liquidation/#how-much-capital-can-pre-liquidation-save) The capital savings depend on several factors including market volatility and pre-liquidation parameters. #### Can anyone perform pre-liquidations?[](https://docs.morpho.org/learn/concepts/liquidation/#can-anyone-perform-pre-liquidations) Yes, similar to standard liquidations, pre-liquidations are open to anyone who can identify eligible positions and execute the transaction. Some gated mechanisms can be implemented, but they are not pre-built at the pre-liquidation contract level. #### How are pre-liquidation parameters determined?[](https://docs.morpho.org/learn/concepts/liquidation/#how-are-pre-liquidation-parameters-determined) Pre-liquidation parameters are fully customizable within their respective range. They should be determined using formulas that optimize for: * Creating a sufficient cushion zone between preLLTV and LLTV * Minimizing borrower losses while maintaining liquidator incentives * Ensuring the position returns to a healthy state after pre-liquidation #### What happens if no one pre-liquidates my position?[](https://docs.morpho.org/learn/concepts/liquidation/#what-happens-if-no-one-pre-liquidates-my-position) If no pre-liquidation occurs and your position's LTV reaches the LLTV, it becomes eligible for standard liquidation, which may result in higher losses. Liquidation Tools[](https://docs.morpho.org/learn/concepts/liquidation/#liquidation-tools) --------------------------------------------------------------------------------------------- * * * By understanding both standard liquidation and pre-liquidation mechanisms, users can better manage their risk on Morpho and protect their positions from adverse market movements. --- # Rewards on Morpho – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/rewards/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Rewards on Morpho On this page Chevron Right ![Morpho Rewards Concept](https://docs.morpho.org/img/homepage/concepts/concepts_rewards_light.png) What are Rewards?[](https://docs.morpho.org/learn/concepts/rewards/#what-are-rewards) ---------------------------------------------------------------------------------------- Rewards are incentives distributed to Morpho users to encourage specific behaviors like supplying assets, borrowing, or providing collateral. These rewards typically come in the form of tokens (like MORPHO or other assets) and are provided by: * The Morpho governance * Market creators bootstrapping liquidity * Vault curators attracting depositors * Token issuers promoting asset usage Types of Rewards[](https://docs.morpho.org/learn/concepts/rewards/#types-of-rewards) --------------------------------------------------------------------------------------- ### Vault Rewards[](https://docs.morpho.org/learn/concepts/rewards/#vault-rewards) Vault depositors can earn rewards from two sources: * **Vault Campaigns**: Direct rewards for depositing into a specific vault * **Market Campaigns**: Rewards automatically forwarded from underlying markets where the vault allocates This dual-source structure allows vault depositors to benefit from multiple incentive programs simultaneously. ### Market Rewards[](https://docs.morpho.org/learn/concepts/rewards/#market-rewards) Market participants can earn rewards based on their activity: * **Supply Rewards**: For supplying assets to a market * **Borrow Rewards**: For borrowing from a market It is also possible to incentivize a simple collateral deposit (without the borrow action required). Borrowers can earn rewards on their borrow position, potentially offsetting or exceeding their borrowing costs. How It Works[](https://docs.morpho.org/learn/concepts/rewards/#how-it-works) ------------------------------------------------------------------------------- 1. **Earning**: Rewards accrue automatically while you participate in incentivized vaults or markets 2. **Computation**: Rewards are calculated offchain based on your onchain activity 3. **Distribution**: Rewards become claimable through Merkl (current) or URD (legacy) systems 4. **Claiming**: Claim your earned rewards anytime with no deadline Distribution Systems[](https://docs.morpho.org/learn/concepts/rewards/#distribution-systems) ----------------------------------------------------------------------------------------------- Morpho rewards are distributed through two systems: * **Merkl** (Current): Updates every 8 hours, handles new programs * **Morpho URD** (Legacy): Handled historical programs, rewards still claimable Users simply need to participate in the protocol to earn rewards. No special actions required beyond claiming when convenient. Learn More[](https://docs.morpho.org/learn/concepts/rewards/#learn-more) --------------------------------------------------------------------------- **For Users:** * Rewards accumulate automatically while you use Morpho * Claim rewards anytime through the Morpho interface * Tutorial: [How to Claim Rewards](https://help.morpho.org/en/articles/12032660-rewards-on-the-morpho-app) **For Developers:** * Complete integration guide: [Rewards Integration](https://docs.morpho.org/build/rewards/get-started) * Technical concepts: [Reward Campaigns](https://docs.morpho.org/build/rewards/concepts/reward-campaigns) * Distribution details: [Distribution System](https://docs.morpho.org/build/rewards/concepts/distribution-system) --- # Flash Loans – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/flashloans/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Flash Loans On this page Chevron Right Flash loans are a powerful DeFi primitive that allow users to borrow assets without collateral, as long as the borrowed amount is returned within the same transaction block. What Are Flash Loans in Morpho?[](https://docs.morpho.org/learn/concepts/flashloans/#what-are-flash-loans-in-morpho) ----------------------------------------------------------------------------------------------------------------------- Morpho's flash loans are similar to other DeFi protocols where these: * Allow borrowing without prior collateral * Require repayment within the same transaction * Execute in a single block * Are primarily meant for developers and advanced users How Morpho Flash Loans Work[](https://docs.morpho.org/learn/concepts/flashloans/#how-morpho-flash-loans-work) ---------------------------------------------------------------------------------------------------------------- The core flash loan functionality is implemented through the `flashLoan` function in the Morpho contract with a corresponding callback mechanism. ### The Flash Loan Flow in Morpho[](https://docs.morpho.org/learn/concepts/flashloans/#the-flash-loan-flow-in-morpho) 1. **Initiation**: A user contract calls `morpho.flashLoan(token, amount, data)` (refer [here](https://github.com/morpho-org/morpho-blue/blob/main/test/forge/integration/CallbacksIntegrationTest.sol#L81) for the testing suite example) 2. **Asset Transfer**: Morpho transfers the requested token amount to the calling contract 3. **Callback Execution**: Morpho calls `onMorphoFlashLoan(amount, data)` on the caller contract ([here](https://github.com/morpho-org/morpho-blue/blob/main/test/forge/integration/CallbacksIntegrationTest.sol#L63) for the test example) 4. **Execution of Logic**: The user's contract executes its intended operations 5. **Repayment**: The user's contract must approve Morpho to pull back the borrowed amount 6. **Completion**: Morpho pulls the funds back from the caller contract If at any point the flow fails (especially if the repayment fails), the entire transaction reverts. Implementing a Flash Loan in Morpho[](https://docs.morpho.org/learn/concepts/flashloans/#implementing-a-flash-loan-in-morpho) -------------------------------------------------------------------------------------------------------------------------------- To use a flash loan with Morpho, you need to: 1. Create a contract that implements the `IMorphoFlashLoanCallback` interface 2. Implement the `onMorphoFlashLoan` function that will handle your logic 3. Ensure your callback function approves the Morpho contract to pull back the borrowed amount Flash Loan Use Cases with Morpho[](https://docs.morpho.org/learn/concepts/flashloans/#flash-loan-use-cases-with-morpho) -------------------------------------------------------------------------------------------------------------------------- 1. **Arbitrage**: Execute trades across different protocols to profit from price discrepancies 2. **Collateral Swaps**: Replace one collateral type with another in a single transaction 3. **Self-Liquidation**: Liquidate your own position to avoid liquidation penalties 4. **Leverage Positions**: Flash loans can simplify leveraged deposit workflows by avoiding onchain looping. Instead of repeatedly borrowing and re-depositing to build leverage, you can use a flash loan to achieve your exact target leverage in a single transaction with more granular control 5. **Flash Actions**: Combine multiple Morpho operations in a single transaction Security Considerations for Morpho Flash Loans[](https://docs.morpho.org/learn/concepts/flashloans/#security-considerations-for-morpho-flash-loans) ------------------------------------------------------------------------------------------------------------------------------------------------------ 1. **Transaction Atomicity**: If your callback fails to approve the repayment, the entire transaction will revert 2. **Contract Security**: Never leave funds in your flash loan contract permanently 3. **Reentrancy**: Be careful about calling external contracts within your flash loan logic 4. **Gas Management**: Flash loans are complex operations that consume significant gas Example Implementation[](https://docs.morpho.org/learn/concepts/flashloans/#example-implementation) ------------------------------------------------------------------------------------------------------ The [FlashBorrowerMock.sol](https://github.com/morpho-org/morpho-blue/blob/main/src/mocks/FlashBorrowerMock.sol) contract in Morpho's repository provides a simple example of how to implement a flash loan contract: Copy `// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IERC20} from "./interfaces/IERC20.sol"; import {IMorpho} from "../interfaces/IMorpho.sol"; import {IMorphoFlashLoanCallback} from "../interfaces/IMorphoCallbacks.sol"; contract FlashBorrowerMock is IMorphoFlashLoanCallback { IMorpho private immutable MORPHO; constructor(IMorpho newMorpho) { MORPHO = newMorpho; } function flashLoan(address token, uint256 assets, bytes calldata data) external { MORPHO.flashLoan(token, assets, data); } function onMorphoFlashLoan(uint256 assets, bytes calldata data) external { require(msg.sender == address(MORPHO)); address token = abi.decode(data, (address)); IERC20(token).approve(address(MORPHO), assets); // Add your logic here. // e.g. swap, liquidate, leverage, and much more... } }` This minimal implementation demonstrates the key components: * **Constructor**: Stores the Morpho contract address * **flashLoan function**: External entry point that initiates the flash loan * **onMorphoFlashLoan callback**: Implements the required callback interface where you add your custom logic (arbitrage, swaps, leverage, etc.) * **Security check**: Verifies the caller is the Morpho contract * **Repayment approval**: Approves Morpho to pull back the borrowed assets Morpho-Specific Callbacks[](https://docs.morpho.org/learn/concepts/flashloans/#morpho-specific-callbacks) ------------------------------------------------------------------------------------------------------------ Morpho implements a broader callback system: * `IMorphoLiquidateCallback`: For liquidation operations * `IMorphoRepayCallback`: For repayment operations * `IMorphoSupplyCallback`: For supply operations * `IMorphoSupplyCollateralCallback`: For supplying collateral This comprehensive callback system allows for more complex transaction patterns beyond simple flash loans, such as the "Flash Actions" test which combines supply, borrow, repay, and withdraw operations in a single transaction flow. [https://dune.com/morpho/morpho-blue-dashboard#flashloans](https://dune.com/morpho/morpho-blue-dashboard#flashloans) --- # Morpho Governance – Morpho Docs [Skip to content](https://docs.morpho.org/learn/governance/organization/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Morpho Governance On this page Chevron Right Morpho Protocol governance is intentionally limited in scope. The core smart contract code is immutable. The powers of the governance include: * Control over the MORPHO tokens in the governance treasury * Ownership of the upgradeable MORPHO token contract * Activating and adjusting the fee switch(Link:[https://github.com/morpho-org/morpho-blue/blob/main/src/Morpho.sol#L123](https://github.com/morpho-org/morpho-blue/blob/main/src/Morpho.sol#L123) ) (capped at a maximum of 25% of interest paid by borrowers) and setting a set a fee recipient address * Whitelisting new [LLTVs and IRMs](https://docs.morpho.org/learn/concepts/market#dao-approved-lltv--irm) for use in the Morpho Protocol * Granting licenses of the Morpho Protocol code by updating the ENS record at morpho-blue-core-license-grants.morpho.eth * Ownership of the morpho.eth ENS domain and subdomains, which are used for clearly labelling relevant protocol addresses The governance discussions happen on [the Morpho governance forum](https://forum.morpho.org/) . This discussions can lead to proposals that will be voted on. MORPHO token-holders can vote on the actions taken by the Morpho governance using the Snapshot interface at [vote.morpho.org](http://vote.morpho.org/) . Anyone who holds or has delegated to them at least 500k MORPHO tokens can submit a proposal for voting. This threshold is adjustable by the governance. Once approved by a governance vote, actions are implemented by the 5/9 [governance Multisig](https://docs.morpho.org/learn/governance/organization#multisig-and-addresses) whose members are decided by the Morpho governance. Morpho Association[](https://docs.morpho.org/learn/governance/organization/#morpho-association) -------------------------------------------------------------------------------------------------- The Morpho Association is a French nonprofit entity grouping the main contributors and users of the Morpho protocol. Its aim is to develop the Morpho protocol by funding contributors, or by facilitating access to the protocol for users and developers. In practice, the association: * Hosts a front end to the protocol to facilitate the access of new users to Morpho: [morpho.org](https://morpho.org/) * Hosts technical documentation to facilitate the work of new Morpho developers * Holds the intellectual property of open-source codebases such as [morpho-optimizers](https://github.com/morpho-org/morpho-optimizers)  and hosts it on the morpho-org GitHub under a GPL3 license. The association does not research or develop Morpho software, contributors or [Institut Louis Bachelier](https://www.institutlouisbachelier.org/) (ILB) do. Multisig and Addresses[](https://docs.morpho.org/learn/governance/organization/#multisig-and-addresses) ---------------------------------------------------------------------------------------------------------- | Name | Address/Details | | --- | --- | | **Morpho Ownerless Admin** | [0x6F073477672F7202272b2684A56AB81Fc0dBaEF4](https://etherscan.io/address/0x6F073477672F7202272b2684A56AB81Fc0dBaEF4) | | **SafeOwner** | [0x0b9915C13e8E184951Df0d9C0b104f8f1277648B](https://etherscan.io/address/0x0b9915C13e8E184951Df0d9C0b104f8f1277648B) | | **MorphoContracts** | See the [Addresses](https://docs.morpho.org/get-started/resources/addresses#1)
section | | **Zodiac Delay Modifier** | [0x68d11129a514C45716e55B9771813f117c4c2FA5](https://etherscan.io/address/0x68d11129a514C45716e55B9771813f117c4c2FA5) | | **Zodiac Roles Modifier** | [0xa8b9650935EFb3F2972D1Ca4D3A8BA752D1A807A](https://etherscan.io/address/0xa8b9650935EFb3F2972D1Ca4D3A8BA752D1A807A) | | **Morpho governance** (Ethereum) | morpho.eth (5/9 multisig): [0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa](https://etherscan.io/address/0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa) | | **Morpho governance** (Base) | morpho.eth (5/9 multisig): [0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa](https://basescan.org/address/0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa) | | **Morpho Operator** | morpho-operator.eth (3/9 multisig): [0x640428D38189B11B844dAEBDBAAbbdfbd8aE0143](https://etherscan.io/address/0x640428D38189B11B844dAEBDBAAbbdfbd8aE0143) | | **MORPHO Rewards Multisig** (Ethereum) | [0xF057afeEc22E220f47AD4220871364e9E828b2e9](https://etherscan.io/address/0xF057afeEc22E220f47AD4220871364e9E828b2e9)
(3/5) | | **MORPHO Rewards Multisig** (Base) | [0x5Eb982bb1E620cC3927E5CF8A5D207e667643297](https://basescan.org/address/0x5Eb982bb1E620cC3927E5CF8A5D207e667643297)
(3/5) | --- # Risk & Security Documentation – Morpho Docs [Skip to content](https://docs.morpho.org/learn/resources/risks/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Risk & Security Documentation On this page Chevron Right By using Morpho or Morpho Vaults, you assume the risks associated. The following section provides an overview of different types of risks you should be aware of when using Morpho and Morpho Vaults. This overview is not exhaustive and may not cover all potential risks to which you might be exposed. Morpho is committed to use industry-leading security practices. Yet, there are still a number of risks associated with the use of Morpho and Morpho Vaults that users must be aware of. Morpho Security practices[](https://docs.morpho.org/learn/resources/risks/#morpho-security-practices) -------------------------------------------------------------------------------------------------------- Morpho is known for its industry-leading security practices and follows a multi-faceted approach to security. Morpho security practices include formal verification, mutation tests, fuzzing, unit testing, and peer reviews that can be found within respective [Github repositories](https://github.com/morpho-org) . External measures include professional security reviews, contests, and pre/post-deployment bounties. A whole article was dedicated to the [Morpho Security Framework](https://morpho.org/blog/morpho-blue-security-framework-building-the-most-secure-lending-protocol/) . Over time, Morpho has been audited 34 times by 14 different security firms. This covers: * Morpho V0 * Morpho Vaults V1 * Morpho Markets V1 * Morpho Vaults V2 * Morpho Front-ends To our knowledge, this makes Morpho the most audited project in the world. Smart Contract Risk[](https://docs.morpho.org/learn/resources/risks/#smart-contract-risk) -------------------------------------------------------------------------------------------- There is an inherent risk that the protocol could contain a smart contract vulnerability or bug. Several security measures are employed to mitigate this risk: * Core contracts are immutable * It is a simple and open-sourced [code base](https://docs.morpho.org/get-started/resources/contracts) that avoids complexities * The code has been audited by multiple auditors, refer to the [security reviews](https://docs.morpho.org/get-started/resources/audits) section * [Formal verification](https://docs.morpho.org/learn/resources/risks#formal-verifications) has been applied using [Certora](https://www.certora.com/) * 2 ongoing bug bounty programs: 1. [Immunefi - $2,500,000](https://immunefi.com/bounty/morpho/) (Morpho & Morpho vaults) 2. [Cantina - $2,500,000](https://cantina.xyz/bounties/35a5f0a1-2ffd-432c-8f3b-77d169add8c3) (Morpho & Morpho vaults) Oracle Risk[](https://docs.morpho.org/learn/resources/risks/#oracle-risk) ---------------------------------------------------------------------------- Every Morpho market is connected to an oracle, established at market creation. It is important to understand that no oracle is immune to price manipulation, which can lead to liquidations or even bad debt. However, some oracles will be more resistant and resilient than others. When assessing the reliability of an oracle, consider factors such as safety and liveness, particularly if the oracle is centralized. Also, take into account the settings and processes pertaining to the definition and frequency of price updates. Counterparty Risk[](https://docs.morpho.org/learn/resources/risks/#counterparty-risk) ---------------------------------------------------------------------------------------- Before entering a market, it's crucial to conduct thorough due diligence on the loan asset and the collateral asset to understand who holds power over them. Factors to consider include centralization, as a centralized governance could blacklist a specific user or even Morpho, resulting in a loss of funds. The distribution of the asset is also important, as a high concentration can cause extreme price fluctuations. Liquidation Risk[](https://docs.morpho.org/learn/resources/risks/#liquidation-risk) -------------------------------------------------------------------------------------- ### Liquidation Risk (for borrowers)[](https://docs.morpho.org/learn/resources/risks/#liquidation-risk-for-borrowers) Each Morpho market is linked to an immutable Liquidation Loan-to-Value (LLTV). If the Loan-To-Value of your position exceeds this LLTV, you will face liquidation. When borrowing on Morpho, carefully select the market and diligently manage the health of your position. ### Bad Debt Risk (for lenders)[](https://docs.morpho.org/learn/resources/risks/#bad-debt-risk-for-lenders) There could be circumstances in which the collateral's value for a position drops below the borrowed amount before liquidators can close the position. In such cases, the borrower holding this position has no incentive to repay the debt. Morpho has different mechanisms for accounting for bad debts. You can read more about it in the [bad debt section](https://docs.morpho.org/learn/concepts/liquidation#bad-debt) . ### Liquidity Risk (for lenders)[](https://docs.morpho.org/learn/resources/risks/#liquidity-risk-for-lenders) Liquidity refers to the access to supplied assets. A lack of liquidity can prevent suppliers from withdrawing their assets for a certain period of time. Liquidity issues are tackled through the interest rate model. Before providing liquidity, it's essential to understand the market's interest rate model. This understanding will help you estimate the level of liquidity you can expect in that market. Morpho Vaults Specific Risks[](https://docs.morpho.org/learn/resources/risks/#morpho-vaults-specific-risks) -------------------------------------------------------------------------------------------------------------- ### Vault Governance Risks[](https://docs.morpho.org/learn/resources/risks/#vault-governance-risks) Key [roles](https://github.com/morpho-org/metamorpho#roles) within a Morpho Vault wield significant power, impacting user interests: * The [Owner](https://github.com/morpho-org/metamorpho#owner) has the ability to set performance fees, appoint curators and allocators, and adjust various other settings. Morpho Vaults impose a timelock on actions that may affect users' interests. * The [Curator](https://github.com/morpho-org/metamorpho#curator) can enable/disable markets. A timelock allows users to react to changes initiated by the curator. * The [Allocators](https://github.com/morpho-org/metamorpho#allocator) determine markets supply/withdrawal order, influencing returns and liquidity for suppliers. * The [Guardian](https://github.com/morpho-org/metamorpho#guardian) has the ability to revoke timelocked actions, providing an additional layer of protection for users. When investing in a Morpho Vault, it is important to conduct thorough due diligence on the vault's settings and its allocation strategy, as well as to stay up to date with its changes. ### Inflation Front-Running Attack Protection[](https://docs.morpho.org/learn/resources/risks/#inflation-front-running-attack-protection) Morpho Vaults V1, like all ERC4626-compliant vaults, have a potential vulnerability to what is known as an "inflation front-running attack," particularly when the vault is newly created and empty. This vulnerability is explicitly mentioned in the Morpho Vault contract: Copy `/// @inheritdoc IERC4626 /// @notice For tokens with 18 decimals, the protection against the inflation front-running attack is low. To /// protect against this attack, vault deployers should make an initial deposit of a non-trivial amount in the vault /// or depositors should check that the share price does not exceed a certain limit.` #### What is an Inflation Front-Running Attack?[](https://docs.morpho.org/learn/resources/risks/#what-is-an-inflation-front-running-attack) This attack works as follows: 1. An attacker sees a pending transaction where a user intends to deposit into an empty (or nearly empty) vault 2. The attacker front-runs the transaction with a minimal deposit followed by a large donation directly to the vault 3. This artificially inflates the share price of the vault 4. When a user’s deposit execute and is small enough, they receive significantly fewer shares than expected 5. The attacker, as the majority shareholder, can benefit from this manipulation if more than one user deposit receives fewer shares than expected This vulnerability is most pronounced for tokens with 18 or more decimals, where the `DECIMALS_OFFSET` in the Morpho Vault V1 contract is zero. #### Protection Strategies[](https://docs.morpho.org/learn/resources/risks/#protection-strategies) ##### For Vault Deployers and Market Creators[](https://docs.morpho.org/learn/resources/risks/#for-vault-deployers-and-market-creators) **Initial Deposit Strategy (Strongly recommended)** Vault deployers and market creators should make an initial deposit of 1e9 shares on behalf of the address `0x000000000000000000000000000000000000dEaD` immediately after vault and market creation in order to implement a permanent protection. ##### For Users and Integrators[](https://docs.morpho.org/learn/resources/risks/#for-users-and-integrators) **Share Price Verification** Users depositing into vaults should implement checks to prevent falling victim to this attack: 1. **For New or Low-Liquidity Vaults**: Implement a maximum share price check with slippage protection: Copy `// Example protection for users uint256 maxAcceptableSharePrice = 1e27 * 1.0001; // Slightly above the expected 1:1 ratio require(vault.previewDeposit(amount) >= computeExpectedShares(amount, maxAcceptableSharePrice));` 2. **For Established Vaults**: Standard slippage checks are typically sufficient, but should still be used #### Best Practices for Morpho Vault Curators[](https://docs.morpho.org/learn/resources/risks/#best-practices-for-morpho-vault-curators) 1. **Initial Protection**: Always make an initial deposit of at least 1e9 shares immediately after vault creation on behalf of the address `0x000000000000000000000000000000000000dEaD` 2. **Timelock**: Implement both a 3-day timelock 3. **Monitoring**: Monitor the vault's share price relative to the underlying asset price to detect potential manipulation #### Technical Details[](https://docs.morpho.org/learn/resources/risks/#technical-details) The vulnerability exists because in ERC4626 vaults, the relationship between shares and assets determines the exchange rate. In an empty vault with no protection mechanisms: 1. The attacker deposits a minimal amount (e.g., 1 wei of the token) and receives 1 share 2. The attacker then transfers a large amount directly to the vault (e.g., 100M tokens) 3. This creates an exchange rate where 1 share ≈ 100M tokens 4. A user depositing 1 token would receive 0 shares due to the inflated exchange rate The protection mechanisms recommended above prevent this by ensuring the vault has enough tokens to dilute to make the share price increase by donation prohibitively expensive or by adding checks that would reject transactions with suspicious exchange rates. #### Additional Resources[](https://docs.morpho.org/learn/resources/risks/#additional-resources) For more information on ERC4626 and the inflation attack vulnerability: * [OpenZeppelin ERC4626 Documentation](https://docs.openzeppelin.com/contracts/5.x/erc4626) * [EIP-4626: Tokenized Vault Standard](https://eips.ethereum.org/EIPS/eip-4626) * [YieldBox Approach to ERC4626 Security](https://github.com/boringcrypto/YieldBox) --- # The MORPHO token – Morpho Docs [Skip to content](https://docs.morpho.org/learn/governance/morpho-token/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu The MORPHO token On this page Chevron Right MORPHO is the Morpho Protocol's governance token. The governance system uses a weighted voting system in which the number of MORPHO tokens held determines voting power. MORPHO holders can vote on changes or improvements to the protocol, see [this section](https://docs.morpho.org/learn/governance/organization#morpho-dao-governance) to get the exhaustive list of actions. Legacy and Wrapped MORPHO[](https://docs.morpho.org/learn/governance/morpho-token/#legacy-and-wrapped-morpho) ---------------------------------------------------------------------------------------------------------------- The original, now legacy, MORPHO token was deployed as an immutable contract and lacked functionality associated with onchain vote accounting. The governance voted to create a contract to wrap the legacy tokens into wrapped MORPHO to enable onchain vote tracking functionality in [MIP-75](https://snapshot.org/#/morpho.eth/proposal/0x53c5f01dac396b97650f37fccfa0910457b27a1fc06c5ec5d54ee0e6e5408180) . In addition to onchain vote tracking, using an upgradeable token makes it possible to conform to a crosschain interoperability standard in the future, minimizing friction for MORPHO holders who want to move their tokens between chains. Although legacy MORPHO tokens can be freely converted to wrapped MORPHO 1:1 via the wrapper contract, there could be a risk that legacy tokens might be used mistakenly in external integrations, such as exchanges. To prevent this, only the wrapped MORPHO will be transferable. Users can easily wrap their existing legacy MORPHO tokens on the Morpho App. MORPHO Token Addresses[](https://docs.morpho.org/learn/governance/morpho-token/#morpho-token-addresses) ---------------------------------------------------------------------------------------------------------- You can find MORPHO token contracts, related contracts addresses as well as Github repositories in the [addresses section](https://docs.morpho.org/get-started/resources/addresses#morpho-token) . The MORPHO token has a maximum supply of 1,000,000,000 MORPHO. Token Distribution & Vesting[](https://docs.morpho.org/learn/governance/morpho-token/#token-distribution--vesting) --------------------------------------------------------------------------------------------------------------------- The overall distribution of MORPHO tokens, including vested and unvested allocations, as of 7 November 2024. ![Morpho distribution](https://docs.morpho.org/img/morpho-distribution6.png) ### Morpho governance[](https://docs.morpho.org/learn/governance/morpho-token/#morpho-governance) 35.4% of MORPHO tokens are owned and controlled by the Morpho governance. Holders of the MORPHO token can vote on how these tokens are used. ### Users & Launch Pools[](https://docs.morpho.org/learn/governance/morpho-token/#users--launch-pools) 4.9% of MORPHO tokens have been distributed from the Morpho governance to users of the Morpho Protocol and launch pool participants. The Morpho governance continues to distribute MORPHO token as rewards. ### Morpho Association[](https://docs.morpho.org/learn/governance/morpho-token/#morpho-association) 6.3% of MORPHO tokens are allocated to the Morpho Association for ecosystem development. This allocation can be used to fund partnerships, contributors, and any other initiatives that help grow the Morpho Protocol and advance Morpho’s network. ### Reserve for Contributors[](https://docs.morpho.org/learn/governance/morpho-token/#reserve-for-contributors) 5.8% of MORPHO tokens are reserved for contributors to the Morpho Protocol for their role in the development and growth of the network. This reserve includes unallocated tokens [set aside by the Morpho governance](https://forum.morpho.org/t/mip1-early-core-contributors-allocation/94) for future contributors to the Morpho Protocol such as Morpho Association employees, service providers, contractors, and research institutes. ### Strategic Partners[](https://docs.morpho.org/learn/governance/morpho-token/#strategic-partners) 27.5% of MORPHO tokens have been allocated to Strategic Partners tokens in exchange for providing support — monetary or otherwise — to the Morpho Protocol. These MORPHO tokens are distributed according to three vesting schedules based on the time these Strategic Partners joined the Morpho ecosystem. **Cohort 1**: 4.0% allocated over a 3 year vest, with a 6 month lockup from when the MORPHO token contract was deployed on 24 June 2022. **Cohort 2**: 16.8% originally allocated over a 3 year vest, with a 6 month lockup from 24 June 2022. However, these strategic partners have agreed to relock to a 6 month linear vesting, following a 6 month lockup from 3 October 2024. This means 100% is vested by 3 October 2025 at the latest. **Cohort 3**: 6.7% allocated over 2 year linear vest, following a 1 year lockup from 21 November 2024. This means 100% is vested by 21 November 2027 at the latest. ### Founders[](https://docs.morpho.org/learn/governance/morpho-token/#founders) 15.2% of MORPHO tokens have been allocated to Morpho’s founders. The tokens were originally allocated over 3 year vest, with a 1-year lockup from when the token was deployed on 24 June 2022. However, all co-founders have agreed to relock to additional 2 year linear vest, following a 1 year lockup from the earliest of any future transferability date or May 17th 2025. This means 100% is vested by 17 May 2028 at the latest. ### Early Contributors[](https://docs.morpho.org/learn/governance/morpho-token/#early-contributors) 4.9% of MORPHO tokens have been allocated to early contributors, including Morpho Association's contributors, independent researchers, and advisors, in exchange for contributions to the Morpho Protocol. These tokens have been subject to either: * A 3-year vesting schedule with a 6-month lockup, or * A 4-year vesting schedule with a 4-month lockup. Circulating Supply[](https://docs.morpho.org/learn/governance/morpho-token/#circulating-supply) -------------------------------------------------------------------------------------------------- The circulating supply on transferability date is expected to be approximately 11.2%. The chart below shows how the circulating supply of MORPHO tokens might evolve over time: ![Morpho distribution](https://docs.morpho.org/img/morpho-circ-supply.png) _Note: the evolution of the MORPHO circulating supply over time is subject to change as the governance makes future decisions on use of reserves and rate of distributions._ Initial Non-Transferability Phase[](https://docs.morpho.org/learn/governance/morpho-token/#initial-non-transferability-phase) -------------------------------------------------------------------------------------------------------------------------------- While token-based governance allows anyone to own a share of the Morpho network, many token launches are very unfair because the launch date & price are often a centralized decision. Moreover, there is usually a large information asymmetry between the initial team/investors and the potential buyers. The MORPHO token was launched as non-transferable to tackle those issues, allowing the governance to turn on transferability anytime. This enabled the protocol to reach meaningful traction prior to a decentralized token launch process. Under this vision, a good equilibrium for the control of a governance is a clear distribution between: 1. Users: To own a share of the network and to provide a positive feedback loop on the product. 2. Contributors: To keep improving and building based on the user's feedback and on their technical vision. 3. Strategic Partners: To provide capital and guidance to fuel those contributions. The current state of distributions in categories 2. and 3. are described above. As for 1., it is described in [the Rewards section](https://docs.morpho.org/learn/concepts/rewards#uniform-rate-programs) . Morpho governance Voted to Enable Token Transferability[](https://docs.morpho.org/learn/governance/morpho-token/#morpho-governance-voted-to-enable-token-transferability) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Although initially deployed as a non-transferable token for the reasons mentioned above, the Morpho governance voted to enable the transferability of the MORPHO token to advance Morpho’s mission to make financial infrastructure a public good. Since launching in June 2022, the governance has progressively distributed ownership to the protocol’s users, strategic partners, risk curators, and other contributors aligned with Morpho's long-term vision. Now, by enabling token transferability, the Morpho governance is opening ownership of the Morpho network to anyone. As discussed [in the community forum](https://forum.morpho.org/t/inviting-the-morpho-community-to-discuss-transferability/742) , this move is a key step toward realizing the protocol’s mission of transforming financial infrastructure into a public good. It will empower a broader range of participants to engage with and contribute to the Morpho ecosystem, bringing new perspectives and ensuring that governance decisions reflect the interests of a more diverse community. MORPHO token transferability was enabled on November 21, 2024. FAQ[](https://docs.morpho.org/learn/governance/morpho-token/#faq) -------------------------------------------------------------------- ### Why are there two MORPHO tokens? What’s the difference between them?[](https://docs.morpho.org/learn/governance/morpho-token/#why-are-there-two-morpho-tokens-whats-the-difference-between-them) The original, now legacy, MORPHO token was deployed as an immutable contract and lacked functionality associated with onchain vote accounting. The Morpho governance voted to create a contract to wrap the legacy tokens into wrapped MORPHO to enable onchain vote tracking functionality in [MIP-75](https://snapshot.box/#/s:morpho.eth/proposal/0x53c5f01dac396b97650f37fccfa0910457b27a1fc06c5ec5d54ee0e6e5408180) . In addition to onchain vote tracking, using an upgradeable token makes it possible to conform to a crosschain interoperability standard in the future, minimizing friction for MORPHO holders who want to move their tokens between chains. Although legacy MORPHO tokens can be freely converted to wrapped MORPHO 1:1 via [the wrapper contract](https://etherscan.io/address/0x9d03bb2092270648d7480049d0e58d2fcf0e5123) , there could be a risk that legacy tokens might be used mistakenly in external integrations, such as exchanges. To prevent this, only the wrapped MORPHO is transferable. Users can easily wrap their existing legacy MORPHO tokens on the Morpho App (see How to wrap [here](https://docs.morpho.org/learn/governance/morpho-token#how-to-wrap-the-legacy-morpho-token) ). ### How to wrap the Legacy MORPHO token on the Morpho interface[](https://docs.morpho.org/learn/governance/morpho-token/#how-to-wrap-the-legacy-morpho-token-on-the-morpho-interface) If you hold Legacy MORPHO token, just go to [app.morpho.org](https://app.morpho.org/?network=mainnet) , connect your wallet holding the legacy tokens, and a banner will appear on top of the screen. This banner will allow you to migrate your Morpho Tokens. Click on the `Wrap` button at the top right of the Morpho interface. ![Morpho wrapping step 1](https://docs.morpho.org/img/token-wrapping-app1-v2.png) Clicking on the `Wrap` button will trigger a modal, showing your Legacy MORPHO token balance and proposing you to wrap it. ![Morpho wrapping step 2](https://docs.morpho.org/img/token-wrapping-app2-v2.png) Then click on the `Wrap MORPHO` button and it will trigger: 1. A transaction to approve the bundler to wrap the Legacy MORPHO tokens. 2. A transaction to wrap the Legacy MORPHO tokens into the wrapped MORPHO token. ### How to wrap the Legacy MORPHO token at contract level[](https://docs.morpho.org/learn/governance/morpho-token/#how-to-wrap-the-legacy-morpho-token-at-contract-level) If you hold Legacy MORPHO tokens and want to migrate them onchain by yourself without going through the Morpho app, you can directly interact at contract level, using Etherscan for instance. To do so, you will have to: * **Connect** your wallet to Etherscan. * **Approve** your Legacy MORPHO tokens to the wrapper. This can be done with [the legacy token contract's `approve` function](https://etherscan.io/address/0x9994E35Db50125E0DF82e4c2dde62496CE330999#writeContract#F1) , (the arguments should be the wrapper contract’s address and your amount of legacy tokens). E.g: - Wrapper address: 0x9D03bb2092270648d7480049d0E58d2FcF0E5123 - 1000000000000000000 for 1 Legacy MORPHO Token (18 decimals) ![Morpho Etherscan wrapping step 1](https://docs.morpho.org/img/token-wrapping-etherscan1.png) * **Migrate** your tokens on the wrapper by calling [the wrapper contract’s `depositFor` function](https://etherscan.io/address/0x9d03bb2092270648d7480049d0e58d2fcf0e5123#writeContract#F1) (the arguments should be your address, or another address if you want another recipient for the migrated tokens, and your amount of legacy tokens). ![Morpho Etherscan wrapping step 2](https://docs.morpho.org/img/token-wrapping-etherscan2.png) Feel free to get in touch via the chatbox on **[help.morpho.org](https://help.morpho.org/) **. --- # Audits - Security Reviews – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/audits/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Audits - Security Reviews On this page Chevron Right | Auditors | Scope | Date | Report | | --- | --- | --- | --- | | [Spearbit](https://spearbit.com/) | Vaults V2 - Adapters | 2025-09-11 | [spearbit-report](https://github.com/morpho-org/vault-v2-adapter-registries/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Vaults V2 | 2025-11-08 | [spearbit-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [ChainSecurity](https://www.chainsecurity.com/) | Vaults V2 | 2025-09-15 | [chainsecurity-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [Blackthorn](https://www.blackthorn.xyz/) | Vaults V2 | 2025-09-15 | [blackthorn-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [Cantina Contest](https://cantina.xyz/competitions/523e1540-f8c3-45ae-9c5d-b6d35d3a326c) | Vaults V2 | 2025-07-15 | [chainsecurity-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [Zellic](https://www.zellic.io/) | Vaults V2 | 2025-07-15 | [zellic-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Vaults V2 | 2025-05-19 | [spearbit-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Morpho V1 - Morpho Periphery | 2024-10-29 | [spearbit-report](https://github.com/morpho-org/pre-liquidation/tree/main/audits) | | [ABDK Consulting](https://abdk.consulting/) | Morpho V1 - Morpho Periphery | 2024-11-01 | [ABDK-report](https://github.com/morpho-org/pre-liquidation/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Morpho V1 - Morpho Periphery | 2024-11-23 | [cantina-managed-review](https://github.com/morpho-org/metamorpho-v1.1/tree/main/audits) | | [Open Zeppelin](https://www.openzeppelin.com/) | Morpho V1 - Morpho Periphery | 2024-11-16 | [MetaMorpho Diff Audit](https://github.com/morpho-org/metamorpho-v1.1/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Morpho V1 - Public Allocator | 2024-03-11 | [cantina-managed-review](https://github.com/morpho-org/public-allocator/tree/main/audits) | | [Cantina Contest](https://cantina.xyz/competitions/d86b7f95-e574-4092-8ea2-78dcac2f54f1) | Morpho V1 | 2023-11 to 2023-12 | [cantina-competition](https://github.com/morpho-org/morpho-blue/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Morpho V1 | 2023-10-16 | [cantina-managed-review](https://github.com/morpho-org/morpho-blue/tree/main/audits) | | [Open Zeppelin](https://www.openzeppelin.com/) | Morpho V1 | 2023-10-13 | [open-zeppelin](https://github.com/morpho-org/morpho-blue/tree/main/audits) | | [Cantina Contest](https://cantina.xyz/competitions/8409a0ce-6c21-4cc9-8ef2-bd77ce7425af) | Morpho V1 - Morpho Periphery | 2023-11 to 2023-12 | [cantina-competition](https://github.com/morpho-org/metamorpho/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Morpho V1 - Morpho Periphery | 2023-11-16 | [cantina-managed-review](https://github.com/morpho-org/metamorpho/tree/main/audits) | | [Open Zeppelin](https://www.openzeppelin.com/) | Morpho V1 - Morpho Periphery | 2023-11-16 | [open-zeppelin](https://github.com/morpho-org/metamorpho/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Morpho V0 (AaveV3) | 2023-06-19 | [spearbit-report](https://cdn.morpho.org/documents/Spearbit_19062023.pdf) | | [Spearbit](https://spearbit.com/) | Morpho V0 (AaveV3) | 2023-05-04 | [spearbit-report](https://cdn.morpho.org/documents/Spearbit_04052023.pdf) | | [Runtime Verification](https://runtimeverification.com/) | Morpho V0 (AaveV3) | 2023-05-02 | [runtime-verification-report](https://cdn.morpho.org/documents/Runtime_02052023.pdf) | | [Spearbit](https://spearbit.com/) | Morpho V0 | 2023-03-01 | [spearbit-report](https://cdn.morpho.org/documents/Spearbit_010323.pdf) | | [Pessimistic](https://pessimistic.io/) | Morpho V0 | 2023-02-20 | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_200223.pdf) | | [Spearbit](https://spearbit.com/) | Morpho V0 \[Draft\] | 2022-12-06 | [spearbit-draft-report](https://cdn.morpho.org/documents/Spearbit_morpho_draft_061222.pdf) | | [Pessimistic](https://pessimistic.io/) | Morpho V0 | 2022-10-06 | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_061022.pdf) | | [Omniscia](https://omniscia.io/) | Morpho V0 | 2022-08-25 | [omniscia-report](https://omniscia.io/reports/morpho-labs-tokenized-vaults/) | | [Spearbit](https://spearbit.com/) | Morpho V0 (AaveV2) | 2022-08-24 | [spearbit-report](https://cdn.morpho.org/documents/MorphoAaveV2_Audit_Spearbit.pdf) | | [Chainsecurity](https://chainsecurity.com/) | Morpho V0 (AaveV3) \[Non Ethereum\] | 2022-08-19 | [chainsecurity-report](https://cdn.morpho.org/documents/MorphoAaveV3_Audit_ChainSecurity.pdf) | | [Omniscia](https://omniscia.io/) | Morpho Datastructures | 2022-08-17 | [omniscia-report](https://cdn.morpho.org/documents/MorphoAaveV2_Audit_Omniscia.pdf) | | [Pessimistic](https://pessimistic.io/) | Morpho V0 (AaveV2) | 2022-07-25 | [pessimistic-report](https://cdn.morpho.org/documents/MorphoAaveV2_Audit_Pessimistic.pdf) | | [Trail of Bits](https://www.trailofbits.com/) | Morpho V0 (CompoundV2) | 2022-07-21 | [trail-of-bits-report](https://cdn.morpho.org/documents/TrailOfBits_210722.pdf) | | [Omniscia](https://omniscia.io/) | MORPHO Token | 2022-06-15 | [omniscia-report](https://omniscia.io/morpho-specialized-token/) | | [Trail of Bits](https://www.trailofbits.com/) | Morpho V0 (CompoundV2) | 2022-06-03 | [trail-of-bits-report](https://cdn.morpho.org/documents/TrailOfBits_030622.pdf) | | [Spearbit](https://spearbit.com/) | Morpho V0 (AaveV2) | 2022-09-05 | [spearbit-report](https://cdn.morpho.org/documents/Spearbit_090522.pdf) | | [Pessimistic](https://pessimistic.io/) | \[Beta\] Morpho V0 (CompoundV2) | 2022-04-25 | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_250422.pdf) | | [Pessimistic](https://pessimistic.io/) | \[Beta\] Morpho V0 (AaveV2) | 2022-03-08 | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_080322.pdf) | | [Pessimistic](https://pessimistic.io/) | \[Beta\] Morpho V0 (AaveV2) | 2022-02-16 | [pessimistic-report](https://cdn.morpho.org/documents/pessimistic_160222.pdf) | | [Pessimistic](https://pessimistic.io/) | \[Alpha\] Morpho V0 (AaveV2) | 2022-01-11 | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_110122.pdf) | | [Solidified](https://www.solidified.io/) | \[Alpha\] Morpho V0 (CompoundV2) | 2021-11-04 | [solidified-report](https://cdn.morpho.org/documents/Solidified_041121.pdf) | | [Lexfo](https://www.lexfo.fr/en/) | Morpho-related DNS's & Morpho-related Github's | 2023-05-10 | [Lexfo\_250523.pdf](https://cdn.morpho.org/documents/Lexfo_250523.pdf) | | [Securing](https://www.securing.biz/) | \[Beta\] Morpho Association dApp | 2022-04-04 | [MorphoDAO\_Frontend\_04042022.pdf](https://cdn.morpho.org/documents/MorphoDAO_Frontend_04042022.pdf) | --- # Morpho Docs [Skip to content](https://docs.morpho.org/learn/resources/formal-verification/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu On this page Chevron Right Formal Verification[](https://docs.morpho.org/learn/resources/formal-verification/#formal-verification) ---------------------------------------------------------------------------------------------------------- | Formally Proven | Scope | Date | Tool Used | | --- | --- | --- | --- | | [Morpho V1 - Pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/main/certora) | core logic | December 2024 | [Certora](https://www.certora.com/) | | [Morpho V1 - Universal rewards distributor](https://github.com/morpho-org/universal-rewards-distributor/tree/main/certora) | Merkle tree and claim function | April 2024 | [Certora](https://www.certora.com/)
& custom checker | | [Morpho V1 - Vaults V1.0](https://github.com/morpho-org/metamorpho/tree/main/certora) | core logic | March 2024 | [Certora](https://www.certora.com/) | | [Morpho V1](https://github.com/morpho-org/morpho-blue/tree/main/certora) | core logic | December 2023 | [Certora](https://www.certora.com/)
& [Halmos](https://github.com/a16z/halmos) | | [Morpho V0 (AaveV3)](https://github.com/morpho-org/morpho-aavev3-optimizer/tree/main/why3) | core logic | April 2023 | [Why3](https://www.why3.org/) | | [Morpho V0](https://github.com/morpho-org/morpho-optimizers/tree/main/certora) | Merkle tree and claim function | April 2024 | [Certora](https://www.certora.com/)
& custom checker | | [Morpho token](https://github.com/morpho-org/semitransferable-token/tree/master/certora) | authorization system | August 2022 | [Certora](https://www.certora.com/) | | [Morpho token (old)](https://github.com/morpho-org/morpho-token/tree/main/certora) | ERC20 and delegation logic | December 2024 | [Certora](https://www.certora.com/) | | [Morpho utils](https://github.com/morpho-org/morpho-utils/tree/main/certora) | math functions | December 2022 | [Certora](https://www.certora.com/) | | [Morpho data structures](https://github.com/morpho-org/morpho-data-structures/tree/main/certora) | double linked list and log buckets | January 2023 | [Certora](https://www.certora.com/)
& [Halmos](https://github.com/a16z/halmos) | --- # Morpho Docs [Skip to content](https://docs.morpho.org/get-started/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Open infrastructure On this page Chevron Right Open infrastructure ======================= for onchain loans ===================== Connect to the most trusted lending network ----------------------------------------------- ![Build](https://docs.morpho.org/img/get-started/home/group-1.svg) ### Build Create DeFi applications with Morpho Vaults and Markets using our SDKs and APIs. [→](https://docs.morpho.org/build/) ![Curate](https://docs.morpho.org/img/get-started/home/group-2.svg) ### Curate Manage vault performance by balancing stakeholder needs and optimizing liquidity allocation. [→](https://docs.morpho.org/curate/) ![Learn](https://docs.morpho.org/img/get-started/home/group-3.svg) ### Learn Understand Morpho's decentralized lending protocol concepts and ecosystem fundamentals. [→](https://docs.morpho.org/learn/) --- # Introduction – Morpho Docs [Skip to content](https://docs.morpho.org/tools/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Introduction On this page Chevron Right Many tools, part of the Morpho Stack, are available for any user, developers, researcher to build on top of the morpho protocol, and access any data. Offchain[](https://docs.morpho.org/tools/#offchain) ------------------------------------------------------ [### Morpho API\ \ ![API](https://docs.morpho.org/img/logos/api.png)\ \ Access data on Morpho users, markets, and more.\ \ More →](https://docs.morpho.org/tools/offchain/api/get-started/) [### Morpho SDKs\ \ A suite of tools to interact with the Morpho ecosystem.\ \ More →](https://docs.morpho.org/tools/offchain/sdks/get-started/) [### Morpho Subgraph\ \ ![Subgraphs](https://docs.morpho.org/img/logos/subgraph.png)\ \ Retrieve onchain data from Morpho contracts.\ \ More →](https://docs.morpho.org/tools/offchain/subgraphs/) [### Dune\ \ For public shared data and analytics\ \ More →](https://docs.morpho.org/tools/offchain/dune/) Onchain[](https://docs.morpho.org/tools/#onchain) ---------------------------------------------------- [### Public Allocator\ \ ![Public Allocator](https://docs.morpho.org/img/logos/public-allocator.png)\ \ Provide on-demand liquidity to the protocol.\ \ More →](https://docs.morpho.org/tools/onchain/public-allocator/) [### Bundlers\ \ ![Bundlers](https://docs.morpho.org/img/logos/bundlers.png)\ \ Simplify multi-step transactions for your users.\ \ More →](https://docs.morpho.org/tools/onchain/bundlers/get-started/) Discover Community Contributions[](https://docs.morpho.org/tools/#discover-community-contributions) ------------------------------------------------------------------------------------------------------ [### Oracles\ \ ![Oracles](https://docs.morpho.org/img/logos/oracles.png)\ \ Community-contributed oracle implementations and adapters.\ \ More →](https://docs.morpho.org/tools/community/oracles/) [### Liquidations\ \ Community-contributed liquidation bot implementations.\ \ More →](https://docs.morpho.org/tools/community/liquidations/) Build with Examples[](https://docs.morpho.org/tools/#build-with-examples) ---------------------------------------------------------------------------- [### Paperclip OS\ \ Complete application implementation with both earn and borrow functionality.](https://github.com/papercliplabs/compound-blue) [](https://github.com/papercliplabs/compound-blue) [Code (Earn & Borrow)|](https://github.com/papercliplabs/compound-blue) [Front End](https://www.compound.blue/) → [### Fallback App\ \ Emergency interface ensuring protocol accessibility during outages.](https://github.com/morpho-org/morpho-blue-offchain-public/tree/main/apps/fallback) [](https://github.com/morpho-org/morpho-blue-offchain-public/tree/main/apps/fallback) [Code|](https://github.com/morpho-org/morpho-blue-offchain-public/tree/main/apps/fallback) [Front End](https://fallback.morpho.org/) → [### Lite App\ \ Lightweight implementation for minimal resource usage.](https://github.com/morpho-org/morpho-lite-apps/tree/main/apps/lite) [](https://github.com/morpho-org/morpho-lite-apps/tree/main/apps/lite) [Code|](https://github.com/morpho-org/morpho-lite-apps/tree/main/apps/lite) [Front End](https://lite.morpho.org/) → [### Liquidation Bot\ \ A simple, fast, and easily deployable liquidation bot for Morpho Market V1.\ \ Code\ \ →](https://github.com/morpho-org/morpho-blue-liquidation-bot) [### Indexer Template\ \ A ready-to-use template for indexing Morpho protocol data with Ponder.\ \ Code\ \ →](https://github.com/morpho-org/ponder-template) --- # Build Earn & Borrow Products on Morpho – Morpho Docs [Skip to content](https://docs.morpho.org/build/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Build Earn & Borrow Products on Morpho On this page Chevron Right Welcome to the Morpho developer hub. Build powerful DeFi applications with our comprehensive suite of tools, SDKs, and APIs. On Morpho, you can leverage Morpho Vaults to build earn products and Morpho Markets to build borrow products. Select what you expect to integrate below: Earn - Morpho Vaults -------------------- Put your crypto to work +Simple +Optimized +Tailored +Non-custodial [Build →](https://docs.morpho.org/build/earn/get-started) [Earn on App ↗︎](https://app.morpho.org/ethereum/earn) ![Vaults](https://docs.morpho.org/img/logos/vaults.png) Borrow - Morpho Markets ----------------------- Provide collateral to borrow any asset +Low costs +Higher collateralization factors +Per market rates +Zero fees [Build →](https://docs.morpho.org/build/borrow/get-started) [Borrow on App ↗︎](https://app.morpho.org/ethereum/borrow) ![Markets](https://docs.morpho.org/img/logos/markets.png) Get Started[](https://docs.morpho.org/build/#get-started) ------------------------------------------------------------ 1. **Choose your product**: Start with [Earn](https://docs.morpho.org/build/earn/get-started) or [Borrow](https://docs.morpho.org/build/borrow/get-started) 2. **Select your tools**: Review our [development tools](https://docs.morpho.org/tools) to choose the best integration approach 3. **Follow the guides**: Use our step-by-step tutorials and reference applications 4. **Get in touch**: Get support via the chatbox on **[help.morpho.org](https://help.morpho.org/) ** and contribute on [GitHub](https://github.com/morpho-org) --- # Morpho Curation – Morpho Docs [Skip to content](https://docs.morpho.org/curate/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Morpho Curation On this page Chevron Right ![Morpho Curator Concept](https://docs.morpho.org/img/homepage/concepts/concepts_curator_light.png) Introduction to Curation[](https://docs.morpho.org/curate/#introduction-to-curation) --------------------------------------------------------------------------------------- Curators are essential in balancing stakeholder needs and maintaining vault performance. This guide highlights the core aspects of effective vault curation. Curator Responsibilities[](https://docs.morpho.org/curate/#curator-responsibilities) --------------------------------------------------------------------------------------- ### Borrower Needs[](https://docs.morpho.org/curate/#borrower-needs) * **Competitive Rates:** Access to markets offering attractive and competitive rates * **Liquidity Assurance:** Reliable liquidity during market stress to prevent rate spikes * **Capital Allocation:** Adequate capital support as positions grow * **Responsive Management:** Quick adaptations to changing market conditions ### Depositor Needs[](https://docs.morpho.org/curate/#depositor-needs) * **Risk Mitigation:** Zero tolerance for bad debt events * **Competitive Yields:** APYs that align with risk profiles * **Security & Monitoring:** Robust security measures and continuous collateral liquidity oversight * **Transparency:** Clear and ongoing risk assessments Operational Requirements[](https://docs.morpho.org/curate/#operational-requirements) --------------------------------------------------------------------------------------- ### Admin Tasks[](https://docs.morpho.org/curate/#admin-tasks) * **Role & Security Configuration:** Establish and maintain secure role assignments * **Market Listings:** Create and manage market listings effectively * **Fee & Cap Adjustments:** Update vault fee parameters and adjust allocation caps * **Public Settings:** Configure public allocation parameters ### Market Curation[](https://docs.morpho.org/curate/#market-curation) * **Liquidity Reallocation:** Automate transfers between markets to optimize capital efficiency * **Performance Monitoring:** Track vault APYs against benchmarks * **Risk Assessment:** Evaluate liquidity risks, oracle reliability, collateral fundamentals, chain-specific factors, and multisig security * **Health Tracking:** Continuously monitor borrower conditions and optionaly execute liquidation processes for at-risk positions Reward Mechanisms[](https://docs.morpho.org/curate/#reward-mechanisms) ------------------------------------------------------------------------- * **MORPHO Rewards:** Distributed to whitelisted markets and, in part, passed directly to vault depositors * **Oracle Integration:** Utilizes onchain price feeds from providers such as Chainlink, Api3, Redstone, Pendle, Hashnote, Chronicle, and Pyth * **Blockchain-Specific Deployment:** Rewards distribution varies by blockchain, with official deployments receiving priority * **Additional Configurations:** Extra market-level or vault-level rewards can be set up following the [reward programs guide](https://github.com/morpho-org/morpho-blue-reward-programs?tab=readme-ov-file#create-a-market-program) Public Allocator Integration[](https://docs.morpho.org/curate/#public-allocator-integration) ----------------------------------------------------------------------------------------------- The [Public Allocator (PA)](https://docs.morpho.org/learn/concepts/public-allocator) significantly enhances vault performance: * Enable the PA on all vaults to maximize capital efficiency while maintaining risk parameters * Set flow configurations strategically: * Open flows between markets sharing identical risk profiles * Configure idle market flows to manipulate rates while preserving borrower access * Set idle market `flow in` to zero unless bot reallocation is desired * Leverage third-party integrations like Contango and DefiSaver to drive additional volume Key Advantages for Curators[](https://docs.morpho.org/curate/#key-advantages-for-curators) --------------------------------------------------------------------------------------------- * **Optimized Capital Efficiency:** Benefit from advanced market-matching algorithms * **Granular Risk Control:** Configure precise market exposure parameters * **Non-Custodial Security:** Ensure transparent, immutable vault operations * **Dynamic Reallocation:** Maintain competitive rates with automated reallocation tools * **Flexible Customization:** Tailor vault parameters to meet diverse market needs Get Started[](https://docs.morpho.org/curate/#get-started) ------------------------------------------------------------- New curators should begin with this overview to build a solid foundation, while experienced curators may reference specific sections for targeted guidance. This concise document is designed to enhance vault performance, manage risk effectively, and optimize returns for all vault users. Refer to [this section](https://docs.morpho.org/get-started/resources/contracts) to dig into the specs of all smart contracts involved. --- # Public Allocator – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/public-allocator/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Public Allocator On this page Chevron Right ![Morpho Public Allocator Concept](https://docs.morpho.org/img/homepage/concepts/concepts_publicAllocator_light.png) What is the Public Allocator?[](https://docs.morpho.org/learn/concepts/public-allocator/#what-is-the-public-allocator) ------------------------------------------------------------------------------------------------------------------------- The Public Allocator is a smart contract that solves one of the biggest drawbacks of isolated markets: fragmented liquidity. It allows borrowers to access deep liquidity by automatically reallocating unused liquidity to the target market. Here is a video that explains how the Public Allocator works: Your browser does not support the video tag. How It Works[](https://docs.morpho.org/learn/concepts/public-allocator/#how-it-works) ---------------------------------------------------------------------------------------- When borrowing from a Morpho Market, users may find that the liquidity they need is distributed across multiple markets. Rather than requiring users to borrow from several different markets to reach their desired loan amount, the Public Allocator automatically handles this complexity. It seamlessly moves liquidity from other markets to the target market, making all funds available through a single borrowing transaction. This process happens behind the scenes and is completely transparent to the user. Benefits[](https://docs.morpho.org/learn/concepts/public-allocator/#benefits) -------------------------------------------------------------------------------- **For Borrowers:** * Access significantly more liquidity in one transaction * Borrow larger amounts without hunting for fragmented liquidity * Experience the simplicity of pool-based lending with the efficiency of Morpho **For the Ecosystem:** * Creates liquidity network effects across vaults * Reduces the need for excessive capital concentration * Maintains the security of isolated markets while offering pool-like convenience Implementation[](https://docs.morpho.org/learn/concepts/public-allocator/#implementation) -------------------------------------------------------------------------------------------- Vault curators control how the Public Allocator can move their funds by setting the Public Allocator contract with the Allocator role, and then sets: * **Flow Caps**: Maximum amounts that can flow in or out of specific markets * **Market Preferences**: Which markets can send or receive funds * **Fee Parameters**: Small fees that may apply to reallocations These controls ensure that while liquidity becomes more accessible, risk curation remains intact. By bridging isolated markets with coordinated liquidity flows, the Public Allocator combines the best of both worlds: the risk curation of separate markets with the convenience of pooled lending. --- # Morpho Bundlers – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/bundlers/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Morpho Bundlers On this page Chevron Right ![Morpho Bundlers Concept](https://docs.morpho.org/img/homepage/concepts/concepts_bundlers_light.png) What are Bundlers?[](https://docs.morpho.org/learn/concepts/bundlers/#what-are-bundlers) ------------------------------------------------------------------------------------------- Bundlers are smart contracts that allow you to combine multiple actions into a single transaction. Instead of executing several transactions in sequence—each requiring confirmation and gas fees—bundlers let you do everything at once. Bundler Implementations[](https://docs.morpho.org/learn/concepts/bundlers/#bundler-implementations) ------------------------------------------------------------------------------------------------------ There are two existing and deployed bundler types: Bundler2 and Bundler3. Bundler3 is Morpho's most advanced bundler, integrated directly into the Morpho interface. This means users will be able to perform complex operations with just one click. The specs can be found [here](https://docs.morpho.org/get-started/resources/contracts/bundlers) . What Bundler3 Allows You To Do[](https://docs.morpho.org/learn/concepts/bundlers/#what-bundler3-allows-you-to-do) -------------------------------------------------------------------------------------------------------------------- Your browser does not support the video tag. With Bundler3, you can: 1. **Streamline Complex Workflows** - Complete lending, borrowing, swapping, and more in one transaction 2. **Save on Gas Fees** - Pay for one transaction instead of many 3. **Avoid Failed Transactions** - If any part of your operation would fail, the entire transaction reverts safely 4. **Perform Advanced Operations** - Combine actions that normally require multiple steps. Practical Examples:[](https://docs.morpho.org/learn/concepts/bundlers/#practical-examples) --------------------------------------------------------------------------------------------- * **One-Click Leverage**: Convert ETH to wstETH, deposit as collateral, and borrow USDC—all in one transaction * **Instant Refinancing**: Borrow from one market, repay another, and adjust collateral positions simultaneously * **Portfolio Rebalancing**: Withdraw, swap, and redeposit assets across multiple markets without waiting for confirmations ### Bundler2[](https://docs.morpho.org/learn/concepts/bundlers/#bundler2) ![](https://docs.morpho.org/img/bundlers/blue-bundlers.svg) --- # Interest Rate Model – Morpho Docs [Skip to content](https://docs.morpho.org/learn/concepts/irm/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Learn Chevron Down Menu Interest Rate Model On this page Chevron Right ![Morpho IRM Concept](https://docs.morpho.org/img/homepage/concepts/concepts_irm_light.png) Morpho is an Interest Rate Model (IRM) agnostic protocol, meaning it can support any interest rate model for its markets. In Morpho, the interest borrowers pay in a given market is defined by the IRM chosen at market creation among a governance-approved set. The only IRM that has been governance-approved is the [AdaptiveCurveIRM](https://docs.morpho.org/learn/concepts/irm/#the-adaptivecurveirm) , which is described in more detail later in this page. Understanding Borrow and Supply APY[](https://docs.morpho.org/learn/concepts/irm/#understanding-borrow-and-supply-apy) ------------------------------------------------------------------------------------------------------------------------- The **Annualized Percentage Yield (APY)** is a critical metric that standardizes interest rates over a one-year period by accounting for compounding. In the context of lending protocols, two key APYs are: * **Borrow APY:** This reflects the effective annual interest cost that borrowers incur. It is derived from the instantaneous interest rate provided by the chosen Interest Rate Model (IRM). Essentially, the Borrow APY tells borrowers how much they will pay on an annual basis for borrowing funds. * **Supply APY:** This indicates the effective annual yield that lenders receive on their supplied assets. It is calculated by adjusting the Borrow APY based on the market's utilization rate and any applicable fees. The Supply APY, therefore, not only factors in the raw interest rate but also considers the portion of the rate that is passed on to suppliers after accounting for the market's fee (currently no fees are activated thus the fee equals). ### How Are These APYs Calculated?[](https://docs.morpho.org/learn/concepts/irm/#how-are-these-apys-calculated) #### Borrow APY Calculation[](https://docs.morpho.org/learn/concepts/irm/#borrow-apy-calculation) The Borrow APY is obtained by compounding the per-second borrow rate over the entire year. The formula is: borrowAPY\=(e(borrowRate×secondsPerYear)−1)\\text{borrowAPY} = \\left(e^{\\left(\\text{borrowRate} \\times \\text{secondsPerYear}\\right)} - 1\\right) borrowAPY\=(e(borrowRate×secondsPerYear)−1) Here, `borrowRate` is the rate provided by the IRM and `secondsPerYear` equals 31,536,000. #### Supply APY Calculation[](https://docs.morpho.org/learn/concepts/irm/#supply-apy-calculation) The Supply APY is obtained by adjusting the Borrow APY like this: supplyAPY\=borrowAPY×utilization×(1−fee)\\text{supplyAPY} = \\text{borrowAPY} \\times \\text{utilization} \\times (1 - \\text{fee}) supplyAPY\=borrowAPY×utilization×(1−fee) Where: * **Utilization:** Is the ratio of the total borrowed assets to the total supplied assets. * **Fee:** The market's fee determined by governance - currently no fees are applied. (Scaled by [WAD: 1e18](https://github.com/morpho-org/morpho-blue/blob/main/src/interfaces/IMorpho.sol#L94C36-L94C50) ) ### Resources[](https://docs.morpho.org/learn/concepts/irm/#resources) For a deeper dive into the mechanics and the code behind these calculations, refer to the following resources: * [**Interest Rate Model Repository**](https://github.com/morpho-org/morpho-blue-irm) : Explore the implementation and the smart contracts that power the IRM. * [**IRM Interface Documentation**](https://github.com/morpho-org/morpho-blue/blob/main/src/interfaces/IIrm.sol) : Review the interface definitions and understand how different IRMs integrate into the system. * [**Introducing the AdaptiveCurveIRM**](https://morpho.mirror.xyz/aaUjIF85aIi5RT6-pLhVWBzuiCpOb4BV03OYNts2BHQ) article This integrated approach ensures that both borrowers and suppliers have a clear understanding of the cost of borrowing and the returns on lending, all derived from a robust and governance-approved interest rate model. Initially, this set is composed of one immutable IRM, the AdaptiveCurveIRM. The AdaptiveCurveIRM[](https://docs.morpho.org/learn/concepts/irm/#the-adaptivecurveirm) ------------------------------------------------------------------------------------------- ### Overview[](https://docs.morpho.org/learn/concepts/irm/#overview) The AdaptiveCurveIRM is engineered to maintain the ratio of borrowed assets over supplied assets, commonly called utilization, close to a target of 90%. In Morpho, the collateral supplied is not rehypothecated. Removing this systemic risk removes the liquidity constraints imposed by liquidation needs. It enables more efficient markets with higher target utilization of capital and lower penalties for illiquidity, resulting in better rates for both lenders and borrowers. As with every parameter of a Morpho Market, the IRM address is immutable. This means that neither governance nor market creators can change it at any given time. As such, the AdaptiveCurveIRM is designed to adapt autonomously to market conditions, including changes in interest rates on other platforms and, more broadly, any shifts in supply and demand dynamics. Its adaptability enables it to perform effectively across any asset, market, and condition, making it highly suitable for Morpho's permissionless market creation. Your browser does not support the video tag. ### How It Works[](https://docs.morpho.org/learn/concepts/irm/#how-it-works) The model can be broken down into two complementary mechanisms: 1. **The Curve Mechanism** This mechanism is akin to the interest rate curve in traditional lending pools. It manages short-term utilization effectively, maintaining capital efficiency while avoiding excessively high utilization zones that could lead to liquidity issues. ![Curve Mechanism 1](https://docs.morpho.org/img/morpho-blue/curve-mechanism-01.png) r90%r\_{90\\%} r90%​ is the target rate at utilization target utarget\=0.9u\_{target}=0.9 utarget​\=0.9 2. **The Adaptive Mechanism** This mechanism fine-tunes the curve over time to keep the range of rates in sync with market dynamics. It achieves this by adjusting the value of the target rate, which in turn shifts the entire curve: * When utilization exceeds the target, the curve continuously shifts upward. This incentivizes loan repayment and thus decreases utilization. * When utilization falls below the target, the curve continuously shifts downward. This incentivizes borrowing and thus increases utilization. ![Curve Mechanism 1](https://docs.morpho.org/img/morpho-blue/curve-mechanism-02.png) The speed at which the curve adjusts is determined by the distance of current utilization to the target: the further it is, the faster the curve shifts. This incremental adjustment of the curve allows for rate exploration, ultimately stabilizing when the interest rate at the target utilization aligns with the market equilibrium. Here's a video showing how the two mechanisms combine to adjust interest rates: Your browser does not support the video tag. For more on the AdaptiveCurveIRM, explore the [technical reference](https://docs.morpho.org/get-started/resources/contracts/irm) . --- # Products – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/products/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Products On this page Chevron Right Earn & Borrow[](https://docs.morpho.org/get-started/products/#earn--borrow) ------------------------------------------------------------------------------ Build powerful financial applications with Morpho's decentralized lending infrastructure. [Earn\ ----\ \ Put your crypto to work\ \ +Simple\ \ +Optimized\ \ +Tailored\ \ +Non-custodial\ \ Build →\ \ ![Vaults](https://docs.morpho.org/img/logos/vaults.png)](https://docs.morpho.org/build/earn/get-started) [Borrow\ ------\ \ Provide collateral to borrow any asset\ \ +Low costs\ \ +Higher collateralization factors\ \ +Per market rates\ \ +Zero fees\ \ Build →\ \ ![Vaults](https://docs.morpho.org/img/logos/markets.png)](https://docs.morpho.org/build/borrow/get-started) --- # Use Cases on the Morpho Stack – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/use-cases/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Use Cases on the Morpho Stack On this page Chevron Right ### Discover who is building and trusting the Morpho Stack.[](https://docs.morpho.org/get-started/use-cases/#discover-who-is-building-and-trusting-the-morpho-stack) [](https://morpho.org/coinbase-loans/) [### Coinbase\ \ Borrow\ \ ![Coinbase 3D Icon](https://docs.morpho.org/img/get-started/use-cases/stack-coinbase.png)\ \ Coinbase leverages the Morpho Stack to offer the Bitcoin-Backed Loan product to their users.](https://morpho.org/coinbase-loans/) [](https://morpho.org/coinbase-loans/) [Coinbase article](https://www.coinbase.com/en-fr/loans) Learn more → [](https://morpho.org/earn-products/) [### Kiln\ \ Earn\ \ ![Kiln 3D Icon](https://docs.morpho.org/img/get-started/use-cases/stack-kiln.png)](https://morpho.org/earn-products/) [Kiln provides Earn Widget on top of Morpho.](https://morpho.org/earn-products/) [Safe](https://app.safe.global/earn?) , [Ledger](https://x.com/MorphoLabs/status/1917215820809470147) and [Trust Wallet](https://x.com/MorphoLabs/status/1916828252175475093) integrations are already live [Kiln documentation](https://docs.kiln.fi/v1/kiln-products/defi/morpho-via-kiln-defi) Learn more → [### Moonwell\ \ Borrow\ \ Earn\ \ ![Moonwell 3D Icon](https://docs.morpho.org/img/get-started/use-cases/stack-moonwell.png)\ \ Moonwell builds innovative lending vaults powered by the Morpho protocol infrastructure.\ \ Learn more →](https://moonwell.fi/vaults) [### Spark\ \ Earn\ \ ![Spark 3D Icon](https://docs.morpho.org/img/get-started/use-cases/stack-spark.png)\ \ Spark utilizes Morpho's infrastructure to provide efficient lending solutions for DeFi users.\ \ Learn more →](https://app.morpho.org/ethereum/vault/0x73e65DBD630f90604062f6E02fAb9138e713edD9/spark-dai-vault) [### Seamless\ \ Borrow\ \ Earn\ \ ![Seamless 3D Icon](https://docs.morpho.org/img/get-started/use-cases/stack-seamless.png)\ \ Seamless leverages Morpho's protocol to deliver seamless lending experiences for users.\ \ Learn more →](https://morpho.org/blog/seamless-2-0-powered-by-morpho/) --- # Addresses – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/addresses/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Addresses On this page Chevron Right Morpho V2 Contracts[](https://docs.morpho.org/get-started/resources/addresses/#morpho-v2-contracts) ------------------------------------------------------------------------------------------------------ EthereumArbitrumBaseBotanixHyperEVMKatanaOP MainnetPlasmaPlumePolygonPOSUnichainWorldChain | Contract | Address | Source Code | | --- | --- | --- | | VaultV2Factory | [0xA1D94F746dEfa1928926b84fB2596c06926C0405](https://etherscan.io/address/0xA1D94F746dEfa1928926b84fB2596c06926C0405#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [0xD1B8E2dee25c2b89DCD2f98448a7ce87d6F63394](https://etherscan.io/address/0xD1B8E2dee25c2b89DCD2f98448a7ce87d6F63394#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [0x3696c5eAe4a7Ffd04Ea163564571E9CD8Ed9364e](https://etherscan.io/address/0x3696c5eAe4a7Ffd04Ea163564571E9CD8Ed9364e#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | Morpho V1 Contracts[](https://docs.morpho.org/get-started/resources/addresses/#morpho-v1-contracts) ------------------------------------------------------------------------------------------------------ EthereumAbstractArbitrumBaseBitlayerBNB ChainBotanixCampCeloCornEtherlinkFlameFraxtalGnosisHemiHyperEVMInkKatanaLiskModeMonadOP MainnetPlasmaPlumePolygonPOSScrollSeiSoneiumSonicStableTACUnichainWorldChainZircuitBase SepoliaSepolia | Contract | Address | Source Code | | --- | --- | --- | | Morpho | [0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb](https://etherscan.io/address/0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC](https://etherscan.io/address/0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766](https://etherscan.io/address/0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0) | | MetaMorpho Factory V1.1 | [0x1897A8997241C1cD4bD0698647e4EB7213535c24](https://etherscan.io/address/0x1897A8997241C1cD4bD0698647e4EB7213535c24) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | MetaMorpho Factory \[OLD\] | [0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101](https://etherscan.io/address/0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101) | [metamorpho](https://github.com/morpho-org/metamorpho/tree/c5e758da97d210ede921bf228d37d31e744bd5bf) | | Public Allocator | [0xfd32fA2ca22c76dD6E550706Ad913FC6CE91c75D](https://etherscan.io/address/0xfd32fA2ca22c76dD6E550706Ad913FC6CE91c75D) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [0x6FF33615e792E35ed1026ea7cACCf42D9BF83476](https://etherscan.io/address/0x6FF33615e792E35ed1026ea7cACCf42D9BF83476) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | Bundlers[](https://docs.morpho.org/get-started/resources/addresses/#bundlers) -------------------------------------------------------------------------------- EthereumAbstractArbitrumBaseBitlayerBNB ChainBotanixCampCeloCornFlameEtherlinkFraxtalGnosisHemiHyperEVMInkKatanaLiskModeMonadOP MainnetPlasmaPlumePolygonPOSScrollSeiSoneiumSonicStableTACUnichainWorldChainZircuit | Contract | Address | Source Code | | --- | --- | --- | | Bundler3 | [0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245](https://etherscan.io/address/0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | EthereumGeneralAdapter1 | [0x4A6c312ec70E8747a587EE860a0353cd42Be0aE0](https://etherscan.io/address/0x4A6c312ec70E8747a587EE860a0353cd42Be0aE0) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ERC20WrapperAdapter | [0xf83D17dFE160597b19e4FdD8ea61A23e9a87F962](https://etherscan.io/address/0xf83D17dFE160597b19e4FdD8ea61A23e9a87F962) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ParaswapAdapter | [0x03b5259Bd204BfD4A616E5B79b0B786d90c6C38f](https://etherscan.io/address/0x03b5259Bd204BfD4A616E5B79b0B786d90c6C38f) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | AaveV3MigrationAdapter “Core” | [0xb09e40EbE31b738fbf20289270a397118707D475](https://etherscan.io/address/0xb09e40EbE31b738fbf20289270a397118707D475) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | AaveV3MigrationAdapter “Prime” | [0x2CC8d502a65824B4cF9A58DB03490bA024BDB806](https://etherscan.io/address/0x2CC8d502a65824B4cF9A58DB03490bA024BDB806) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | AaveV3MigrationAdapter “EtherFi” | [0x4011dc6581fA05F9B0c7A12AdCd676e2b1a59ca3](https://etherscan.io/address/0x4011dc6581fA05F9B0c7A12AdCd676e2b1a59ca3) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | CompoundV3MigrationAdapter | [0xdBa5bdE29eA030Bfa6A608592dFcA1D02CB26773](https://etherscan.io/address/0xdBa5bdE29eA030Bfa6A608592dFcA1D02CB26773) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | AaveV3OptimizerMigrationAdapter | [0x9e2ea2d5785598a163D569D795f286F5C55ad972](https://etherscan.io/address/0x9e2ea2d5785598a163D569D795f286F5C55ad972) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | AaveV2MigrationAdapter | [0x40288815C399709dFC0875A384B637fFe387961B](https://etherscan.io/address/0x40288815C399709dFC0875A384B637fFe387961B) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | CompoundV2MigrationAdapter | [0x9B89c07f480Df1945279031b5fC6fF241b8f1101](https://etherscan.io/address/0x9B89c07f480Df1945279031b5fC6fF241b8f1101) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | EthereumBundlerV2 | [0x4095F064B8d3c3548A3bebfd0Bbfd04750E30077](https://etherscan.io/address/0x4095F064B8d3c3548A3bebfd0Bbfd04750E30077) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/97ecc8b05b6a5ea8693668c24b946347d2847e4c) | | EthereumBundler | [0xa7995f71aa11525DB02Fc2473c37Dee5dbf55107](https://etherscan.io/address/0xa7995f71aa11525DB02Fc2473c37Dee5dbf55107) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) | | AaveV2MigrationBundler | [0xb3dCc75DB379925edFd3007511A8CE0cB4aa8e76](https://etherscan.io/address/0xb3dCc75DB379925edFd3007511A8CE0cB4aa8e76) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) | | AaveV3MigrationBundler | [0x98ccB155E86bb478d514a827d16f58c6912f9BDC](https://etherscan.io/address/0x98ccB155E86bb478d514a827d16f58c6912f9BDC) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) | | AaveV3OptimizerMigrationBundler | [0x16F38d2E764E7BeBF625a8E995b34968226D2F9c](https://etherscan.io/address/0x16F38d2E764E7BeBF625a8E995b34968226D2F9c) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) | | CompoundV2MigrationBundler | [0x26bF52a84360Ad3d01d7CDc28FC2dDC04d8c8647](https://etherscan.io/address/0x26bF52a84360Ad3d01d7CDc28FC2dDC04d8c8647) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) | | CompoundV3MigrationBundler | [0x3a0e2E9FB9c95fBc843daF166276C90B6C479558](https://etherscan.io/address/0x3a0e2E9FB9c95fBc843daF166276C90B6C479558) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) | Rewards[](https://docs.morpho.org/get-started/resources/addresses/#rewards) ------------------------------------------------------------------------------ EthereumArbitrumBaseCornFlameFraxtalHemiInkKatanaLiskModeOP MainnetPlumePolygonPOSScrollSoneiumSonicUnichainWorldChain | Contract | Address | Source Code | | --- | --- | --- | | Universal Rewards Distributor Factory | [0x9baA51245CDD28D8D74Afe8B3959b616E9ee7c8D](https://etherscan.io/address/0x9baA51245CDD28D8D74Afe8B3959b616E9ee7c8D) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Universal Rewards Distributor (used with the Market Rewards Program Registry) | [0x330eefa8a787552DC5cAd3C3cA644844B1E61Ddb](https://etherscan.io/address/0x330eefa8a787552DC5cAd3C3cA644844B1E61Ddb) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UniversalRewardsDistributor.sol) | MORPHO Token[](https://docs.morpho.org/get-started/resources/addresses/#morpho-token) ---------------------------------------------------------------------------------------- The MORPHO token has 18 decimals. EthereumBaseArbitrumKatana | Contract | Address | Source Code | | --- | --- | --- | | MORPHO | [0x58D97B57BB95320F9a05dC918Aef65434969c2B2](https://etherscan.io/address/0x58D97B57BB95320F9a05dC918Aef65434969c2B2) | [morpho-org/morpho-token](https://github.com/morpho-org/morpho-token) | | MorphoOFTAdapter | [0x50d3d6fD7518682155E3C1B65FDD50e1b35649D9](https://etherscan.io/address/0x50d3d6fD7518682155E3C1B65FDD50e1b35649D9) | [morpho-org/morpho-token-l0](https://github.com/morpho-org/morpho-token-l0) | | MORPHO wrapper | [0x9D03bb2092270648d7480049d0E58d2FcF0E5123](https://etherscan.io/address/0x9d03bb2092270648d7480049d0e58d2fcf0e5123) | [morpho-org/morpho-token](https://github.com/morpho-org/morpho-token) | | Legacy MORPHO | [0x9994E35Db50125E0DF82e4c2dde62496CE330999](https://etherscan.io/address/0x9994E35Db50125E0DF82e4c2dde62496CE330999) | [morpho-org/legacy-morpho-token](https://github.com/morpho-org/legacy-morpho-token) | Morpho V0 (Deprecated)[](https://docs.morpho.org/get-started/resources/addresses/#morpho-v0-deprecated) ---------------------------------------------------------------------------------------------------------- Ethereum only | Contract | Address | Source Code | | --- | --- | --- | | Morpho V0 (AaveV3 Optimizer - ETH emode) | [0x33333aea097c193e66081E930c33020272b33333](https://etherscan.io/address/0x33333aea097c193e66081E930c33020272b33333) | [morpho-org/morpho-aave-v3](https://github.com/morpho-org/morpho-aave-v3/tree/main) | | Morpho V0 (AaveV2 Optimizer) | [0x777777c9898D384F785Ee44Acfe945efDFf5f3E0](https://etherscan.io/address/0x777777c9898D384F785Ee44Acfe945efDFf5f3E0) | [morpho-org/morpho-optimizers](https://github.com/morpho-org/morpho-optimizers) | | Morpho V0 (AaveV2 Lens) | [0x507fa343d0a90786d86c7cd885f5c49263a91ff4](https://etherscan.io/address/0x507fA343d0A90786d86C7cd885f5C49263A91FF4) | [morpho-org/morpho-optimizers](https://github.com/morpho-org/morpho-optimizers) | | Morpho V0 (CompoundV2 Optimizer) | [0x8888882f8f843896699869179fB6E4f7e3B58888](https://etherscan.io/address/0x8888882f8f843896699869179fB6E4f7e3B58888) | [morpho-org/morpho-optimizers](https://github.com/morpho-org/morpho-optimizers) | | Morpho V0 (CompoundV2 Lens) | [0x930f1b46e1D081Ec1524efD95752bE3eCe51EF67](https://etherscan.io/address/0x930f1b46e1D081Ec1524efD95752bE3eCe51EF67) | [morpho-org/morpho-optimizers](https://github.com/morpho-org/morpho-optimizers) | | Bulker V0 (Gateway) | [0xF99e3796f94000462f736925Cf32162Fea82c168](https://etherscan.io/address/0xF99e3796f94000462f736925Cf32162Fea82c168) | [morpho-org/morpho-aave-v3](https://github.com/morpho-org/morpho-aave-v3/blob/main/src/extensions/BulkerGateway.sol) | ### Tokenized Supply Vaults[](https://docs.morpho.org/get-started/resources/addresses/#tokenized-supply-vaults) ABI are different for Morpho V0 (AaveV2) & Morpho V0 (CompoundV2) vaults, and all the vaults are deployed on the Ethereum mainnet with 18 decimals. They are fully compliant with the [ERC4626](https://eips.ethereum.org/EIPS/eip-4626) standard. Ethereum only | Contract | Address | Source Code | | --- | --- | --- | | maWBTC | [0xd508F85F1511aAeC63434E26aeB6d10bE0188dC7](https://etherscan.io/address/0xd508F85F1511aAeC63434E26aeB6d10bE0188dC7) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | maWETH | [0x490BBbc2485e99989Ba39b34802faFa58e26ABa4](https://etherscan.io/address/0x490BBbc2485e99989Ba39b34802faFa58e26ABa4) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | maDAI | [0x36F8d0D0573ae92326827C4a82Fe4CE4C244cAb6](https://etherscan.io/address/0x36F8d0D0573ae92326827C4a82Fe4CE4C244cAb6) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | maUSDC | [0xA5269A8e31B93Ff27B887B56720A25F844db0529](https://etherscan.io/address/0xA5269A8e31B93Ff27B887B56720A25F844db0529) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | maUSDT | [0xAFe7131a57E44f832cb2dE78ade38CaD644aaC2f](https://etherscan.io/address/0xAFe7131a57E44f832cb2dE78ade38CaD644aaC2f) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | maCRV | [0x9dc7094530cB1bcf5442c3b9389ee386738A190c](https://etherscan.io/address/0x9dc7094530cB1bcf5442c3b9389ee386738A190c) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | mcDAI | [0x8F88EaE3e1c01d60bccdc3DB3CBD5362Dd55d707](https://etherscan.io/address/0x8F88EaE3e1c01d60bccdc3DB3CBD5362Dd55d707) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | mcWETH | [0x676E1B7d5856f4f69e10399685e17c2299370E95](https://etherscan.io/address/0x676E1B7d5856f4f69e10399685e17c2299370E95) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | mcCOMP | [0xaA768b85eC827cCc36D882c1814bcd27ec4A8593](https://etherscan.io/address/0xaA768b85eC827cCc36D882c1814bcd27ec4A8593) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | mcUNI | [0x496da625C736a2fF122638Dc26dCf1bFdEf1778c](https://etherscan.io/address/0x496da625C736a2fF122638Dc26dCf1bFdEf1778c) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | mcUSDC | [0xba9E3b3b684719F80657af1A19DEbc3C772494a0](https://etherscan.io/address/0xba9E3b3b684719F80657af1A19DEbc3C772494a0) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | mcUSDT | [0xC2A4fBA93d4120d304c94E4fd986e0f9D213eD8A](https://etherscan.io/address/0xC2A4fBA93d4120d304c94E4fd986e0f9D213eD8A) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | mcWBTC | [0xF31AC95fe692190b9C67112d8c912bA9973944F2](https://etherscan.io/address/0xF31AC95fe692190b9C67112d8c912bA9973944F2) | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults) | | ma3WETH | [0x39Dd7790e75C6F663731f7E1FdC0f35007D3879b](https://etherscan.io/address/0x39Dd7790e75C6F663731f7E1FdC0f35007D3879b) | [morpho-aave-v3](https://github.com/morpho-org/morpho-aave-v3/blob/main/src/extensions/SupplyVault.sol) | --- # Developers Hub – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/developers/quick-start/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Developers Hub On this page Chevron Right Integrate[](https://docs.morpho.org/get-started/developers/quick-start/#integrate) ------------------------------------------------------------------------------------- [### Earn - Morpho Vaults\ \ ![Vaults](https://docs.morpho.org/img/logos/vaults.png)\ \ Add yield-generating capabilities to your application.\ \ More →](https://docs.morpho.org/build/earn/get-started) [### Borrow - Morpho Markets\ \ ![Markets](https://docs.morpho.org/img/logos/markets.png)\ \ Enable borrowing functionality in your applications.\ \ More →](https://docs.morpho.org/build/borrow/get-started) Use Tools[](https://docs.morpho.org/get-started/developers/quick-start/#use-tools) ------------------------------------------------------------------------------------- ### Offchain[](https://docs.morpho.org/get-started/developers/quick-start/#offchain) [### Morpho API\ \ ![API](https://docs.morpho.org/img/logos/api.png)\ \ Access data on Morpho users, markets, and more.\ \ More →](https://docs.morpho.org/tools/offchain/api/get-started/) [### Morpho SDKs\ \ A suite of tools to interact with the Morpho ecosystem.\ \ More →](https://docs.morpho.org/sdks/introduction/) [### Morpho Subgraph\ \ ![Subgraphs](https://docs.morpho.org/img/logos/subgraph.png)\ \ Retrieve onchain data from Morpho contracts.\ \ More →](https://docs.morpho.org/tools/offchain/subgraphs/) [### Dune\ \ For public shared data and analytics\ \ More →](https://docs.morpho.org/tools/offchain/dune/) ### Onchain[](https://docs.morpho.org/get-started/developers/quick-start/#onchain) [### Public Allocator\ \ ![Public Allocator](https://docs.morpho.org/img/logos/public-allocator.png)\ \ Provide on-demand liquidity to the protocol.\ \ More →](https://docs.morpho.org/tools/onchain/public-allocator/) [### Bundlers\ \ ![Bundlers](https://docs.morpho.org/img/logos/bundlers.png)\ \ Simplify multi-step transactions for your users.\ \ More →](https://docs.morpho.org/tools/onchain/bundlers/get-started/) Discover Community Contributions[](https://docs.morpho.org/get-started/developers/quick-start/#discover-community-contributions) ----------------------------------------------------------------------------------------------------------------------------------- [### Oracles\ \ ![Oracles](https://docs.morpho.org/img/logos/oracles.png)\ \ Community-contributed oracle implementations and adapters.\ \ More →](https://docs.morpho.org/tools/community/oracles/) [### Liquidations\ \ Community-contributed liquidation bot implementations.\ \ More →](https://docs.morpho.org/tools/community/liquidations/) Build with Examples[](https://docs.morpho.org/get-started/developers/quick-start/#build-with-examples) --------------------------------------------------------------------------------------------------------- [### Paperclip OS\ \ Complete application implementation with both earn and borrow functionality.](https://github.com/papercliplabs/compound-blue) [](https://github.com/papercliplabs/compound-blue) [Code (Earn & Borrow)|](https://github.com/papercliplabs/compound-blue) [Front End](https://www.compound.blue/) → [### Fallback App\ \ Emergency interface ensuring protocol accessibility during outages.](https://github.com/morpho-org/morpho-blue-offchain-public/tree/main/apps/fallback) [](https://github.com/morpho-org/morpho-blue-offchain-public/tree/main/apps/fallback) [Code|](https://github.com/morpho-org/morpho-blue-offchain-public/tree/main/apps/fallback) [Front End](https://fallback.morpho.org/) → [### Lite App\ \ Lightweight implementation for minimal resource usage.](https://github.com/morpho-org/morpho-lite-apps/tree/main/apps/lite) [](https://github.com/morpho-org/morpho-lite-apps/tree/main/apps/lite) [Code|](https://github.com/morpho-org/morpho-lite-apps/tree/main/apps/lite) [Front End](https://lite.morpho.org/) → [### Liquidation Bot\ \ A simple, fast, and easily deployable liquidation bot for Morpho Market V1.\ \ Code\ \ →](https://github.com/morpho-org/morpho-blue-liquidation-bot) [### Indexer Template\ \ A ready-to-use template for indexing Morpho protocol data with Ponder.\ \ Code\ \ →](https://github.com/morpho-org/ponder-template) --- # Morpho Apps – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/app-ecosystem/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Morpho Apps On this page Chevron Right This section details the critical applications developed by Morpho Association for effective vault management and ecosystem participation. Each application serves specific functions in the curation workflow. Consumer[](https://docs.morpho.org/get-started/resources/app-ecosystem/#consumer) ------------------------------------------------------------------------------------ ### Main App - [app.morpho.org](https://app.morpho.org/) [](https://docs.morpho.org/get-started/resources/app-ecosystem/#main-app--appmorphoorg) **Purpose:** Interface for both lenders interacting with Morpho vaults and Borrowers interacting with Morpho Markets. **Key Features:** * View all Morpho Markets & Morpho Vaults * Deposit, manage, and exit positions in Morpho Vaults * Enter, manage, and exit from borrow positions * Track vault performance metrics * Monitor position health and market statistics **Version: Production** ### Fallback App - [fallback.morpho.org](https://fallback.morpho.org/) [](https://docs.morpho.org/get-started/resources/app-ecosystem/#fallback-app---fallbackmorphoorg) **Purpose:** Built for emergencies, this app prioritizes resilience over speed. This interface is for both lenders interacting with Morpho vaults and Borrowers interacting with Morpho Markets. **Key Features:** * View your Morpho Markets & Morpho Vaults positions * Exit positions from Morpho Vaults and Morpho Markets **Version: Production** Prime[](https://docs.morpho.org/get-started/resources/app-ecosystem/#prime) ------------------------------------------------------------------------------ ### Curator App - [curator.morpho.org](https://curator.morpho.org/) [](https://docs.morpho.org/get-started/resources/app-ecosystem/#curator-app--curatormorphoorg) **Purpose:** Delivers specialized tools for vault curators to manage vault operations. **Key Features:** * Create and deploy new vaults * Manage market listings and parameters * Configure vault settings and permissions * Set allocation caps and strategies **Version:** Beta deployment with ongoing feature development **Implementation Note:** For actions not yet implemented in the Curator App, use direct interaction with vault contracts through verified sources such as Etherscan. Always verify contract addresses before interaction. Other[](https://docs.morpho.org/get-started/resources/app-ecosystem/#other) ------------------------------------------------------------------------------ ### Oracle Decoder - [oracles.morpho.dev](https://oracles.morpho.dev/oracle-decoder) [](https://docs.morpho.org/get-started/resources/app-ecosystem/#oracle-decoder--oraclesmorphodev) **Purpose:** Aid oracle configurations to ensure price feed accuracy and security. **Key Features:** * Decode oracle configurations * Verify price accuracy against reference sources * Test oracle configurations * Identify configuration issues **Version:** Production **Implementation Note:** Always verify oracle data configurations before deploying to production environments. Use this tool to: 1. Confirm correct asset pricing 2. Validate operational parameters 3. Test edge case scenarios ### Liquidation App - [liquidation.morpho.org](https://liquidation.morpho.org/) [](https://docs.morpho.org/get-started/resources/app-ecosystem/#liquidation-app--liquidationmorphoorg) **Purpose:** Provides manual liquidation capabilities for unhealthy positions. **Key Features:** * Identify liquidatable positions * Execute manual liquidations * Calculate liquidation profitability * Monitor position health metrics **Version:** Production and requires supplemental automation **Implementation Note:** Develop and deploy automated liquidation bots for production environments. The liquidation app serves primarily as a backup mechanism when bots fail or for testing purposes. External[](https://docs.morpho.org/get-started/resources/app-ecosystem/#external) ------------------------------------------------------------------------------------ This section details the applications developed by third parties allowing to interact with rewards, or with Morpho contracts on networks where the Morpho main app is not deployed. This external applications are provided by third parties. The Morpho Association does not endorse or guarantee its functionality. Use at your own discretion. ### Rewards[](https://docs.morpho.org/get-started/resources/app-ecosystem/#rewards) * [Merkl](https://app.merkl.xyz/?protocol=morpho&tokenType=all&sort=tvl-desc) ### Corn[](https://docs.morpho.org/get-started/resources/app-ecosystem/#corn) * [Oku app by GFX](https://oku.trade/morpho/vaults?chainFilter=21000000) ### HyperEVM[](https://docs.morpho.org/get-started/resources/app-ecosystem/#hyperevm) * [Felix](https://usefelix.xyz/earn) * [HyperBeat](https://app.hyperbeat.org/earn) ### OP Mainnet[](https://docs.morpho.org/get-started/resources/app-ecosystem/#op-mainnet) * [Moonwell](https://moonwell.fi/vaults) ### World Chain[](https://docs.morpho.org/get-started/resources/app-ecosystem/#world-chain) * [World Mini App by Paperclip](https://world.org/blog/announcements/morpho-mini-app-for-world-app) * [Oku app by GFX](https://oku.trade/morpho/vaults?chainFilter=480) --- # Morpho Contracts – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Morpho Contracts On this page Chevron Right | **Category** | **Contract** | **Github Repositories** | **Specs** | | --- | --- | --- | --- | | **Morpho Core** | Morpho Market V1 | [morpho-blue](https://github.com/morpho-org/morpho-blue) | [spec](https://docs.morpho.org/get-started/resources/contracts/morpho) | | | Interest Rate Model | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm) | [spec](https://docs.morpho.org/get-started/resources/contracts/irm) | | | Oracle | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles) | [spec](https://docs.morpho.org/get-started/resources/contracts/oracles) | | | Pre-Liquidation | [pre-liquidation](https://github.com/morpho-org/pre-liquidation) | [spec](https://docs.morpho.org/get-started/resources/contracts/morpho#liquidation) | | **Morpho Vaults V1** | Vaults V1.1 | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1) | [spec](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults) | | | Vaults V1.0 | [metamorpho](https://github.com/morpho-org/metamorpho) | [spec](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults) | | **Morpho Vaults V2** | Vaults V2 | [vault-v2](https://github.com/morpho-org/vault-v2) | [spec](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2) | | **Public Allocator** | Public-Allocator | [public-allocator](https://github.com/morpho-org/public-allocator) | [spec](https://docs.morpho.org/get-started/resources/contracts/public-allocator) | | **Bundlers** | Bundler3 | [bundler3](https://github.com/morpho-org/bundler3) | [spec](https://docs.morpho.org/get-started/resources/contracts/bundlers) | | | Bundler2 | [morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers) | [spec](https://docs.morpho.org/get-started/resources/contracts/bundlers) | | **Rewards** | Universal-Rewards-Distributor | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor) | [spec](https://docs.morpho.org/get-started/resources/contracts/rewards) | --- # Morpho Docs [Skip to content](https://docs.morpho.org/tools/community/oracles#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu On this page Chevron Right ← Back to [Oracle Concept Section](https://docs.morpho.org/learn/concepts/oracle) Oracle Community section[](https://docs.morpho.org/tools/community/oracles#oracle-community-section) ------------------------------------------------------------------------------------------------------- ### Disclaimer[](https://docs.morpho.org/tools/community/oracles#disclaimer) ### Origami[](https://docs.morpho.org/tools/community/oracles#origami) **By:** [TempleDAO](https://github.com/TempleDAO) **Languages and Tools:** Solidity **Description:** Origami Oracle Adapters are Chainlink-interface-compliant feeds to provide price data. These can be used within Origami Finance, Morpho Oracles. **Repository:** [origami-oracle-adapters](https://github.com/TempleDAO/origami-oracle-adapters) ### LlamaRisk[](https://docs.morpho.org/tools/community/oracles#llamarisk) **By:** [LlamaRisk](https://github.com/llama-risk) **Languages and Tools:** Solidity **Description:** More information here: [https://www.llamarisk.com/research/morpho-crvusd-vault](https://www.llamarisk.com/research/morpho-crvusd-vault) . **Repository:** [llama-risk/tri-pool-lp-crvusd-oracle](https://github.com/llama-risk/tri-pool-lp-crvusd-oracle) ### Oval[](https://docs.morpho.org/tools/community/oracles#oval) **By:** [Oval](https://github.com/UMAprotocol) **Languages and Tools:** Solidity **Description:** Oval is an OEV recapture tool. Oval oracle adapters wrap oracle price feeds and output Chainlink-interface-compliant prices. Oval can easily be deployed via factory contract for Morpho markets following this tutorial: [https://docs.oval.xyz/integration/morpho-deployment](https://docs.oval.xyz/integration/morpho-deployment) **Repository:** [UMAprotocol/oval-contracts](https://github.com/UMAprotocol/oval-contracts) ### Pendle[](https://docs.morpho.org/tools/community/oracles#pendle) **By:** [Horace](https://github.com/horacepan) **Languages and Tools:** Solidity **Description:** This project provides two key components for Pendle Principal Token (PT) price feeds: 1. A PT Oracle Price Adapter that wraps Pendle's PT oracle to make it compatible with Chainlink's AggregatorV3 interface, which is required by Morpho oracles 2. A factory contract for easy deployment of both the PT Oracle Price Adapter and Pendle's SparkLinearDiscountOracle These oracle instances can be used as base or quote feeds with the MorphoChainlinkOracleV2Factory. **Repository:** [horacepan/pendle-adapter-factory](https://github.com/horacepan/morpho-blue-oracles/tree/pendle-adapter-factory) ### f(x)[](https://docs.morpho.org/tools/community/oracles#fx) **By:** [chiaki644](https://github.com/chiaki644) **Languages and Tools:** Solidity **Description:** This adapter supports all f(x) protocol tokens, including fxUSD, rUSD, btcUSD, fETH, xETH, xstETH, xfrxETH, xezETH, xeETH, xWBTC. The token addresses can be found in the [f(x) protocol deployments](https://github.com/AladdinDAO/deployments/blob/main/deployments.mainnet.md) . **Repository:** [AladdinDAO/fxusd-adapter](https://github.com/AladdinDAO/morpho-blue-oracles/tree/feat/fxusd-adapter) ### sfrxETH-frxETH Exchange Rate[](https://docs.morpho.org/tools/community/oracles#sfrxeth-frxeth-exchange-rate) **By:** [Horace](https://github.com/horacepan) **Languages and Tools:** Solidity **Description:** A Chainlink-interface-compliant oracle adapter for the sfrxETH-frxETH exchange rate. This adapter follows the same pattern as the wstETH-stETH exchange rate adapter, but calculates the exchange rate using the `pricePerShare` function instead of `getPooledEthByShares`. **Repository:** [horacepan/sfrxeth-exchange-rate-adapter](https://github.com/horacepan/morpho-blue-oracles/tree/sfrxeth-exchange-rate-adapter) ### Other Exchange Rates[](https://docs.morpho.org/tools/community/oracles#other-exchange-rates) **By:** [frontier159](https://github.com/frontier159) **Languages and Tools:** Solidity **Description:** A collection of Chainlink-interface-compliant oracle adapters for various Liquid Staking Token (LST) and Liquid Restaking Token (LRT) exchange rates against ETH. Supports ezETH (Renzo), rsETH (Kelp), swETH (Swell LST), rswETH (Swell LRT), and weETH (ether.fi). **Repository:** [frontier159/lrt-oracles](https://github.com/frontier159/morpho-blue-oracles/tree/lrt-oracles) ### Pyth[](https://docs.morpho.org/tools/community/oracles#pyth) **By:** [aditya520](https://github.com/aditya520) **Languages and Tools:** Solidity **Description:** MorphoPythOracle is a Morpho V1 oracle implementation that uses Pyth Price Feeds. Created by Pyth Data Association, it facilitate price data from Pyth Network for Morpho Market's dedicated oracles. **Repository:** [pyth-network/pyth-morpho-wrapper](https://github.com/pyth-network/pyth-morpho-wrapper) ### Ojo[](https://docs.morpho.org/tools/community/oracles#ojo) **By:** [Ojo](https://github.com/ojo-network) **Languages and Tools:** Solidity **Description:** Yield risk engine is designed to put a static cap on how much a yield asset can appreciate over time. It's designed to reduce risk exposure to inflation attacks where users are able to donate to an ERC-4626 vault and artificially increase the value of a vault token in order to borrow more against it. **Repository:** [ojo-network/yield-risk-engine](https://github.com/ojo-network/yield-risk-engine) --- # Deploy an Oracle for Morpho Markets – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Deploy an Oracle for Morpho Markets On this page Chevron Right Oracle deployment is a critical step when creating lending markets in Morpho, as these smart contracts provide essential price information that powers core functionalities like collateral evaluation and liquidation triggers. This guide will walk you through the entire process of configuring, testing, and deploying an oracle using the Morpho ecosystem tools. Understanding Oracles in Morpho[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#understanding-oracles-in-morpho) ------------------------------------------------------------------------------------------------------------------------------------------ Before jumping into deployment, let's review what oracles do in the Morpho ecosystem: * **Purpose**: Oracles provide price data that determines what one token is worth relative to another * **Implementation**: Morpho takes an oracle-agnostic approach, allowing market creators to choose appropriate price feed mechanisms * **Interface**: All oracles implement the `IOracle` interface with a single standardized function: `price()` * **Immutability**: Once a market is deployed, its oracle address cannot be modified, making correct setup crucial The Oracle Deployment Process[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#the-oracle-deployment-process) -------------------------------------------------------------------------------------------------------------------------------------- This guide covers the complete process of deploying a new oracle using: 1. **MorphoChainlinkOracleV2Factory**: The contract used to create new oracles 2. **Oracle Tester Tool**: A web interface to validate your configuration and prepare deployment 3. **Oracle Decoder**: A tool to run additional checks on your configuration post-deployment Step 1: Understanding the Oracle Parameters[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#step-1-understanding-the-oracle-parameters) ----------------------------------------------------------------------------------------------------------------------------------------------------------------- The `MorphoChainlinkOracleV2Factory` requires several parameters that determine how the oracle will calculate prices. Let's break them down: ### Key Parameters[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#key-parameters) | Parameter | Description | | --- | --- | | `baseVault` | ERC4626 vault for the collateral token (zero address if not applicable) | | `baseVaultConversionSample` | Amount of base vault shares for conversion calculation (use 1 if no vault) | | `baseFeed1` | First price feed for the collateral token (zero address if not needed) | | `baseFeed2` | Second price feed for the collateral token (zero address if not needed) | | `baseTokenDecimals` | Decimal precision of the base/collateral token | | `quoteVault` | ERC4626 vault for the loan token (zero address if not applicable) | | `quoteVaultConversionSample` | Amount of quote vault shares for conversion calculation (use 1 if no vault) | | `quoteFeed1` | First price feed for the loan token (zero address if not needed) | | `quoteFeed2` | Second price feed for the loan token (zero address if not needed) | | `quoteTokenDecimals` | Decimal precision of the quote/loan token | | `salt` | Unique identifier for deterministic address creation (typically "0x") | ### Common Oracle Configurations[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#common-oracle-configurations) Different asset pairs require different oracle configurations. Here are some common patterns: 1. **Standard tokens (ETH/USDC)**: Direct price feed with no vaults 2. **Wrapped tokens (wstETH/ETH)**: Requires special exchange rate adapter 3. **Yield-bearing tokens (sDAI/USDC)**: Requires vault configuration (sDAI -> DAI -> USD -> USDC or sDAI -> DAI -> USDC) Step 2: Using the Oracle Tester Tool[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#step-2-using-the-oracle-tester-tool) --------------------------------------------------------------------------------------------------------------------------------------------------- The Oracle Tester tool helps you validate your configuration before deployment, saving gas and preventing errors. Here's how to use it: ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-empty-v2.png) ### Accessing the Oracle Tester[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#accessing-the-oracle-tester) #### Navigate[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#navigate) Jump on the Morpho Oracle Interface at [oracles.morpho.dev](https://oracles.morpho.dev/oracle-tester) #### Tester section[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#tester-section) Verify you are on the "Tester" tab in the navigation menu #### Form section[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#form-section) You'll see a form for configuring and testing your oracle ### Basic Steps[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#basic-steps) #### Select Network[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#select-network) Choose the blockchain where you'll deploy your oracle. All blockchains where Morpho contracts were deployed are supported. Verify the addresses [here](https://docs.morpho.org/get-started/resources/addresses#morpho-contracts) . #### Select Assets[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#select-assets) * Choose the **Collateral Asset** (the token that will be used as collateral) * Choose the **Loan Asset** (the token that will be borrowed) * If your token isn't listed, click "Add New Asset" to add custom token information ### Advanced Configuration[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#advanced-configuration) After selecting your assets, you'll need to fill in the detailed oracle parameters: #### Base (Collateral) Configuration[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#base-collateral-configuration) * **Base Vault**: If your collateral is an ERC4626 token, enter the vault address. Otherwise, use the default zero address (`0x0000000000000000000000000000000000000000`). * **Base Vault Conv. Sample**: Default is 1 if using zero address for Base Vault. For ERC4626 tokens, use a value like `1000000000000000000` (1e18) to ensure precision. This value is used to query the `convertToAsset` function on the Base Vault address you put thus needs enough precision. Click here to read more about vault conversion sample ##### Understanding Vault Conversion Samples[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#understanding-vault-conversion-samples) For ERC4626 tokens like sDAI, the Vault Conversion Sample is critical for accurate pricing: 1. **What it does**: The conversion sample represents the amount of vault shares (e.g., sDAI) that will be passed to the vault's `convertToAssets` function to determine the equivalent amount of underlying tokens (e.g., DAI). 2. **Why it matters**: The `convertToAssets` function returns how much of the underlying asset (e.g., DAI) you would receive if you redeemed a given amount of vault shares (e.g., sDAI). 3. **Choosing a value**: * For non-vault tokens: Use `1` * For ERC4626 tokens: Use a value with sufficient precision, typically `1000000000000000000` (1e18) 4. **Example with sDAI**: * When we set `baseVault` to the sDAI vault address (0x83F20F44975D03b1b09e64809B757c47f942BEeA) * And `baseVaultConversionSample` to 1e18 (1 full share) * The oracle internally calls `convertToAssets(1e18)` on the sDAI vault * This returns the current amount of DAI that 1e18 sDAI shares are worth * This exchange rate is then used in the price calculation alongside the DAI/USD price feed 5. **Formula visualization**: For a sDAI/USDC oracle, the pricing path is: Copy `sDAI → DAI (via vault conversion) → USD (via DAI/USD feed) → USDC (via USDC/USD feed)` The vault conversion is the first step in establishing the price routing path for ERC4626 tokens, allowing accurate relative valuation between yield-bearing tokens and their non-yield-bearing counterparts. * **Base Feed 1**: The primary price feed for your collateral asset. This could be a Chainlink, Redstone, Pyth, or Chronicle, ... * **Base Feed 2**: If needed, a secondary price feed for route calculation. Often the zero address. * **Base Token Decimals**: The decimal precision of your collateral token. In most of the case, it should match the actual collateral token decimals. If a Base Vault is put, use the underlying asset decimals. (Eg: if `sDAI` is put in Base Vault, use `DAI` decimals) #### Quote (Loan) Configuration[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#quote-loan-configuration) * **Quote Vault**: If your loan token is an ERC4626 token, enter the vault address. Otherwise, use the zero address. * **Quote Vault Conv. Sample**: Similar to Base Vault Conversion Sample, default is 1. * **Quote Feed 1**: Primary price feed for the loan asset. * **Quote Feed 2**: Secondary price feed if needed. * **Quote Token Decimals**: The decimal precision of your loan token. #### Salt Configuration[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#salt-configuration) * **Salt**: This is typically set to `0x` for initial deployments. It's used to create deterministic addresses. This means that changing the salt, with the very same config, will create a different oracle address. #### Scale Factor[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#scale-factor) ### Running Tests[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#running-tests) After configuring all parameters, click the "Check" button to run a series of tests: 1. **Decimals Check**: Verifies that the token decimals match what's expected 2. **ERC4626 Check**: Confirms if the loan asset is an ERC4626 token 3. **Deployment Check**: Checks if an oracle with these parameters already exists \[_Only on Ethereum and Base_\] 4. ~**Feeds Check**: Feel free to ignore this one~ \[_Deprecated_\] 5. **Price Check**: Compares the calculated oracle price with expected market prices from a USD comparison price Each check will show a status indicator: * ✅ **Green** = Passed * ⚠️ **Yellow** = Warning or needs attention * ❌ **Red** = Failed check ### Generating Deployment Payload[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#generating-deployment-payload) If all checks pass, click the "Generate Payload" button to create the transaction data you'll need for deployment. You can: 1. View the payload details directly in the interface 2. Download the payload as a JSON file 3. Open a Safe transaction to deploy using the "Open Safe" button (for multisig deployments) Step 3: Deploying the Oracle[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#step-3-deploying-the-oracle) ----------------------------------------------------------------------------------------------------------------------------------- Once you've validated your configuration, you have two options for deployment: ### Option A: Deploying via Etherscan[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#option-a-deploying-via-etherscan) #### Find the Factory Contract[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#find-the-factory-contract) * Navigate to the MorphoChainlinkOracleV2Factory address on Etherscan: * Ethereum: [0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766](https://etherscan.io/address/0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766#writeContract) * Base: Check the [Morpho documentation](https://docs.morpho.org/get-started/resources/addresses) for the latest address #### Connect Your Wallet[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#connect-your-wallet) * Click "Connect to Web3" on Etherscan * Connect your wallet (MetaMask, WalletConnect, etc.) #### Fill in the Parameters[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#fill-in-the-parameters) * Navigate to the `createMorphoChainlinkOracleV2` function * Input all the parameters you validated with the Oracle Tester * Double-check all values against your test results #### Write Contract[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#write-contract) * Click "Write" to send the transaction * Confirm the transaction in your wallet * Wait for the transaction to be confirmed #### Verify Deployment[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#verify-deployment) * Check for the `CreateMorphoChainlinkOracleV2` event in the transaction logs * Note the deployed oracle address for future reference ### Option B: Deploying via Safe (Multisig)[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#option-b-deploying-via-safe-multisig) #### Prepare the Safe Transaction[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#prepare-the-safe-transaction) * Click "Open Safe" in the Oracle Tester after generating the payload * This will open the Safe interface with the transaction data pre-filled #### Review and Submit\*\*:[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#review-and-submit) * Review all parameters in the Safe interface * Submit the transaction for signing by your multisig participants * Execute the transaction once you have the required signatures Step 4: Final Validation[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#step-4-final-validation) --------------------------------------------------------------------------------------------------------------------------- After deployment, it's crucial to validate that your oracle is working correctly: #### Use the Oracle Decoder Tool[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#use-the-oracle-decoder-tool) * Navigate to [oracles.morpho.dev/oracle-decoder](https://oracles.morpho.dev/oracle-decoder) * Enter your oracle address * Verify that it returns the expected price for your asset pair #### Check the Oracle Price[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#check-the-oracle-price) * Call the `price()` function on your deployed oracle * Verify that the returned price is within expected ranges Example Configurations[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#example-configurations) ------------------------------------------------------------------------------------------------------------------------ Here are detailed examples for common token pairs: ### A. cbBTC/USDC Oracle[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#a-cbbtcusdc-oracle) Copy `baseVault: "0x0000000000000000000000000000000000000000", // No Base Vault baseVaultConversionSample: 1, // Default to 1 as no Base Vault baseFeed1: "0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c", // BTC/USD Feed baseFeed2: "0x0000000000000000000000000000000000000000", // - Default to Zero Address baseTokenDecimals: 8, // BTC Decimals quoteVault: "0x0000000000000000000000000000000000000000", // No Quote Vault quoteVaultConversionSample: 1, // Default to 1 as no Quote Vault quoteFeed1: "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6", // USDC/USD Feed quoteFeed2: "0x0000000000000000000000000000000000000000", // - quoteTokenDecimals: 6, // USDC Decimals salt: "0x0000000000000000000000000000000000000000000000000000000000000000", // one can put any bytes 32 different than a deployed oracle with the very same configuration` ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-cbbtc-usdc-v2-1.png) ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-cbbtc-usdc-v2-2.png) **Explanation**: * This configuration uses a direct BTC/USD [price feed](https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&search=0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c) for calculating the cbBTC/USD feed price. * It also uses a USDC/USD [quote feed](https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&search=0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6) for calculating the USDC/USD feed price. As USDC/USD is used in the quote section, the final route is: cbBTC -> USD -> USDC. ### B. DAI/USDC Oracle - USDC Hardcoded[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#b-daiusdc-oracle---usdc-hardcoded) The particularity in this example is that removing the `QuoteFeed1` as it was in previous example acts as if someone was hardcoding the USDC price to 1 in the oracle of the market, because the virtual path is: Copy `baseVault: "0x0000000000000000000000000000000000000000", // - baseVaultConversionSample: 1, // - default baseFeed1: "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9", // DAI/USD Feed baseFeed2: "0x0000000000000000000000000000000000000000", // - baseTokenDecimals: 18, // DAI Decimals (NOT sDAI decimals) quoteVault: "0x0000000000000000000000000000000000000000", // - quoteVaultConversionSample: 1, // - quoteFeed1: "0x0000000000000000000000000000000000000000", // EMPTY Feed quoteFeed2: "0x0000000000000000000000000000000000000000", // - quoteTokenDecimals: 6, // USDC Decimals salt: "0x0000000000000000000000000000000000000000000000000000000000000000",` ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-dai-usdc-hardcoded-v2-1.png) ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-dai-usdc-hardcoded-v2-2.png) **Explanation**: This configuration is using the chainlink price feed for the DAI -> USD part, and is not pricing USDC -> USD on purpose to showcase the USDC `hardcoding` method. ### C. sDAI/USDC Oracle[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#c-sdaiusdc-oracle) Copy `baseVault: "0x83F20F44975D03b1b09e64809B757c47f942BEeA", // sDAI Vault baseVaultConversionSample: 1000000000000000000, // 1e18 baseFeed1: "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9", // DAI/USD Feed baseFeed2: "0x0000000000000000000000000000000000000000", // - baseTokenDecimals: 18, // DAI Decimals (NOT sDAI decimals) quoteVault: "0x0000000000000000000000000000000000000000", // - quoteVaultConversionSample: 1, // - quoteFeed1: "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6", // USDC/USD Feed quoteFeed2: "0x0000000000000000000000000000000000000000", // - quoteTokenDecimals: 6, // USDC Decimals salt: "0x0000000000000000000000000000000000000000000000000000000000000000",` ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-sdai-usdc-v2-1.png) ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-sdai-usdc-v2-2.png) **Explanation**: This configuration handles a yield-bearing token (sDAI) by specifying its vault address and using a higher conversion sample to account for the share-to-asset conversion. The price feeds are standard Chainlink feeds for the underlying assets. ### D. sDAI/USDC Oracle - USDC Hardcoded[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#d-sdaiusdc-oracle---usdc-hardcoded) Copy `baseVault: "0x83F20F44975D03b1b09e64809B757c47f942BEeA", // sDAI Vault baseVaultConversionSample: 10000000000, // 1e10 - Explanation below baseFeed1: "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9", // DAI/USD Feed baseFeed2: "0x0000000000000000000000000000000000000000", // - baseTokenDecimals: 18, // DAI Decimals (NOT sDAI decimals) quoteVault: "0x0000000000000000000000000000000000000000", // - quoteVaultConversionSample: 1, // - quoteFeed1: "0x0000000000000000000000000000000000000000", // USDC/USD Feed quoteFeed2: "0x0000000000000000000000000000000000000000", // - quoteTokenDecimals: 6, // USDC Decimals salt: "0x0000000000000000000000000000000000000000000000000000000000000000",` ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-sdai-usdc-hardcoded-v2-1.png) ![Oracle Tester Interface](https://docs.morpho.org/img/curators/tutorials/oracle-tester-sdai-usdc-hardcoded-v2-2.png) * **Explanation**: This configuration handles a yield-bearing token (sDAI) by specifying its vault address and using a high conversion sample (1e10) to account for the share-to-asset conversion. The price feed used in Base Feed 1 is a standard Chainlink feed. Why `baseVaultConversionSample` is 1e10 this time? Sometimes a vault conversion sample that is too high will result in a scale factor of 0 (or even cause a revert at deployment). A solution is to find a tradeoff by reducing the vault conversion sample value (base or quote) while keeping it high enough to maintain precision. ### E. wstETH/ETH Oracle[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#e-wstetheth-oracle) Copy `baseVault: "0x0000000000000000000000000000000000000000", baseVaultConversionSample: 1, baseFeed1: "0x905b7dAbCD3Ce6B792D874e303D336424Cdb1421", // wstETH/stETH adapter baseFeed2: "0x86392dC19c0b719886221c78AB11eb8Cf5c52812", // stETH/ETH price feed baseTokenDecimals: 18, quoteVault: "0x0000000000000000000000000000000000000000", quoteVaultConversionSample: 1, quoteFeed1: "0x0000000000000000000000000000000000000000", quoteFeed2: "0x0000000000000000000000000000000000000000", quoteTokenDecimals: 18, salt: "0x",` **Explanation**: This configuration uses multiple feeds to establish a price path from wstETH to ETH. It requires a special adapter contract (`WstEthStEthExchangeRateChainlinkAdapter`) that handles the wstETH to stETH conversion, followed by a standard feed for stETH to ETH. Troubleshooting Common Issues[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#troubleshooting-common-issues) -------------------------------------------------------------------------------------------------------------------------------------- ### Oracle Deployment Errors[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#oracle-deployment-errors) | Issue | Solution | | --- | --- | | "Transaction reverted" | Double-check all addresses and ensure they are valid contract addresses | | "Gas estimation failed" | Your configuration may be invalid or the contract cannot be executed properly | | "Oracle with same parameters already deployed" | Use the existing oracle (check the deployment check results) | ### Price Verification Issues[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#price-verification-issues) | Issue | Solution | | --- | --- | | Price significantly deviates from expected | Check that your feeds are correctly configured and that the decimals are accurate | | Price is zero | Ensure that all required feeds are working and that conversion samples are appropriate | | Price overflow/underflow | Adjust conversion samples to ensure mathematical operations don't exceed limits | Best Practices for Oracle Deployment[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#best-practices-for-oracle-deployment) ---------------------------------------------------------------------------------------------------------------------------------------------------- 1. **Always test before deploying** - Use the Oracle Tester tool to validate your configuration. 2. **Understand token decimals** - Incorrect decimal configuration is a common source of errors. 3. **Use reliable price feeds** - Choose established providers like Chainlink, Redstone, Chronicle, API3, Pyth ... 4. **Check for existing oracles** - Reuse existing oracles when possible to save gas and ensure consistency. 5. **Document your configuration** - Keep a record of all parameters for future reference. 6. **Verify after deployment** - Always check that the deployed oracle returns expected prices. Security Considerations[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#security-considerations) -------------------------------------------------------------------------------------------------------------------------- Since oracles are immutable once deployed and attached to a market, their security is paramount: 1. **Verify the source code** of any adapter contracts you're using 2. **Understand the price path** and how multiple feeds work together 3. **Consider failure modes** in your price feeds and how they could affect the oracle 4. **Test with extreme market conditions** to ensure robustness Community Contributions[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#community-contributions) -------------------------------------------------------------------------------------------------------------------------- Getting Help[](https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/#getting-help) ---------------------------------------------------------------------------------------------------- If you encounter issues during the oracle deployment process: 1. Get in touch via the chatbox on **[help.morpho.org](https://help.morpho.org/) ** 2. For complex setups, consider reaching out to the Morpho Association or to a curator directly By following this guide, you should be able to configure, test, and deploy oracles for your Morpho markets with confidence. Remember that careful setup is essential as oracles play a critical role in market safety and cannot be changed after market deployment. --- # Morpho Docs [Skip to content](https://docs.morpho.org/tools/community/liquidations#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu On this page Chevron Right ← Back to [Liquidation Concept Section](https://docs.morpho.org/learn/concepts/liquidation) Liquidation Community section[](https://docs.morpho.org/tools/community/liquidations#liquidation-community-section) ---------------------------------------------------------------------------------------------------------------------- ### Disclaimer[](https://docs.morpho.org/tools/community/liquidations#disclaimer) ### Liquidation Bot 1[](https://docs.morpho.org/tools/community/liquidations#liquidation-bot-1) **By:** [morpho-labs](https://github.com/morpho-labs/) **Languages and Tools:** Typescript & Solidity **Description:** A simple, fast, and easily deployable liquidation bot for the Morpho protocol. This bot is entirely based on RPC calls and is designed to be easy to configure, customizable, and ready to deploy on any EVM-compatible chain. **Repository:** [Morpho-liquidation-bot](https://github.com/morpho-org/morpho-blue-liquidation-bot) ### Liquidation Bot 2[](https://docs.morpho.org/tools/community/liquidations#liquidation-bot-2) **By:** [morpho-labs](https://github.com/morpho-labs/) **Languages and Tools:** Typescript & Solidity **Description:** This contribution presents a simple implementation of a liquidation bot that can liquidate unhealthy position on Morpho. Using Typescript and Solidity. **Repository:** [Morpho-liquidation-bot-educational](https://github.com/morpho-org/morpho-liquidation-bot-educational) ### Liquidation Bot 3[](https://docs.morpho.org/tools/community/liquidations#liquidation-bot-3) **By:** [etherhood](https://github.com/etherhood/) **Languages and Tools:** Rust & Solidity **Description:** This contribution presents a detailed strategy for liquidations using Rust and Solidity. **Repository:** [Liquidator-Morpho](https://github.com/etherhood/Liquidator-Morpho) ### Liquidation Bot 4[](https://docs.morpho.org/tools/community/liquidations#liquidation-bot-4) **By:** [zach030](https://github.com/zach030/) **Languages and Tools:** Go & Solidity **Description:** This contribution presents a detailed strategy for liquidations using Go and Solidity. **Repository:** [morpho-liquidator-bot](https://github.com/zach030/morpho-liquidator-bot) --- # Integrating Morpho Rewards – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/get-started#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Get Started On this page Chevron Right Morpho's rewards system allows protocols, DAOs, and token issuers to incentivize specific behaviors on the Morpho protocol—such as supplying assets to vaults or borrowing from markets. As an integrator, your role is to help users discover, track, and claim these rewards through your application. Understanding the Rewards Ecosystem[](https://docs.morpho.org/build/rewards/get-started#understanding-the-rewards-ecosystem) ------------------------------------------------------------------------------------------------------------------------------- Rewards on Morpho are distributed through **two primary systems**: 1. **Merkl** (Primary - Current Standard) 2. **Morpho URD** (Legacy - Historical Programs) Merkl: The Current Standard[](https://docs.morpho.org/build/rewards/get-started#merkl-the-current-standard) -------------------------------------------------------------------------------------------------------------- [Merkl](https://merkl.xyz/) is a third-party rewards distribution platform that now handles Morpho ecosystem rewards. It offers: * **Flexible distribution**: Rewards updated every 8 hours * **Multi-protocol support**: Used across DeFi, not just Morpho * **Automated calculations**: Offchain computation of eligible rewards * **Standardized claiming**: Consistent API and claiming process **When to use Merkl:** * All new reward programs (July 2025 onwards) * Third-party incentive programs * Current MORPHO token distributions Morpho URD: Legacy Support[](https://docs.morpho.org/build/rewards/get-started#morpho-urd-legacy-support) ------------------------------------------------------------------------------------------------------------ The Universal Rewards Distributor (URD) was Morpho's native rewards system. While new programs use Merkl, the URD still holds claimable rewards from historical programs. **When to support URD:** * Legacy MORPHO distributions (pre-July 2025) * Historical vault and market rewards distributions * Unclaimed rewards from completed campaigns Who Should Integrate Rewards?[](https://docs.morpho.org/build/rewards/get-started#who-should-integrate-rewards) ------------------------------------------------------------------------------------------------------------------ You should integrate rewards if you're building: * **Earn Products**: Display additional APR from rewards alongside base vault yield * **Borrow Products**: Show borrowers incentives for taking loans * **Portfolio Dashboards**: Provide users with a complete view of their Morpho earnings * **Aggregators**: Compare total yields (base + rewards) across protocols * **Reward Platforms**: Create specialized UIs for rewards discovery and claiming What You'll Need to Integrate[](https://docs.morpho.org/build/rewards/get-started#what-youll-need-to-integrate) ------------------------------------------------------------------------------------------------------------------ A complete rewards integration involves three main components: ### 1\. Rewards Discovery & Display[](https://docs.morpho.org/build/rewards/get-started#1-rewards-discovery--display) Fetch and display available rewards for vaults and markets: * Query reward rates from Merkl API or Morpho API * Calculate total APY (base yield + reward APR) * Show reward token types and amounts * Display program timelines and eligibility ### 2\. User Balance Tracking[](https://docs.morpho.org/build/rewards/get-started#2-user-balance-tracking) Show users their accrued and claimable rewards: * Fetch user-specific reward balances * Display rewards by token and program * Calculate USD values of rewards * Update balances in real-time ### 3\. Claiming Interface[](https://docs.morpho.org/build/rewards/get-started#3-claiming-interface) Enable users to claim their rewards: * Support Merkl claim flow (primary) * Support Morpho URD claim flow (legacy) * Handle transaction signing and confirmation * Provide claim status feedback Integration Paths[](https://docs.morpho.org/build/rewards/get-started#integration-paths) ------------------------------------------------------------------------------------------- First, [Understand Reward Programs](https://docs.morpho.org/build/rewards/concepts/reward-campaigns) and learn the different program types. Choose your integration approach based on your needs: ### Quick Start (Display Only)[](https://docs.morpho.org/build/rewards/get-started#quick-start-display-only) Just want to show rewards APR alongside base yield? Start here: 1. [Fetch Rewards Data](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data) - Learn to query both APIs 2. [Integrate Display](https://docs.morpho.org/build/rewards/tutorials/integrate-display) - Show rewards in your UI ### Full Integration (Display + Claiming)[](https://docs.morpho.org/build/rewards/get-started#full-integration-display--claiming) Building a complete product? Follow this path: 1. [Merkl Distribution System](https://docs.morpho.org/build/rewards/concepts/distribution-system) - Understand Distribution 2. [Fetch Rewards Data](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data) - Query rewards information 3. [Claim Rewards](https://docs.morpho.org/build/rewards/tutorials/claim-rewards) - Implement claiming for both systems 4. [Complete Integration Guide](https://docs.morpho.org/build/rewards/guides/complete-integration) - See a full working example ### Creating Rewards (Issuers)[](https://docs.morpho.org/build/rewards/get-started#creating-rewards-issuers) Are you a protocol or DAO looking to create a rewards program? 1. [Create a Program](https://docs.morpho.org/build/rewards/tutorials/create-program) - Step-by-step program creation Need Help?[](https://docs.morpho.org/build/rewards/get-started#need-help) ---------------------------------------------------------------------------- * **Technical Support**: Visit [help.morpho.org](https://help.morpho.org/) * **Merkl Support**: Reach out via [Merkl's documentation](https://docs.merkl.xyz/) --- # Reward Campaigns on Morpho – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Concepts On this page Chevron Right Reward campaigns are incentive strategies created via [Merkl](https://merkl.xyz/) to encourage specific user behaviors within the Morpho protocol. Understanding how these campaigns work and the different distribution strategies available is essential for integrators who want to accurately display and calculate reward rates for their users. What Are Reward Campaigns?[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#what-are-reward-campaigns) -------------------------------------------------------------------------------------------------------------------------- Merkl allows protocols, DAOs, and token issuers to **reward users for providing active liquidity** on Morpho. Campaigns incentivize users who hold supply or borrow balances on the protocol. Rewards are distributed automatically based on users' positions over time. When creating a campaign through Merkl's interface, you select: * The lending market or vault you want to incentivize * The reward token to distribute * The campaign duration and reward budget * The specific user behavior to reward (supply or borrow) It is also possible to incentivize a simple collateral deposit (without the borrow action required). Distribution Strategies[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#distribution-strategies) --------------------------------------------------------------------------------------------------------------------- Merkl offers two main categories of reward distribution for Morpho: 1. **Vault-Level Incentives** - Target deposits into specific Morpho Vaults 2. **Market-Level Incentives** - Target activity within Morpho Markets ### Vault-Level Incentives[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#vault-level-incentives) **Strategy: Supply to a Morpho Vault** This strategy incentivizes users who deposit assets into a specific Morpho Vault. It's the simplest distribution method, rewarding vault depositors proportionally based on their share of total vault deposits over time. **How it works:** * Rewards are distributed linearly over the campaign duration * Users earn rewards based on their vault deposit amount and duration * All depositors into the targeted vault are eligible * Only one reward rate applies (vault supply rewards) **Use cases:** * Bootstrap a new vault to attract initial liquidity * Increase deposits into an established vault * Provide additional yield to vault depositors beyond base APY ### Market-Level Incentives[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#market-level-incentives) **Strategy: Incentivize Activity in Morpho V1 Markets** Market-level strategies provide more granular control, allowing you to target specific behaviors within Morpho V1 Markets. You can incentivize: * **Supply**: Reward users who lend assets to a market * **Borrow**: Reward users who borrow assets from a market Additionally, you can choose between: * **Specific market targeting**: Incentivize activity in one particular market * **Token-based targeting**: Incentivize use of a specific token across all markets **Distribution Options:** 1. **Supply to a specific market**: Rewards users who supply assets to a particular Morpho V1 market. 2. **Supply a token to any market**: Rewards users who supply a specific token across all Morpho V1 markets (e.g., all markets where USDC is the loan asset). 3. **Borrow from a specific market**: Rewards users who borrow assets from a particular Morpho V1 market. 4. **Borrow a token from any market**: Rewards users who borrow a specific token across all Morpho V1 markets. **How it works:** * Campaigns distribute rewards linearly over a defined period * Each campaign can have separate rates for supply and borrow * Users earn rewards based on their position size and duration * Rates are expressed as annualized amounts per token **Use cases:** * Bootstrap a new market by incentivizing early suppliers or borrowers * Encourage borrowing to increase market utilization * Reward specific collateral types to diversify market risk * Create token-wide incentives across the entire Morpho ecosystem Combining Multiple Campaigns[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#combining-multiple-campaigns) ------------------------------------------------------------------------------------------------------------------------------- Merkl API provides an APR for each campaign (vault and market ones). Vault depositors may be eligible for rewards from **multiple campaigns simultaneously**: 1. **Direct vault-level rewards**: From campaigns directly targeting the vault 2. **Forwarded market-level rewards**: From campaigns targeting markets where the vault allocates liquidity **Total Vault APY:** Copy `Total APY = Base Vault APY + Vault Campaign APR + Σ(Forwarded Market Campaign APR)` Where: * **Base Vault APY**: Native lending yield from the vault's market allocations * **Vault Campaign APR**: Direct vault-level incentives * **Forwarded Market Campaign APR**: Sum of all market-level rewards from allocated markets Reward Forwarding[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#reward-forwarding) --------------------------------------------------------------------------------------------------------- One of the most important features of Morpho's reward system is **automatic reward forwarding** for vault depositors. ### How Forwarding Works[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#how-forwarding-works) When a Morpho Vault allocates liquidity to a market with an active supply campaign, the vault itself technically earns those rewards (since it's the direct supplier to the market). However, these rewards are **automatically forwarded to individual vault depositors** proportionally to their vault shares. **The forwarding mechanism:** 1. Market-level supply campaigns distribute rewards to suppliers 2. Vaults that supply to these markets earn rewards at the vault contract level 3. Merkl's offchain computation reallocates these rewards to individual vault depositors 4. Vault depositors can claim these market-level rewards directly This happens transparently in the background, ensuring that: * Vault depositors benefit from all market-level campaigns * No manual intervention is required * Rewards are distributed fairly based on deposit amounts and duration Forwarding works for Morpho Vaults V1 and Morpho Vaults V2. ### Integration Considerations[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#integration-considerations) As an integrator, you should display: * **Direct vault campaigns**: Campaigns explicitly targeting the vault * **Forwarded market campaigns**: Campaigns targeting markets where the vault allocates, with rewards forwarded to depositors * **Combined APR**: Total reward APR from both sources Users expect to see the full picture of their potential earnings, including both direct and forwarded rewards. Blacklisting[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#blacklisting) ----------------------------------------------------------------------------------------------- Campaign creators can **blacklist specific addresses** from earning rewards. This is commonly used to: * Prevent self-incentivization when protocols bootstrap their own markets * Exclude treasury addresses that provide initial liquidity * Remove addresses that don't align with campaign goals **Example:** If a protocol creates a market and deposits its treasury to provide initial liquidity, it can blacklist its treasury address. This ensures: * Reward budget goes entirely to external users * No circular incentive flow * Fair distribution among community participants Blacklisting is configured when creating the campaign and is enforced during rewards computation. It's transparent—anyone can verify which addresses are excluded from a campaign. Historical Context: Legacy Reward Systems[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#historical-context-legacy-reward-systems) -------------------------------------------------------------------------------------------------------------------------------------------------------- Querying Active Campaigns[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#querying-active-campaigns) ------------------------------------------------------------------------------------------------------------------------- You can see how to retrieve campaigns data in the [Fetch Rewards Data section](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data) . Next Steps[](https://docs.morpho.org/build/rewards/concepts/reward-campaigns#next-steps) ------------------------------------------------------------------------------------------- * **Create campaigns**: Follow the [Create a Rewards Program tutorial](https://docs.morpho.org/build/rewards/tutorials/create-program) * **Understand distribution**: Read about [Distribution System](https://docs.morpho.org/build/rewards/concepts/distribution-system) * **Fetch data**: Follow the [Fetch Rewards Data tutorial](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data) * **Display rewards**: See the [Integrate Display tutorial](https://docs.morpho.org/build/rewards/tutorials/integrate-display) --- # Merkl Distribution System – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/concepts/distribution-system#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Distribution System On this page Chevron Right [Merkl](https://merkl.xyz/) is a third-party rewards distribution platform that has become the standard for Morpho rewards following [MIP 111](https://snapshot.box/#/s:morpho.eth/proposal/0xadf3862d97cf4e8bb84a4b3d5117abe1a9db774e92ad97c65bde22214c0b76c9) . How Merkl Works[](https://docs.morpho.org/build/rewards/concepts/distribution-system#how-merkl-works) -------------------------------------------------------------------------------------------------------- ### Offchain Computation[](https://docs.morpho.org/build/rewards/concepts/distribution-system#offchain-computation) Merkl's infrastructure continuously monitors onchain activity and calculates earned rewards: * Monitors onchain activity directly via RPC nodes * Proprietary indexing infrastructure * Real-time event processing This is necessary because: 1. **Complex logic**: Reward calculations involve historical data, forwarding, and blacklisting 2. **Gas efficiency**: Computing onchain would be prohibitively expensive 3. **Flexibility**: Allows for sophisticated distribution strategies ### Merkle Tree Generation & Onchain Distribution[](https://docs.morpho.org/build/rewards/concepts/distribution-system#merkle-tree-generation--onchain-distribution) Every 8 hours, Merkl generates a new Merkle tree containing all claimable rewards. The Merkle root is posted onchain, making rewards claimable. * Rewards are recalculated every 8 hours * Users see their accruing rewards in near real-time ### User Claims[](https://docs.morpho.org/build/rewards/concepts/distribution-system#user-claims) Users can claim their rewards by submitting a transaction with their Merkle proof. * Low waiting period between earning and claiming Key Characteristics[](https://docs.morpho.org/build/rewards/concepts/distribution-system#key-characteristics) ---------------------------------------------------------------------------------------------------------------- **Standardized Integration** * Consistent API across all protocols using Merkl * Well-documented claiming process * Community-supported SDKs and tools **Multi-Protocol Support** * Same infrastructure used by many DeFi protocols * Familiar UX for users who've claimed rewards elsewhere * Centralized infrastructure for reward discovery When to Use[](https://docs.morpho.org/build/rewards/concepts/distribution-system#when-to-use) ------------------------------------------------------------------------------------------------ Integrate Merkl for: * All new reward programs (July 2025 onwards) * Current MORPHO token distributions * Third-party incentive programs * Real-time reward tracking Integration Points[](https://docs.morpho.org/build/rewards/concepts/distribution-system#integration-points) -------------------------------------------------------------------------------------------------------------- **For Claiming Rewards:** head to the [Integrate Rewards Claim](https://docs.morpho.org/build/rewards/tutorials/claim-rewards) section. **For Displaying Rewards:** head to the [Integrate Rewards Display](https://docs.morpho.org/build/rewards/tutorials/integrate-display) section. --- # Morpho API – Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/api/get-started/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Morpho API On this page Chevron Right The Morpho API provides a powerful, GraphQL-based interface for accessing a comprehensive range of onchain and offchain data from the Morpho ecosystem. It is designed for developers building applications, dashboards, bots, or any service that requires reliable data on Morpho Markets, Morpho Vaults, user positions, and more. Endpoints[](https://docs.morpho.org/tools/offchain/api/get-started/#endpoints) --------------------------------------------------------------------------------- The ecosystem uses two primary API endpoints: * **Main GraphQL API**: For all data related to markets, vaults, and positions. You can explore the schema and run live queries in the [GraphQL Playground](https://api.morpho.org/graphql) . * **Rewards API**: A dedicated REST API for fetching data on reward programs, user eligibility, and distributions. See the [Rewards API Documentation](https://rewards.morpho.org/docs) for details. Key Data & Features[](https://docs.morpho.org/tools/offchain/api/get-started/#key-data--features) ---------------------------------------------------------------------------------------------------- * **Real-time & Historical Data**: Access both current state and historical timeseries data for markets and vaults. * **Market & Vault Analytics**: Retrieve metrics like APYs, TVL, utilization, fees, and market allocations. * **User Positions**: Fetch detailed information on supply, borrow, and collateral positions for any user. * **Public Allocator Liquidity**: Query data on reallocatable liquidity available through the Public Allocator. Supported Networks[](https://docs.morpho.org/tools/offchain/api/get-started/#supported-networks) --------------------------------------------------------------------------------------------------- The API provides data for fully supported deployments on networks including: * **Ethereum** (Chain ID: 1) * **Arbitrum** (Chain ID:42161) * **Base** (Chain ID: 8453) * **HyperEVM** (Chain ID: 999) * **Katana** (Chain ID: 747474) * **Polygon** (Chain ID: 137) * **Unichain** (Chain ID: 130) Morpho API main rules[](https://docs.morpho.org/tools/offchain/api/get-started/#morpho-api-main-rules) --------------------------------------------------------------------------------------------------------- ### Maximum complexity of a GraphQL query[](https://docs.morpho.org/tools/offchain/api/get-started/#maximum-complexity-of-a-graphql-query) A complexity score is associated with each query in the Morpho API. GraphQL complexity details: * **Max allowed complexity: 1,000,000** * Base cost per operation: 10 * Each field adds cost; some fields declare explicit costs and/or multipliers. One can verify its queries' complexity in [https://api.morpho.org/graphql](https://api.morpho.org/graphql) . The complexity number is returned as an extension. If one of the query is above the threshold, you have the following alternatives: * **Trim the selection set**: keep only fields you actually use. Prefer cheap snapshots (state.\*) over histories when possible. * **Lower fan-out**: reduce first (e.g., 25 or 50), then paginate. * **Split the work**: fetch a light list first (IDs + a few cheap fields), then run follow-up queries for heavy history on a subset. * **Tune multipliers**: for fields like currentIrmCurve(numberOfPoints: N), lower N. ### Best Practices & Rate Limiting[](https://docs.morpho.org/tools/offchain/api/get-started/#best-practices--rate-limiting) To ensure reliable service for all users, **the API is subject to rate limiting: 5k/5min**. We strongly recommend implementing the following best practices in your integration: * **Cache Responses**: Cache API query results on your backend to reduce redundant requests and improve your application's performance. * **Request Only What You Need**: Structure your GraphQL queries to fetch only the data fields required for your use case. * **Avoid Excessive Polling**: Design your application to fetch data efficiently, respecting API limits to prevent interruptions. The `numberOfResults` parameter in the search root resolver is constrained to be within \[0, 1000\] (default value being 5). Where to Find Query Examples[](https://docs.morpho.org/tools/offchain/api/get-started/#where-to-find-query-examples) ----------------------------------------------------------------------------------------------------------------------- This page serves as a high-level overview. For detailed documentation and hands-on query examples, please refer to the dedicated sections below. ### Comprehensive API Documentation[](https://docs.morpho.org/tools/offchain/api/get-started/#comprehensive-api-documentation) For a full list of available queries, schemas, and example use cases for each part of the protocol, explore these sections: * [**Morpho Markets API**](https://docs.morpho.org/tools/offchain/api/morpho) * [**Morpho Vaults API**](https://docs.morpho.org/tools/offchain/api/morpho-vaults) * [**Public Allocator API**](https://docs.morpho.org/tools/offchain/api/public-allocator) * [**Rewards API**](https://docs.morpho.org/tools/offchain/api/rewards) ### Practical Integration Tutorials[](https://docs.morpho.org/tools/offchain/api/get-started/#practical-integration-tutorials) To see how the API is used in practical integration scenarios, check out our step-by-step tutorials: * **Integrating Earn Data**: See the [Get Data for Earn](https://docs.morpho.org/build/earn/tutorials/get-data) tutorial. * **Integrating Borrow Data**: Follow the [Get Data for Borrow](https://docs.morpho.org/build/borrow/tutorials/get-data) guide. * **Fetching Public Allocator Data**: Visit the [Trigger the Public Allocator](https://docs.morpho.org/build/borrow/tutorials/public-allocator) tutorial. --- # Morpho Markets – Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/api/morpho/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Morpho Markets On this page Chevron Right How to query Morpho Markets Data thanks to the API?[](https://docs.morpho.org/tools/offchain/api/morpho/#how-to-query-morpho-markets-data-thanks-to-the-api) --------------------------------------------------------------------------------------------------------------------------------------------------------------- Select the query you are interested in in the list below, and paste it into the GraphQL Playground: [https://api.morpho.org/graphql](https://api.morpho.org/graphql) By default, the Morpho API returns only the 100 first results and retrieve informations on the Ethereum network. Discovery and Listing[](https://docs.morpho.org/tools/offchain/api/morpho/#discovery-and-listing) ---------------------------------------------------------------------------------------------------- ### Markets List[](https://docs.morpho.org/tools/offchain/api/morpho/#markets-list) All MarketsWhitelisted Markets All Markets Copy `query { markets { items { uniqueKey lltv oracleAddress irmAddress loanAsset { address symbol decimals } collateralAsset { address symbol decimals } state { borrowAssets supplyAssets fee utilization } } } }` ### Market Parameters[](https://docs.morpho.org/tools/offchain/api/morpho/#market-parameters) All MarketsSpecific Market All Markets Copy `query { markets( first: 100 orderBy: SupplyAssetsUsd orderDirection: Desc where: { chainId_in: [1, 8453] } ) { items { uniqueKey loanAsset { address } collateralAsset { address } lltv irmAddress oracleAddress } } }` Market Metrics[](https://docs.morpho.org/tools/offchain/api/morpho/#market-metrics) -------------------------------------------------------------------------------------- ### Total Collateral, Borrow & Supply[](https://docs.morpho.org/tools/offchain/api/morpho/#total-collateral-borrow--supply) All MarketsSpecific Market All Markets Copy `query { markets( first: 100 orderBy: SupplyAssetsUsd orderDirection: Desc where: { chainId_in: [1, 8453] } ) { items { uniqueKey state { collateralAssets collateralAssetsUsd borrowAssets borrowAssetsUsd supplyAssets supplyAssetsUsd liquidityAssets liquidityAssetsUsd } } } }` ### Market APY (Native & Rewards)[](https://docs.morpho.org/tools/offchain/api/morpho/#market-apy-native--rewards) All MarketsSpecific Market All Markets Copy `query { markets( first: 100 orderBy: SupplyAssetsUsd orderDirection: Desc where: { chainId_in: [1, 8453] } ) { items { uniqueKey state { borrowApy avgBorrowApy avgNetBorrowApy supplyApy avgSupplyApy avgNetSupplyApy rewards { asset { address chain { id } } supplyApr borrowApr } } } } }` Asset Information[](https://docs.morpho.org/tools/offchain/api/morpho/#asset-information) -------------------------------------------------------------------------------------------- ### Assets (Price & Yield)[](https://docs.morpho.org/tools/offchain/api/morpho/#assets-price--yield) Copy `query GetAssetsWithPrice { assets(where: { symbol_in: ["wstETH", "WETH"], chainId_in: [1] }) { items { symbol address priceUsd chain { id network } } } }` * `priceUsd` is the current price of the asset in USD. * `oraclePriceUsd` is a deprecated field, please use priceUsd instead. Position Tracking[](https://docs.morpho.org/tools/offchain/api/morpho/#position-tracking) -------------------------------------------------------------------------------------------- ### User Positions[](https://docs.morpho.org/tools/offchain/api/morpho/#user-positions) #### User All Markets Position[](https://docs.morpho.org/tools/offchain/api/morpho/#user-all-markets-position) Copy `query { marketPositions( first: 10, orderBy: BorrowAssetsUsd, orderDirection: Desc where: { marketUniqueKey_in: ["0x698fe98247a40c5771537b5786b2f3f9d78eb487b4ce4d75533cd0e94d88a115"] } ) { items { user { address } state { collateral borrowAssets borrowAssetsUsd } } } }` #### User Account Overview[](https://docs.morpho.org/tools/offchain/api/morpho/#user-account-overview) Copy `query { userByAddress( chainId: 1 address: "0x821880a3E2bac432d67E5155e72BB655Ef65fa5E" ) { address marketPositions { market { uniqueKey } borrowAssets borrowAssetsUsd supplyAssets supplyAssetsUsd } vaultPositions { vault { address name } assets assetsUsd shares } transactions { hash timestamp type } } }` ### All Market Positions[](https://docs.morpho.org/tools/offchain/api/morpho/#all-market-positions) Copy `query { marketPositions( first: 10 orderBy: SupplyShares orderDirection: Desc where: { marketUniqueKey_in: [ "0x698fe98247a40c5771537b5786b2f3f9d78eb487b4ce4d75533cd0e94d88a115" ] } ) { items { market { uniqueKey loanAsset { address symbol } collateralAsset { address symbol } } user { address } state { supplyShares supplyAssets supplyAssetsUsd borrowShares borrowAssets borrowAssetsUsd collateral collateralUsd } } } }` Risk & Oracle Data[](https://docs.morpho.org/tools/offchain/api/morpho/#risk--oracle-data) --------------------------------------------------------------------------------------------- ### Oracle Data[](https://docs.morpho.org/tools/offchain/api/morpho/#oracle-data) #### All Markets[](https://docs.morpho.org/tools/offchain/api/morpho/#all-markets) Copy `query MARKETS_PARAMS { markets( first: 100 orderBy: SupplyAssetsUsd orderDirection: Desc where: { chainId_in: [1, 8453] } ) { items { uniqueKey oracleAddress oracle { address type creationEvent { txHash timestamp blockNumber } data { ... on MorphoChainlinkOracleV2Data { baseFeedOne { address description vendor pair } baseFeedTwo { address } baseVaultConversionSample quoteFeedOne { address } quoteFeedTwo { address } quoteVaultConversionSample } ... on MorphoChainlinkOracleData { baseFeedOne { address description vendor pair } baseOracleVault { address } } } } oracleInfo { type } } } }` #### Specific Market[](https://docs.morpho.org/tools/offchain/api/morpho/#specific-market) Copy `query { marketByUniqueKey( uniqueKey: "0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836" chainId: 8453 ) { uniqueKey oracleAddress oracle { address type creationEvent { txHash timestamp blockNumber } data { ... on MorphoChainlinkOracleV2Data { baseFeedOne { address description vendor pair } baseFeedTwo { address } baseVaultConversionSample quoteFeedOne { address } quoteFeedTwo { address } quoteVaultConversionSample } ... on MorphoChainlinkOracleData { baseFeedOne { address description vendor pair } baseOracleVault { address } } } } oracleInfo { type } } }` ### Liquidations[](https://docs.morpho.org/tools/offchain/api/morpho/#liquidations) Copy `query { transactions( where: { marketUniqueKey_in: [ "0x49bb2d114be9041a787432952927f6f144f05ad3e83196a7d062f374ee11d0ee" "0x093d5b432aace8bf6c4d67494f4ac2542a499571ff7a1bcc9f8778f3200d457d" ] type_in: [MarketLiquidation] } ) { items { blockNumber hash type user { address } data { ... on MarketLiquidationTransactionData { seizedAssets repaidAssets seizedAssetsUsd repaidAssetsUsd badDebtAssetsUsd liquidator market { uniqueKey } } } } } }` ### Market Warnings[](https://docs.morpho.org/tools/offchain/api/morpho/#market-warnings) Copy `query { markets { items { uniqueKey warnings { type level } } } }` Integration[](https://docs.morpho.org/tools/offchain/api/morpho/#integration) -------------------------------------------------------------------------------- ### Vault Listing[](https://docs.morpho.org/tools/offchain/api/morpho/#vault-listing) Copy `query { marketByUniqueKey( uniqueKey: "0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836" chainId: 8453 ) { uniqueKey supplyingVaults { address symbol metadata { description } } } }` Historical Data[](https://docs.morpho.org/tools/offchain/api/morpho/#historical-data) ---------------------------------------------------------------------------------------- The `historicalState` allows to get historical data for certain queries. The queries need to be backfilled to return proper data (i.e. the historical data needs to be indexed and stored). Some queries are not backfilled and are flagged as deprecated in [the Morpho API sandbox](https://api.morpho.org/graphql) . ### How to use the historicalState variables[](https://docs.morpho.org/tools/offchain/api/morpho/#how-to-use-the-historicalstate-variables) Here are the available variables when using an `historicalState` query: * `startTimestamp`: beginning of the historical data in UNIX timestamp format, * `endTimestamp`: end of the historical data in UNIX timestamp format, * `interval`: interval of the historical data points (`YEAR`, `QUARTER`, `MONTH`, `WEEK`, `DAY`, `HOUR`). Inputting these variables is not mandatory but it is advised to specify them to control the specific data returned. If no variables are specified, the default values will be: * `startTimestamp`: 0, * `endTimestamp`: infinity, * `interval`: will adjust according to `startTimestamp` and `endTimestamp` to return around 50 data points. Note that the `historicalState` field is not accessible through the (multiple) markets(...) and vaults(...) list queries. Historical data is only available through individual market or vault queries like `market(id: "")`, `marketByUniqueKey`, `vault(id: "")` or `vaultByAddress`. Below you will find examples of `historicalData` queries. ### Historical APYs[](https://docs.morpho.org/tools/offchain/api/morpho/#historical-apys) Copy `query MarketByUniqueKey($uniqueKey: String!, $options: TimeseriesOptions) { marketByUniqueKey(uniqueKey: $uniqueKey) { historicalState { supplyApy(options: $options) { x y } borrowApy(options: $options) { x y } } } }` With the following `variables`: Copy `{ "variables": { "startTimestamp": 1707749700, "endTimestamp": 1708354500, "interval": HOUR, } }` ### Historical Market States[](https://docs.morpho.org/tools/offchain/api/morpho/#historical-market-states) Copy `query MarketApys($options: TimeseriesOptions) { marketByUniqueKey( uniqueKey: "0x608929d6de2a10bacf1046ff157ae38df5b9f466fb89413211efb8f63c63833a" ) { uniqueKey historicalState { supplyAssetsUsd(options: $options) { x y } borrowAssetsUsd(options: $options) { x y } } } }` With the following `variables`: Copy `"variables": { "startTimestamp": 1707749700, "endTimestamp": 1708354500, "interval": HOUR, }` ### Historical Asset Price[](https://docs.morpho.org/tools/offchain/api/morpho/#historical-asset-price) Copy `query { wstETHWeeklyPriceUsd: assetByAddress( address: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0" chainId: 1 ) { historicalPriceUsd( options: { startTimestamp: 1707749700 endTimestamp: 1708354500 interval: HOUR } ) { x y } } }` All queries sent for `assetByAddress`, `marketByUniqueKey` and `vaultByAddress` should include the `chainId` parameter. Advanced Features[](https://docs.morpho.org/tools/offchain/api/morpho/#advanced-features) -------------------------------------------------------------------------------------------- ### Paging, Ordering & Filtering[](https://docs.morpho.org/tools/offchain/api/morpho/#paging-ordering--filtering) Copy `query { markets( first: 3 skip: 1 orderBy: Lltv orderDirection: Desc where: { collateralAssetAddress_in: ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"] } ) { pageInfo { count countTotal } items { uniqueKey lltv collateralAsset { symbol } loanAsset { symbol } } } }` --- # Public Allocator – Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/api/public-allocator/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Public Allocator On this page Chevron Right How to query Public Allocator's Data thanks to the API?[](https://docs.morpho.org/tools/offchain/api/public-allocator/#how-to-query-public-allocators-data-thanks-to-the-api) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Select the query you are interested in in the list below, and paste it into the GraphQL Playground: [https://api.morpho.org/graphql](https://api.morpho.org/graphql) Basic Queries[](https://docs.morpho.org/tools/offchain/api/public-allocator/#basic-queries) ---------------------------------------------------------------------------------------------- ### Public Allocator address[](https://docs.morpho.org/tools/offchain/api/public-allocator/#public-allocator-address) Copy `query { publicAllocators { items { address creationBlockNumber morphoBlue { address chain { id network } } } } }` ### Total reallocatable liquidity[](https://docs.morpho.org/tools/offchain/api/public-allocator/#total-reallocatable-liquidity) Reallocations necessary to reach this number Copy `query { marketByUniqueKey( uniqueKey: "0xe7e9694b754c4d4f7e21faf7223f6fa71abaeb10296a4c43a54a7977149687d2" chainId: 1 ) { reallocatableLiquidityAssets state { liquidityAssets } publicAllocatorSharedLiquidity { assets vault { address name } allocationMarket { uniqueKey } } } }` ### Market's Available liquidity[](https://docs.morpho.org/tools/offchain/api/public-allocator/#markets-available-liquidity) Available liquidity of a market taking account for the public Allocator. Copy `query MarketByUniqueKey($uniqueKey: String!, $chainId: Int) { marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) { reallocatableLiquidityAssets state { liquidityAssets } publicAllocatorSharedLiquidity { assets vault { address name } allocationMarket { uniqueKey reallocatableLiquidityAssets } } } }` with the following variables: Copy `{ "uniqueKey": "0xb8fc70e82bc5bb53e773626fcc6a23f7eefa036918d7ef216ecfb1950a94a85e", "chainId": 1 }` Market's Available liquidity is `liquidityAssets` (the market liquidity) + the sum of `reallocatableLiquidityAssets` (what can be reallocated from other markets). ### Reallocations that occurred for a Morpho Vault[](https://docs.morpho.org/tools/offchain/api/public-allocator/#reallocations-that-occurred-for-a-morpho-vault) Copy `query { publicAllocatorReallocates( where: { vaultAddress_in: ["0xBEEf050ecd6a16c4e7bfFbB52Ebba7846C4b8cD4"] } ) { items { timestamp assets type vault { address } market { uniqueKey } } } }` ### Config of the Public Allocator for a Morpho Vault[](https://docs.morpho.org/tools/offchain/api/public-allocator/#config-of-the-public-allocator-for-a-morpho-vault) Copy `query { vaultByAddress( address: "0x38989BBA00BDF8181F4082995b3DEAe96163aC5D" chainId: 1 ) { address publicAllocatorConfig { fee flowCaps { market { uniqueKey } maxIn maxOut } } } }` --- # Morpho Vaults for Earn products – Morpho Docs [Skip to content](https://docs.morpho.org/build/earn/get-started#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Get Started On this page Chevron Right Integrating Morpho Vaults (Earn) into your application means implementing the infrastructure that allows users to deposit assets into yield-generating vaults built on top of Morpho's lending protocol. As of today, one can integrate both [Morpho Vaults V2](https://docs.morpho.org/learn/concepts/vault-v2) and [Morpho Vaults V1](https://docs.morpho.org/learn/concepts/vault) . The users will benefit from earning native yield on their deposited assets, alongside with incentives (rewards) from different rewards provider. Key Components of Earn Integration[](https://docs.morpho.org/build/earn/get-started#key-components-of-earn-integration) -------------------------------------------------------------------------------------------------------------------------- When building earn products with Morpho Vaults, you need to integrate three main components: 1. **Vault Operations**: Deposit, withdraw, and position management 2. **Yield Tracking**: Vault APY calculation and performance monitoring 3. **Rewards Integration**: Discovery, tracking, and claiming of additional incentives Here is a quick visual for better understanding: ![Slide 1](https://docs.morpho.org/img/earn/Developers_Earn_MorphoVaultsforEarnPorducts_1_light.png) ![Slide 2](https://docs.morpho.org/img/earn/Developers_Earn_MorphoVaultsforEarnPorducts_2_light.png) ![Slide 3](https://docs.morpho.org/img/earn/Developers_Earn_MorphoVaultsforEarnPorducts_3_light.png) Integrating Earn gives users access to: 1. **Curated Risk Profiles**: Unlike traditional lending platforms where users are exposed to all assets in the pool, Morpho Vaults allow selective exposure to specific collateral types based on risk preferences. 2. **Permissionless Infrastructure**: Any entity (individual, DAO, protocol) can create and manage vaults with different risk parameters and allocation strategies. 3. **Non-Custodial Architecture**: All positions remain fully controlled by the user with transparent onchain verification of allocations and immutable vault logic. Technical Components[](https://docs.morpho.org/build/earn/get-started#technical-components) ---------------------------------------------------------------------------------------------- From a technical standpoint, integrating Earn involves: 1. **Vault Discovery and Display**: Implementing systems to discover available vaults, display their key metrics (APY, TVL, allocation breakdown), and present risk profiles to users. 2. **Transaction Handling**: Building the interface and backend support for deposit and withdrawal operations, including: * Asset approval workflows * Transaction status monitoring * Receipt confirmation and position updates * Rewards tracking updates 3. **Position Management**: Creating interfaces for users to: * View their current vault positions * Track historical performance * Monitor yield accrual * Perform deposits & withdrawals * Claim rewards 4. **Risk Transparency**: Building displays that clearly communicate: * Which Morpho markets the vault allocates to * Collateral types users are exposed to * Current utilization ratios * Current allocation strategy and any pending changes Rewards Considerations[](https://docs.morpho.org/build/earn/get-started#rewards-considerations) -------------------------------------------------------------------------------------------------- A complete Earn integration should include rewards functionality as one of the core components. Many Morpho Vaults earn additional incentives beyond base lending yield through reward campaigns. Key aspects to integrate: * **Rewards Discovery**: Identify available reward programs for vault depositors * **Rewards Tracking**: Display accruing and claimable rewards in real-time * **Claiming Process**: Implement claim functionality using Merkle-proof based distribution systems (URD and Merkl) * **Multi-Token Support**: Handle various reward tokens from different reward providers * **Program Awareness**: Display active campaigns and their respective parameters For detailed implementation guidance, see the [Rewards integration guide](https://docs.morpho.org/build/rewards/get-started) . Assets Flow - Earn[](https://docs.morpho.org/build/earn/get-started#assets-flow---earn) ------------------------------------------------------------------------------------------ Understanding the complete flow of assets is crucial for proper integration: ### 1\. Deposit[](https://docs.morpho.org/build/earn/get-started#1-deposit) * User deposits an asset (e.g., USDC, ETH) into a Morpho Vault * User receives vault shares (ERC4626 tokens) representing their proportional ownership * The vault allocates the deposited assets across: * Morpho Markets V1 (for Vaults V1) * Morpho Vaults V1 (for Vaults V2) based on the curator's strategy * These markets are permissionless pools containing a loan token (what was deposited) and a collateral token ### 2\. Yield Generation[](https://docs.morpho.org/build/earn/get-started#2-yield-generation) * Borrowers deposit collateral into Morpho Markets and borrow the loan token * Borrowers pay interest on borrowed amounts * This interest accrues to suppliers (the vault, in this case) * The vault's share price increases as interest accumulates, representing yield for depositors ### 3\. Withdrawal Process[](https://docs.morpho.org/build/earn/get-started#3-withdrawal-process) * Users can redeem their vault shares for the underlying asset at any time * Vault V1 pulls liquidity directly from Morpho Markets V1 via its withdrawal queue * Vault V2 pulls liquidity from underlying Morpho Vaults V1, which in turn pull from Morpho Markets V1 * Users receive their original deposit plus accrued yield (minus any performance or management fee) Functional Integration Requirements[](https://docs.morpho.org/build/earn/get-started#functional-integration-requirements) ---------------------------------------------------------------------------------------------------------------------------- For a complete Earn integration, your system needs to implement: 1. **Read Operations**: * Query vault metadata (name, symbol, asset, curator, fees) * Fetch current APY and historical performance * Display current allocation across markets * Show user-specific position data * Present risk parameters of underlying markets 2. **Write Operations**: * Handle asset approvals * Execute deposits & withdrawals * Facilitate claiming any associated rewards 3. **Monitoring Capabilities**: * Track position changes * Alert users to significant vault parameter changes * Update yield information in real-time Risk Considerations[](https://docs.morpho.org/build/earn/get-started#risk-considerations) -------------------------------------------------------------------------------------------- A complete Earn integration should help users understand: 1. **Smart Contract Risk**: Exposure to both Morpho and Vault contracts 2. **Market Risk**: Exposure to specific collateral types and their volatility 3. **Curator Risk**: Dependence on curator's expertise and continued management 4. **Liquidity Risk**: Potential for withdrawal delays during high utilization 5. **Oracle Risk**: Vulnerability to incorrect price feeds affecting underlying markets By properly integrating these components, your application can offer users access to Morpho's capital-efficient lending infrastructure through a curated, simplified experience that abstracts away much of the complexity while maintaining transparency about underlying risks and operations. --- # Morpho Markets for Borrow products – Morpho Docs [Skip to content](https://docs.morpho.org/build/borrow/get-started#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Get Started On this page Chevron Right Integrating Morpho Markets (Borrow) into your application means implementing the infrastructure that allows users to supply collateral and borrow assets directly from isolated lending markets. Users will pay a borrow rate on their borrowed assets and may receive incentives (rewards). A critical part of a borrow integration is facilitating the monitoring of position health to help users avoid **liquidation**, where their collateral can be seized to repay their debt. Note: Borrowers will see interests accruing in their debt position, while the collateral remains idle, and do not yield. Key Components of Borrow Integration[](https://docs.morpho.org/build/borrow/get-started#key-components-of-borrow-integration) -------------------------------------------------------------------------------------------------------------------------------- When building borrow products with Morpho Markets, you need to integrate three main components: 1. **Market Operations**: Supplying collateral, borrowing, repaying, and withdrawing collateral. 2. **Position Health Management**: Real-time tracking of Loan-to-Value (LTV), Health Factor, and liquidation risk. 3. **Rewards Integration**: Discovery and claiming of incentives for supplying collateral or borrowing. Integrating Borrow gives users access to: 1. **Isolated Risk**: Each market's risk is contained. A problem in one market (e.g., a volatile collateral asset) does not affect the solvency of any other market. 2. **Capital Efficiency**: The underlying interest rate models are designed for high utilization, which translates to better rates for both borrowers and lenders. 3. **Deep Liquidity via Public Allocator**: While markets are isolated, the [Public Allocator](https://docs.morpho.org/build/borrow/tutorials/public-allocator) enables liquidity to flow between them on demand, ensuring borrowers can access deep liquidity from a single market. Technical Components[](https://docs.morpho.org/build/borrow/get-started#technical-components) ------------------------------------------------------------------------------------------------ From a technical standpoint, integrating Borrow involves: 1. **Market Discovery and Display**: Implementing systems to discover available markets and display their key parameters (Collateral/Loan Asset, APYs, TVL, LLTV, Oracle, IRM). 2. **Transaction Handling**: Building the interface and backend support, including asset approvals, transaction monitoring, and position updates. Here are the four core market operations: * `supplyCollateral` * `borrow` * `repay` * `withdrawCollateral` 3. **Position Management**: Creating interfaces for users to: * View their current collateral and debt balances. * Clearly track their **Health Factor** and current LTV. * Perform any of the four core market operations. * Claim any available rewards. 4. **Liquidation Risk Transparency**: Building clear and prominent displays that communicate: * The user's current Health Factor. * The market's Liquidation Loan-to-Value (LLTV), which is the LTV at which liquidation can occur. * Visual warnings when a user's position health is declining. Rewards Considerations[](https://docs.morpho.org/build/borrow/get-started#rewards-considerations) ---------------------------------------------------------------------------------------------------- A complete Borrow integration should include rewards functionality. Many markets offer incentives for both borrowers and collateral suppliers through reward campaigns. Key aspects to integrate: * **Rewards Discovery**: Identify available reward programs for borrowers and collateral suppliers * **Rewards Tracking**: Display accruing and claimable rewards in real-time * **Claiming Process**: Implement claim functionality using Merkle-proof based distribution systems (URD and Merkl) * **Multi-Token Support**: Handle various reward tokens from different incentive programs * **Program Awareness**: Display active campaigns and their respective parameters For detailed implementation guidance, see the [Rewards integration guide](https://docs.morpho.org/build/rewards/get-started) . Assets Flow - Borrow[](https://docs.morpho.org/build/borrow/get-started#assets-flow---borrow) ------------------------------------------------------------------------------------------------ Understanding the complete flow of assets is crucial for a proper integration: ### 1\. Supply Collateral[](https://docs.morpho.org/build/borrow/get-started#1-supply-collateral) * A user selects a market (e.g., wstETH/WETH). * They supply a collateral asset (wstETH) to the market. This collateral secures their future debt. ### 2\. Borrow[](https://docs.morpho.org/build/borrow/get-started#2-borrow) * The user borrows the loan asset (WETH) from the same market. * The amount they can borrow is limited by the value of their collateral and the market's Liquidation Loan-to-Value (LLTV). * The user's **Health Factor** is established, representing their position's safety from liquidation. ### 3\. Repay[](https://docs.morpho.org/build/borrow/get-started#3-repay) * The user repays the loan asset (WETH), either partially or in full. * Repaying debt reduces their LTV and increases their Health Factor, making their position safer. * Interest continuously accrues on the outstanding debt, which must also be repaid. ### 4\. Withdraw Collateral[](https://docs.morpho.org/build/borrow/get-started#4-withdraw-collateral) * After repaying debt, the user can withdraw their collateral. * They can only withdraw collateral if their position remains healthy (i.e., their Health Factor stays above 1). If the user has fully repaid their debt, they can withdraw all of their collateral. Functional Integration Requirements[](https://docs.morpho.org/build/borrow/get-started#functional-integration-requirements) ------------------------------------------------------------------------------------------------------------------------------ For a complete Borrow integration, your system needs to implement: 1. **Read Operations**: * Query market parameters (LLTV, oracle, irm, etc.). * Fetch real-time market state (APYs, total supply/borrow, utilization). * Display user-specific position data (collateral, debt, **Health Factor**). * Present available liquidity, including reallocatable liquidity from the Public Allocator. 2. **Write Operations**: * Handle token approvals for supplying collateral and repaying debt. * Execute `supplyCollateral`, `borrow`, `repay`, and `withdrawCollateral`. * Facilitate claiming any associated rewards. 3. **Monitoring Capabilities**: * Track position Health Factor changes in real-time. * Alert users when their position approaches the liquidation threshold. * Update market data and interest rates dynamically. Risk Considerations[](https://docs.morpho.org/build/borrow/get-started#risk-considerations) ---------------------------------------------------------------------------------------------- A responsible Borrow integration must clearly communicate the following risks to the user: 1. **Liquidation Risk**: This is the primary risk for borrowers. If a position's Health Factor drops below 1, their collateral can be seized by liquidators, resulting in a loss of funds. 2. **Oracle Risk**: Inaccurate or manipulated price feeds from the market's oracle can lead to premature liquidations or prevent timely ones, causing bad debt. 3. **Smart Contract Risk**: Exposure to vulnerabilities in the Morpho core contracts. 4. **Market Liquidity Risk**: Low liquidity in a market can prevent users from borrowing or impact interest rates significantly. 5. **Counterparty Risk**: The risk associated with the assets themselves (e.g., de-pegging of a stablecoin or centralization risk of a token). By properly integrating these components and transparently communicating risks, your application can offer users direct access to Morpho's efficient and secure lending markets. --- # Morpho Vaults – Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Morpho Vaults On this page Chevron Right How to query Morpho Vaults Data thanks to the API?[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#how-to-query-morpho-vaults-data-thanks-to-the-api) -------------------------------------------------------------------------------------------------------------------------------------------------------------------- Select the query you are interested in in the list below, and paste it into the GraphQL Playground: [https://api.morpho.org/graphql](https://api.morpho.org/graphql) Discovery and Listing[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#discovery-and-listing) ----------------------------------------------------------------------------------------------------------- ### Vaults List[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#vaults-list) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2s(first: 1000, where: { chainId_in: [1, 8453] }) { items { address symbol name whitelisted asset { id address decimals } chain { id network } } } }` Vault Metrics[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#vault-metrics) ------------------------------------------------------------------------------------------- ### Total Deposits & Assets[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#total-deposits--assets) #### All Vaults[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#all-vaults) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2s(first: 100) { items { address totalAssets totalAssetsUsd totalSupply liquidityUsd idleAssetsUsd } } }` #### Specific Vault[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#specific-vault) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2ByAddress( address: "0x04422053aDDbc9bB2759b248B574e3FCA76Bc145" chainId: 1 ) { address totalAssets totalAssetsUsd totalSupply liquidity liquidityUsd idleAssetsUsd } }` ### APY (Native + Rewards)[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#apy-native--rewards) #### All Vaults[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#all-vaults-1) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2s(first: 10) { items { address asset { yield { apr } } avgApy avgNetApy performanceFee managementFee maxRate rewards { asset { address chain { id } } supplyApr yearlySupplyTokens } } } }` #### Specific Vault[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#specific-vault-1) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2ByAddress( address: "0x04422053aDDbc9bB2759b248B574e3FCA76Bc145" chainId: 1 ) { address asset { yield { apr } } avgApy avgNetApy performanceFee managementFee maxRate rewards { asset { address chain { id } } supplyApr yearlySupplyTokens } } }` ### Share Price (Token Value)[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#share-price-token-value) #### All Vaults[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#all-vaults-2) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2s(first: 10) { items { address totalSupply totalAssets } } }` #### Specific Vault[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#specific-vault-2) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2ByAddress( address: "0x04422053aDDbc9bB2759b248B574e3FCA76Bc145" chainId: 1 ) { totalAssets totalSupply } }` Allocation & Strategy[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#allocation--strategy) ---------------------------------------------------------------------------------------------------------- Vault V2 allocation data is expressed via adapters, whereas Vault V1 allocations reference the underlying Morpho Markets V1. Keep that distinction in mind when mapping results. ### Current Allocations[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#current-allocations) #### All Vaults[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#all-vaults-3) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2s(first: 10) { items { address totalAssetsUsd totalAssets totalSupply adapters { items { address assets assetsUsd type } } } } }` #### Specific Vault[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#specific-vault-3) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2ByAddress( address: "0x04422053aDDbc9bB2759b248B574e3FCA76Bc145" chainId: 1 ) { totalAssetsUsd totalAssets totalSupply adapters { items { address assets assetsUsd type } } } }` ### Strategy: Vault Queues (Morpho Vaults V1)[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#strategy-vault-queues-morpho-vaults-v1) All VaultsSpecific Vault All Vaults Copy `query { vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) { items { address state { totalAssets lastTotalAssets allocation { supplyQueueIndex withdrawQueueIndex market { uniqueKey } } } } } }` Configuration & Curation[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#configuration--curation) ---------------------------------------------------------------------------------------------------------------- ### Vault Parameters[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#vault-parameters) #### All Vaults[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#all-vaults-4) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2s(first: 10) { items { address name whitelisted metadata { description forumLink image } allocators { allocator { address } } owner { address } curators { items { addresses { address } } } sentinels { sentinel { address } } timelocks { duration selector functionName } } } }` #### Specific Vault[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#specific-vault-4) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2ByAddress( address: "0x04422053aDDbc9bB2759b248B574e3FCA76Bc145" chainId: 1 ) { address name whitelisted metadata { description forumLink image } allocators { allocator { address } } owner { address } curators { items { addresses { address } } } sentinels { sentinel { address } } timelocks { duration selector functionName } } }` ### Risk Indicators[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#risk-indicators) #### Vault Warnings[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#vault-warnings) a. Warning `type` can be: * unrecognized\_deposit\_asset, * unrecognized\_vault\_curator. * not\_whitelisted. b. Warning `level` is either: * `YELLOW`, * `RED`. Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2s(first: 5) { items { name warnings { type level } } } }` You can read more about warnings in the dedicated section [here](https://docs.morpho.org/get-started/resources/app-ecosystem#more-resources-below) . ### Vault Curation[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#vault-curation) _Note: These curator-focused endpoints currently expose Vault V1 data._ #### Current Vaults Pending Caps[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#current-vaults-pending-caps) Copy `query { vaults { items { pendingCaps { validAt supplyCap market { uniqueKey } } } } }` #### Current Vaults Allocators[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#current-vaults-allocators) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2s(first: 10) { items { name allocators { allocator { address } } } } }` Position Tracking[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#position-tracking) --------------------------------------------------------------------------------------------------- ### Vault Depositors[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#vault-depositors) #### Specific Vault[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#specific-vault-5) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2ByAddress( address: "0x04422053aDDbc9bB2759b248B574e3FCA76Bc145" chainId: 1 ) { positions(first: 10, skip:0) { items { user { address } assets assetsUsd shares } } totalSupply asset { address symbol } } }` #### Set of Vaults (Morpho Vaults V1)[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#set-of-vaults-morpho-vaults-v1) _Vault V2 does not yet expose an equivalent batched depositor query._ Copy `query { vaultPositions( first: 10 orderBy: Shares orderDirection: Desc where: { vaultAddress_in: [ "0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB" "0x73e65DBD630f90604062f6E02fAb9138e713edD9" ] } ) { items { vault { address } user { address } state { shares assets assetsUsd } } } }` ### User Positions[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#user-positions) #### User All Vaults Position (Vault V1)[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#user-all-vaults-position-vault-v1) Copy `query GetUserVaultPositions($address: String!, $chainId: Int!) { userByAddress(address: $address, chainId: $chainId) { id vaultV2Positions { state { shares } vault { address symbol } } vaultPositions { state { shares } vault { address symbol } } } }` #### User Account Overview[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#user-account-overview) Copy `query { userByAddress( chainId: 1 address: "0x821880a3E2bac432d67E5155e72BB655Ef65fa5E" ) { address marketPositions { market { uniqueKey } borrowAssets borrowAssetsUsd supplyAssets supplyAssetsUsd } vaultPositions { vault { address name } assets assetsUsd shares } transactions { hash timestamp type } } }` ### Transaction History[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#transaction-history) #### Specific Vault[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#specific-vault-6) Morpho Vaults V2Morpho Vaults V1 Morpho Vaults V2 Copy `query { vaultV2transactions( first: 10 skip: 0 where: { vaultAddress_in: "0x04422053aDDbc9bB2759b248B574e3FCA76Bc145" } ) { items { vault { address } type shares blockNumber timestamp txHash txIndex } } }` #### Latest Transactions (All Vaults)[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#latest-transactions-all-vaults) Copy `query { transactions( first: 10 orderBy: Timestamp orderDirection: Desc where: { type_in: [MetaMorphoFee, MetaMorphoWithdraw, MetaMorphoWithdraw] } ) { items { hash timestamp type chain { id network } user { address } data { ... on VaultTransactionData { shares assets vault { address } } ... on MarketTransferTransactionData { shares market { uniqueKey } } } } } }` Public Allocator[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#public-allocator) ------------------------------------------------------------------------------------------------- ### Configuration[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#configuration) Copy `query { vaultByAddress( address: "0x38989BBA00BDF8181F4082995b3DEAe96163aC5D" chainId: 1 ) { address publicAllocatorConfig { fee flowCaps { market { uniqueKey } maxIn maxOut } } } }` ### Reallocations[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#reallocations) Copy `query { vaultReallocates( first: 10 skip: 0 orderBy: Timestamp where: {vaultAddress_in:["0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB"]} orderDirection: Desc ) { items { id timestamp hash blockNumber caller shares assets type vault { id chain { id } } market { id uniqueKey lltv oracleAddress irmAddress creationBlockNumber loanAsset { symbol } collateralAsset { symbol } } } pageInfo { countTotal count skip limit } } }` Historical Data[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#historical-data) ----------------------------------------------------------------------------------------------- ### APY Historical State (Morpho Vaults V1)[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#apy-historical-state-morpho-vaults-v1) #### All Vaults[](https://docs.morpho.org/tools/offchain/api/morpho-vaults/#all-vaults-5) All VaultsSpecific Vault All Vaults Copy `query VaultApys($options: TimeseriesOptions) { vaults(first: 10, orderBy: TotalAssetsUsd, orderDirection: Desc) { items { address historicalState { apy(options: $options) { x y } netApy(options: $options) { x y } } } } }` **Query Variables:** Copy `{ "options": { "startTimestamp": 1716249600, "endTimestamp": 1716422400, "interval": "DAY" } }` --- # Morpho Subgraphs – Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/subgraphs/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Morpho Subgraphs On this page Chevron Right Introduction[](https://docs.morpho.org/tools/offchain/subgraphs/#introduction) --------------------------------------------------------------------------------- The Morpho Subgraphs provide a powerful and efficient way to access and retrieve data from the Morpho Protocol using GraphQL. These subgraphs index onchain data for all Morpho Markets and Morpho Vaults, making it easy for developers to track protocol activity, user positions, and other key analytics without needing to process raw blockchain data directly. The subgraphs follow the [Messari Schema standard for Lending protocols](https://github.com/messari/subgraphs/blob/master/schema-lending.graphql) , ensuring a familiar and standardized data structure. Note that some entity names may differ from Morpho's internal naming to align with this standard. Disclaimer: Open-Source and Community Maintained[](https://docs.morpho.org/tools/offchain/subgraphs/#disclaimer-open-source-and-community-maintained) -------------------------------------------------------------------------------------------------------------------------------------------------------- The Morpho Subgraphs are open-source and maintained by the community. The source code is available in the [morpho-blue-subgraph repository on GitHub](https://github.com/morpho-org/morpho-blue-subgraph) . Please be aware that Morpho Association does not provide official support for these subgraphs. Developers are encouraged to understand the code and use it at their own discretion. Accessing the Subgraphs[](https://docs.morpho.org/tools/offchain/subgraphs/#accessing-the-subgraphs) ------------------------------------------------------------------------------------------------------- To query the subgraphs, you need a basic understanding of GraphQL. All subgraphs are accessible through The Graph's decentralized network. 1. **Explore in the Playground**: You can find all official deployments on [The Graph Explorer](https://thegraph.com/explorer/profile/0x84d3e4ee550dd5f99e76a548ac59a6be1c8dcf79?view=Subgraphs) . Select a subgraph and use the "Playground" tab to write and test queries directly in your browser. 2. **Programmatic Access (API Key)**: For use in applications or scripts, you must generate an API key from [The Graph Studio](https://thegraph.com/studio/apikeys/) . Add this key to the query URL provided on each subgraph's explorer page. Subgraph Studio users start on a free plan, which is sufficient for most development and testing purposes. For more details on pricing and query limits, refer to [The Graph's official documentation](https://thegraph.com/docs) . Subgraph Deployments[](https://docs.morpho.org/tools/offchain/subgraphs/#subgraph-deployments) ------------------------------------------------------------------------------------------------- Here is a list of the official subgraph deployments across various networks: * [Ethereum Mainnet](https://thegraph.com/explorer/subgraphs/8Lz789DP5VKLXumTMTgygjU2xtuzx8AhbaacgN5PYCAs) * [Base](https://thegraph.com/explorer/subgraphs/71ZTy1veF9twER9CLMnPWeLQ7GZcwKsjmygejrgKirqs) * [Arbitrum](https://thegraph.com/explorer/subgraphs/XsJn88DNCHJ1kgTqYeTgHMQSK4LuG1LR75339QVeQ26) * [Corn](https://thegraph.com/explorer/subgraphs/4SswjwWRyBryaEBwzHfwayEpJWRS9f7xvsGC5kE6govQ) * [Fraxtal](https://thegraph.com/explorer/subgraphs/CDFzHFQTXj1ryFgA8KpkUuv6qu3Jk6fLG7kzdpuCe95g) * [Hemi](https://thegraph.com/explorer/subgraphs/2JZScBV6sD7BdoU9JBAwYPrbzUarPGGz9P1xVWFQxmdX) * [Ink](https://thegraph.com/explorer/subgraphs/7pezYZCEJVBbZbbkjLFcPo3hdVUxUv8skF2FqGibRcfk) * [MODE](https://thegraph.com/explorer/subgraphs/341uEcvH1UAzWETvVB974Au1YR3MksJdf2jhjuHXDLQ7) * [OP Mainnet](https://thegraph.com/explorer/subgraphs/5y8d3K3vVCR7r5YwANGCjupLc3hUge54XvhYMEq3Jmq1) * [Polygon POS](https://thegraph.com/explorer/subgraphs/EhFokmwryNs7qbvostceRqVdjc3petuD13mmdUiMBw8Y) * [Scroll](https://thegraph.com/explorer/subgraphs/Aic7prLAxhtipUEbLu5BhDDWf4LssT9n3DG4fT9yCRqm) * [Sonic](https://thegraph.com/explorer/subgraphs/J2THmwKHrTLKT9HPZNwZ69NkJ7WSbtLKz7pUQZW1Z1Qc) * [Unichain](https://thegraph.com/explorer/subgraphs/ESbNRVHte3nwhcHveux9cK4FFAZK3TTLc5mKQNtpYgmu) Query Examples[](https://docs.morpho.org/tools/offchain/subgraphs/#query-examples) ------------------------------------------------------------------------------------- ### Morpho Market Examples[](https://docs.morpho.org/tools/offchain/subgraphs/#morpho-market-examples) #### 1\. `BorrowAPY`[](https://docs.morpho.org/tools/offchain/subgraphs/#1-borrowapy) This query retrieves the annualized borrow rate for the top 100 markets. Copy `{ interestRates( first: 100 where: { side: BORROWER } orderBy: market__totalValueLockedUSD orderDirection: desc ) { id rate side } }` The returned `rate` is an annualized value. To get the APY, you can use the formula: `BorrowAPY = e^(rate) - 1`. #### 2\. `SupplyAPY`[](https://docs.morpho.org/tools/offchain/subgraphs/#2-supplyapy) This query retrieves the annualized supply rate for the top 100 markets. Copy `{ interestRates( first: 100 where: { side: LENDER } orderBy: market__totalValueLockedUSD orderDirection: desc ) { id rate side } }` Similarly, the `SupplyAPY` can be calculated as `e^(rate) - 1`. #### 3\. `Market Data`[](https://docs.morpho.org/tools/offchain/subgraphs/#3-market-data) This query fetches comprehensive data for the top 1000 markets by TVL. Copy `{ markets(first: 1000, orderBy: totalValueLockedUSD, orderDirection: desc) { id name isActive inputToken { name } borrowedToken { name symbol } totalValueLockedUSD totalBorrowBalanceUSD totalDepositBalanceUSD cumulativeBorrowUSD cumulativeDepositUSD maximumLTV liquidationThreshold liquidationPenalty } }` #### 4\. `Positions Data`[](https://docs.morpho.org/tools/offchain/subgraphs/#4-positions-data) This query retrieves all positions for the first 1000 accounts. Copy `{ accounts(first: 1000) { id positionCount openPositionCount positions { id market { id } asset { id } side isCollateral balance } } }` ### Morpho Vault Examples[](https://docs.morpho.org/tools/offchain/subgraphs/#morpho-vault-examples) #### 1\. Vault-Specific Data[](https://docs.morpho.org/tools/offchain/subgraphs/#1-vault-specific-data) This query fetches detailed configuration data for a specific Morpho Vault. Copy `{ metaMorphos(where: { id: "0xbeef02e5e13584ab96848af90261f0c8ee04722a" }) { id name symbol owner { id } curator { id } fee asset { id } supplyQueue { market { id } } withdrawQueue { market { id } } timelock } }` Questions[](https://docs.morpho.org/tools/offchain/subgraphs/#questions) --------------------------------------------------------------------------- If you have any questions or need further assistance, please don't hesitate to reach out via the chatbox on **[help.morpho.org](https://help.morpho.org/) **. --- # Guide: Integrating One-Click Yield with OnchainKit – Morpho Docs [Skip to content](https://docs.morpho.org/build/earn/guides/base-onchainkit/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Guides On this page Chevron Right This tutorial provides a complete guide for developers to integrate a simple, high-yield deposit feature into their applications using Morpho's Vaults and Coinbase's OnchainKit. This powerful combination allows you to offer your users a seamless, one-click experience to earn interest on their crypto, complete with gas-sponsored transactions, all powered by Base and Morpho's efficient onchain infrastructure. We will walk through the entire process, from initial setup to implementing both a plug-and-play component and a fully custom UI. **Final Product:** By the end of this guide, you'll be able to integrate a yield component into any Base-related app, similar to the earn features found in leading wallets and dApps. Architecture Overview[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#architecture-overview) ------------------------------------------------------------------------------------------------------------ The integration relies on two key components working in concert: 1. **Morpho Protocol (Vaults)**: Provides the core, permissionless yield infrastructure. Morpho Vaults are ERC4626-compliant smart contracts that automatically allocate user deposits across various Morpho Markets to generate an optimized, passive yield. 2. **OnchainKit**: Acts as the developer-friendly SDK and component library for building onchain apps on Base. It handles wallet connections, transaction building, and provides pre-built React components like `` that abstract away the complexity of interacting with DeFi protocols. Here is a high-level view of the interaction flow: Copy `┌───────────┐ │ End User │ └───────────┘ │ │ Interacts with ▼ ┌──────────────────┐ │ Your Application │ └──────────────────┘ │ │ Uses ▼ ┌────────────────────┐ │ OnchainKit │ │ Component │ └────────────────────┘ │ │ 1. Connects Wallet │ 2. Builds & Sponsors Transaction (via Paymaster) ▼ ┌──────────────────┐ │ Base Chain │ └──────────────────┘ │ │ Executes atomic deposit call ▼ ┌──────────────────┐ │ Morpho Vault │ │ (deposit) │ └──────────────────┘` Part 1: Setup and Configuration[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#part-1-setup-and-configuration) ------------------------------------------------------------------------------------------------------------------------------- This guide assumes you are building a React application with TypeScript on the Base network. #### Step 1: Install Dependencies[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#step-1-install-dependencies) We recommend starting with the official OnchainKit template, which sets up the entire environment for you. Copy `npm create onchain@latest` If you are adding OnchainKit to an existing project, install the necessary packages: Copy `npm install @coinbase/onchainkit viem wagmi @tanstack/react-query` #### Step 2: Configure Paymaster for Gas Sponsorship[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#step-2-configure-paymaster-for-gas-sponsorship) To sponsor your users' gas fees, you'll need a Paymaster service. OnchainKit is deeply integrated with the Coinbase Developer Platform (CDP). 1. **Create a CDP Account**: Sign up on the **[Coinbase Developer Platform](https://cdp.coinbase.com/) **. 2. **Create a Project**: Create a new project and get your `projectId`. 3. **Set up a Paymaster**: Navigate to the "Paymaster" section, create a new paymaster for the Base network, and copy the **Paymaster URL**. 4. **Fund Your Paymaster**: Add funds to your CDP account to cover the gas fees for your users. 5. **Allowlist Contracts (Important!)**: In your Paymaster policy settings, you **must** allowlist the contract functions the `` component will call: * The **Morpho Vault** address: allow the `deposit` and `redeem` functions. * The **underlying token** (e.g., USDC, WETH) address: allow the `approve` function. #### Step 3: Define Constants[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#step-3-define-constants) For a clean implementation, define your vault address in a separate constants file. You can find a list of available Morpho Vaults on the **[Morpho App](https://app.morpho.org/base/earn) **. Copy `// constants.ts import { base } from "viem/chains"; // 1. Supported Network export const SUPPORTED_NETWORK = base; // 2. Morpho Vault Address on Base (Example: USDC Vault) export const MORPHO_USDC_VAULT_ADDRESS = "0x425314C7836371752a7b8eF41B32997f888A011f";` #### Step 4: Configure the OnchainKit Provider[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#step-4-configure-the-onchainkit-provider) Wrap your application's root with the `OnchainKitProvider`. This makes all of OnchainKit's hooks and components available throughout your app. Copy `// In your main App.tsx or a layout component import { OnchainKitProvider } from '@coinbase/onchainkit'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { base } from 'viem/chains'; import { WagmiProvider, createConfig, http } from 'wagmi'; const queryClient = new QueryClient(); // Configure wagmi with the standard Base RPC const wagmiConfig = createConfig({ chains: [base], transports: { [base.id]: http(), }, }); const App = ({ children }: { children: React.ReactNode }) => { return ( {children} ); };` * * * Part 2: Building the Earn Component[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#part-2-building-the-earn-component) --------------------------------------------------------------------------------------------------------------------------------------- OnchainKit offers incredible flexibility. You can either use the pre-built, plug-and-play `` component for a quick integration, or build a fully custom UI using its underlying hooks. ### Option A: The Plug-and-Play Approach (Easiest)[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#option-a-the-plug-and-play-approach-easiest) This is the fastest way to add a yield feature to your app. The `` component handles the entire UI and transaction logic for you. Copy `// components/SimpleEarnComponent.tsx import { Earn } from '@coinbase/onchainkit/earn'; import { MORPHO_USDC_VAULT_ADDRESS } from '../constants'; export const SimpleEarnComponent = () => { return (
); };` **That's it!** You now have a fully functional, gas-sponsored yield component in your application. ### Option B: The Custom UI Approach (Advanced)[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#option-b-the-custom-ui-approach-advanced) For full control over the look and feel, you can build your own component using the `useEarnContext` hook and the declarative `` component. Copy ``// components/CustomEarnComponent.tsx import React, { useCallback } from 'react'; import { useAccount } from 'wagmi'; import { Earn, useEarnContext, buildDepositToMorphoTx, } from '@coinbase/onchainkit/earn'; import { Transaction } from '@coinbase/onchainkit/transaction'; import { parseUnits } from 'viem'; import { MORPHO_USDC_VAULT_ADDRESS } from '../constants'; // A custom UI that uses the underlying context from the provider const CustomDepositUI = () => { const { address } = useAccount(); // useEarnContext gives you all the data you need about the vault const { apy, vaultToken, setDepositAmount, depositAmount } = useEarnContext(); // This function prepares the transaction calls. // It's passed to the component, which handles execution. const buildCalls = useCallback(async () => { if (!address || !depositAmount || parseFloat(depositAmount) === 0) return []; const parsedAmount = parseUnits(depositAmount, vaultToken.decimals); // OnchainKit's helper function builds the necessary `approve` and `deposit` calls. const calls = await buildDepositToMorphoTx({ vaultAddress: MORPHO_USDC_VAULT_ADDRESS, tokenAddress: vaultToken.address, amount: parsedAmount, recipientAddress: address, }); return calls; }, [address, depositAmount, vaultToken]); return (

Custom Deposit for {vaultToken.symbol}

APY: {(apy * 100).toFixed(2)}%

setDepositAmount(e.target.value)} /> {/* The component is a declarative wrapper. It takes the `buildCalls` function and handles the button state, transaction submission, and waiting states for you. */}
); }; // You must wrap your custom UI with the component to provide the context. export const CustomEarnComponent = () => { return ( ); };`` * * * Part 3: Production Considerations[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#part-3-production-considerations) ----------------------------------------------------------------------------------------------------------------------------------- ### Security Best Practices[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#security-best-practices) * **Key Management**: Never expose private keys or Paymaster URLs in client-side code. Use secure environment variables. * **Input Validation**: Always validate and sanitize user inputs, especially amounts, to prevent errors and unexpected behavior. * **Paymaster Monitoring**: Regularly monitor your Paymaster balance on the Coinbase Developer Platform to ensure you have sufficient funds to sponsor user transactions. Set up low-balance alerts. ### Common Issues & Troubleshooting[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#common-issues--troubleshooting) | Issue | Solution | | --- | --- | | **Transaction fails silently** | Check the browser console for detailed error messages. Common causes include an incorrect `vaultAddress` or network mismatch. | | **Paymaster / Gas Sponsorship Fails** | Verify your Paymaster URL is correct, your account is funded, and that you have allowlisted the vault and token contracts in your CDP policy. | | **Component not rendering data** | Ensure that `OnchainKitProvider` correctly wraps your entire application or the component tree where `` is used. | | **"Cannot estimate gas"** | This often points to an onchain error. Ensure the user has enough of the asset to deposit or that the vault contract is operational. | Key Resources & Next Steps[](https://docs.morpho.org/build/earn/guides/base-onchainkit/#key-resources--next-steps) --------------------------------------------------------------------------------------------------------------------- You now have the building blocks to integrate a powerful, user-friendly yield product. To learn more, explore these resources: [### OnchainKit Earn Docs\ \ Dive deeper into the `` component, its subcomponents, and the `useEarnContext` hook.\ \ Read Docs →](https://docs.base.org/onchainkit/earn/earn) [### OnchainKit Quickstart\ \ Review the setup process and explore other powerful components for identity, transactions, and more.\ \ Start Building →](https://docs.base.org/onchainkit/get-started) [### Morpho Earn Concepts\ \ Understand the mechanics behind Morpho Vaults, including how yield is generated and risks are managed.\ \ Learn More →](https://docs.morpho.org/build/earn/get-started) [### Community Support\ \ Join the Base Discord to ask questions and get help from the community and the OnchainKit team.\ \ Join Discord →](https://discord.gg/buildonbase) --- # Dune – Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/dune/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Dune On this page Chevron Right [Dune](https://dune.com/home) defines itself as the Crypto's Data Hub. It is a platform that provides comprehensive data and analytics for the cryptocurrency space. It offers access to community dashboards, allowing users to track metrics for DeFi, NFTs, and various crypto projects. It provides data infrastructure to Web3 teams, supporting multiple blockchains and offering tools for data analysis, integration, and application development. Multiple open source dashboards are provided below: High-level dashboards[](https://docs.morpho.org/tools/offchain/dune/#high-level-dashboards) ---------------------------------------------------------------------------------------------- * [GMorpho Dashboard](https://dune.com/morpho/gmorpho-dashboard) * [Morpho protocol](https://dune.com/morpho/multichain-activity) Domain specific dashboards[](https://docs.morpho.org/tools/offchain/dune/#domain-specific-dashboards) -------------------------------------------------------------------------------------------------------- * [Morpho Migrations](https://dune.com/morpho/morpho-migration) * [Coinbase Onchain Borrowing & Lending](https://dune.com/morpho/coinbase-onchain-lending-borrowing) * [Vault Performance](https://dune.com/morpho/vault-performance) * [Morpho Credit Risk](https://dune.com/morpho/morpho-credit-risk) If you want to be displayed here, please reach out via the chatbox on **[help.morpho.org](https://help.morpho.org/) **. --- # How Bundlers Work – Morpho Docs [Skip to content](https://docs.morpho.org/tools/onchain/bundlers/how-it-works/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu How Bundlers Work On this page Chevron Right Morpho Bundlers simplify complex onchain interactions by acting as a trusted dispatcher. Developers define a sequence of actions offchain using the SDK, which are then encoded and executed atomically onchain by the `Bundler3` smart contract. The Onchain & Offchain Flow[](https://docs.morpho.org/tools/onchain/bundlers/how-it-works/#the-onchain--offchain-flow) ------------------------------------------------------------------------------------------------------------------------- 1. **Offchain (SDK Layer)**: Your application uses the `bundler-sdk` to define a sequence of high-level actions (e.g., `Blue_SupplyCollateral`, `Blue_Borrow`). The SDK simulates these actions, automatically adding necessary steps like token approvals and transfers, and then encodes them into a single `multicall`. 2. **Onchain (Contract Layer)**: The encoded bundle is sent to the `Bundler3` contract's `multicall` function. The bundler then dispatches each call to its respective adapter for execution in a single, atomic transaction. Onchain Architecture: `Bundler3` and Adapters[](https://docs.morpho.org/tools/onchain/bundlers/how-it-works/#onchain-architecture-bundler3-and-adapters) ----------------------------------------------------------------------------------------------------------------------------------------------------------- The onchain system is composed of a core `Bundler3` contract and a set of specialized `Adapters`. ### The `multicall` Function[](https://docs.morpho.org/tools/onchain/bundlers/how-it-works/#the-multicall-function) The core of the system is the `multicall(Call[] calldata bundle)` function within the `Bundler3` contract. It accepts an array of `Call` structs, where each call is defined by: * **`to`**: The target address for the call (usually an adapter). * **`data`**: The encoded function call data. * **`value`**: The amount of native currency (e.g., ETH) to send with the call. * **`skipRevert`**: A boolean flag. If `true`, the `multicall` will not revert if this specific call fails, allowing the rest of the bundle to proceed. * **`callbackHash`**: A hash used to control reentrancy, ensuring secure interactions with external contracts that might call back into the bundler. ### Adapters[](https://docs.morpho.org/tools/onchain/bundlers/how-it-works/#adapters) Adapters are modular contracts that handle the logic for specific actions. They all inherit from a `CoreAdapter`, which grants them secure access to the `initiator` (the original `msg.sender` of the `multicall`) via transient storage (`tload`). This ensures that adapters can only perform actions on behalf of the user who initiated the transaction. There are several types of adapters: * **General Adapters**: The `GeneralAdapter1` (and its chain-specific versions like `EthereumGeneralAdapter1`) handles common actions like token transfers, wrapping/unwrapping native currency, and core Morpho market/vault operations. * **DEX Adapters**: The `ParaswapAdapter` integrates with the ParaSwap DEX aggregator to perform token swaps, buys, and sells within the bundle. * **Migration Adapters**: Specialized adapters exist for migrating user positions from other protocols like Aave V2/V3 and Compound V2/V3 into Morpho seamlessly. --- # Earn: Developer Resources – Morpho Docs [Skip to content](https://docs.morpho.org/build/earn/resources/all#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Resources On this page Chevron Right This page is your central hub for all the tools, links, and data sources you need to build on Morpho's Earn product (Morpho Vaults). Onchain Data & Contracts[](https://docs.morpho.org/build/earn/resources/all#onchain-data--contracts) ------------------------------------------------------------------------------------------------------- These resources are for interacting directly with the blockchain. * **Vault Addresses**: While you can find the factory (the main address used to deploy all vaults) list of all core contracts on the main [Addresses page](https://docs.morpho.org/get-started/resources/addresses) , the best way to dynamically fetch all deployed Morpho vaults is via the [Morpho API](https://docs.morpho.org/build/earn/tutorials/get-data) . * **Contract Specifications**: For detailed function signatures, events, and errors, refer to the canonical [Morpho Vaults Contract Specs](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults) . * **GitHub Repositories**: * [`vault-v2`](https://github.com/morpho-org/vault-v2) : The V2 version of Morpho Vaults. * [`metamorpho-V1.1`](https://github.com/morpho-org/metamorpho-v1.1) : The latest Vault V1 implementation. * [`metamorpho`](https://github.com/morpho-org/metamorpho) : The original Vault V1 implementation. Offchain Data & Tools[](https://docs.morpho.org/build/earn/resources/all#offchain-data--tools) ------------------------------------------------------------------------------------------------- These tools provide easier access to onchain data for frontends, backends, and analytics. * **Morpho API (Recommended)**: The simplest way to fetch comprehensive data about vaults, their states, APYs, and user positions. * **API Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql) * **Tutorial**: [Using the API for Vaults](https://docs.morpho.org/build/earn/tutorials/get-data) * **Morpho Subgraphs**: For developers who prefer querying via The Graph protocol. * **Tutorial**: [Using Subgraphs for Vaults](https://docs.morpho.org/tools/offchain/subgraphs#morpho-vault-examples) * **SDKs**: A suite of TypeScript libraries to accelerate your development. * **`@morpho-org/blue-sdk`**: Core, framework-agnostic classes for entities like Vaults and Markets. * **`@morpho-org/blue-sdk-viem`**: Adds Viem-based fetchers to the core SDK classes. * **`@morpho-org/simulation-sdk`**: Simulates user interactions to predict outcomes before sending a transaction. * **`@morpho-org/bundler-sdk-viem`**: The essential tool for creating one-click user experiences by bundling multiple actions. * **Learn more**: [Introduction to Morpho SDKs](https://docs.morpho.org/tools/offchain/sdks/get-started) Code & Examples[](https://docs.morpho.org/build/earn/resources/all#code--examples) ------------------------------------------------------------------------------------- * **Example Application**: The [`earn-basic-app`](https://github.com/morpho-org/earn-basic-app) is a minimal but complete example of a React application for interacting with Morpho Vaults. * **Solidity Snippets**: The [`morpho-blue-snippets`](https://github.com/morpho-org/morpho-blue-snippets) repository contains simple, educational Solidity contracts for common vault interactions. --- # Rewards – Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/api/rewards/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Rewards On this page Chevron Right Endpoints[](https://docs.morpho.org/tools/offchain/api/rewards/#endpoints) ----------------------------------------------------------------------------- You can read more about Rewards integration in your product in the dedicated section [here](https://docs.morpho.org/build/rewards/get-started) . Rewards API[](https://docs.morpho.org/tools/offchain/api/rewards/#rewards-api) --------------------------------------------------------------------------------- Rewards API endpoint: [https://rewards.morpho.org/docs](https://rewards.morpho.org/docs) ### All Rewards for a User[](https://docs.morpho.org/tools/offchain/api/rewards/#all-rewards-for-a-user) This endpoint returns all rewards at the current timestamp on all chains for one user. Copy `GET /v1/users/[Address]/rewards` Example: Copy `https://rewards.morpho.org/v1/users/0x0ec553110e53122d1226646670a8475D4C8E6F04/rewards` Here is part of what the above example returns, specific to a rewards program (the endpoint can return several rewards programs for the same user depending on his eligibility). For each rewards program, you will get: * The accruing rewards: `"claimable_next"` * The claimable rewards: `"claimable_now"` * The already claimed rewards: `"claimed"` * The sum of the above: `"total"` Copy `[...] { "user": "0x0ec553110e53122d1226646670a8475D4C8E6F04", "type": "uniform-reward", "asset": { "id": "0x58D97B57BB95320F9a05dC918Aef65434969c2B2-1", "address": "0x58D97B57BB95320F9a05dC918Aef65434969c2B2", "chain_id": 1 }, "program_id": "0x5068269e48209fcd731fa6e02c54646871431970ea8eaca4c5b56ba1bc34afad", "amount": { "total": "115631364898103632676", "claimable_now": "22676259927164556632", "claimable_next": "1688912463745536463", "claimed": "91266192507193539581" } } [...]` ### All Distributions for a User[](https://docs.morpho.org/tools/offchain/api/rewards/#all-distributions-for-a-user) This endpoint returns all distributions on all chains for one user. Copy `GET /v1/users/[Address]/distributions` Example: Copy `https://rewards.morpho.org/v1/users/0x0ec553110e53122d1226646670a8475D4C8E6F04/distributions` The `"claimable"` amount retrieved for a specific `distributor` (URD) is what has been pushed onchain at the tree level to the URD making this user eligible to rewards up to this amount since inception. This amount is the sum of claimed and unclaimed rewards for a specific asset on a specific distributor. This is used to claim rewards at contract level as detailed [here](https://docs.morpho.org/build/rewards/tutorials/claim-rewards) . ### All Programs[](https://docs.morpho.org/tools/offchain/api/rewards/#all-programs) This endpoint returns all programs on all chains. Copy `GET /v1/programs` Example: Copy `https://rewards.morpho.org/v1/programs` ### State of rewards distribution[](https://docs.morpho.org/tools/offchain/api/rewards/#state-of-rewards-distribution) This endpoint returns all rewards distribution on all chains. This gives a dynamic state of the rewards distributed on Morpho (claimed and unclaimed) and it is updated every 24 hours at 00:00:00 UTC. Copy `https://rewards.morpho.org/v1/rewards/stats` Morpho API[](https://docs.morpho.org/tools/offchain/api/rewards/#morpho-api) ------------------------------------------------------------------------------- Morpho API endpoint: [https://api.morpho.org/graphql](https://api.morpho.org/graphql) ### Morpho markets rewards[](https://docs.morpho.org/tools/offchain/api/rewards/#morpho-markets-rewards) Copy `{ markets(orderBy: SupplyAssetsUsd, orderDirection: Desc) { items { uniqueKey state { rewards { supplyApr borrowApr asset { address chain { id } } } } } } }` ### Morpho Vaults rewards received through Vault programs[](https://docs.morpho.org/tools/offchain/api/rewards/#morpho-vaults-rewards-received-through-vault-programs) Copy `{ vaults(where: { chainId_in: [8453] }) { items { state { rewards { asset { address chain { id } } yearlySupplyTokens supplyApr } } } } }` ### Morpho Vaults rewards per allocated market[](https://docs.morpho.org/tools/offchain/api/rewards/#morpho-vaults-rewards-per-allocated-market) Copy `{ marketPositions( where: { userAddress_in: ["0xEbFA750279dEfa89b8D99bdd145a016F6292757b"] } ) { items { supplyAssets market { uniqueKey loanAsset { name symbol } collateralAsset { name symbol } lltv oracleAddress irmAddress state { rewards { asset { address chain { id } } supplyApr } } } } } }` ### Morpho Vaults rewards[](https://docs.morpho.org/tools/offchain/api/rewards/#morpho-vaults-rewards) To retrieve the rewards that a vault inherit, not only you have to check the rewards of the vault, but also the one inherited form the allocated markets: Copy `query VaultByAddress($address: String!, $chainId: Int) { vaultByAddress(address: $address, chainId: $chainId) { address state { rewards { asset { address name chain { id } } supplyApr } allocation { market { uniqueKey state { rewards { supplyApr asset { address chain { id } } } } } supplyAssetsUsd } } chain { id } } }` With the following variables: Copy `{ "address": "0x9aB2d181E4b87ba57D5eD564D3eF652C4E710707", "chainId": 8453 }` You can then compute the overall Vault rewards following [the Morpho Vault rewards computation](https://docs.morpho.org/build/earn/tutorials/get-data#apy-native--rewards) . For any questions on how to integrate the data, feel free to message Morpho via the chatbox on **[help.morpho.org](https://help.morpho.org/) **. --- # Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu On this page Chevron Right Introduction[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#introduction) ------------------------------------------------------------------------------------------ The [**blue-sdk-viem**](https://github.com/morpho-org/sdks/tree/main/packages/blue-sdk-viem) package extends the functionality of [**blue-sdk**](https://docs.morpho.org/tools/offchain/sdks/blue-sdk) by providing Viem-based fetchers for interacting with Morpho markets and positions onchain. This package augments the core SDK classes with static `fetch` methods that retrieve live data from the blockchain. Installation[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#installation) ------------------------------------------------------------------------------------------ To use [**blue-sdk-viem**](https://github.com/morpho-org/sdks/tree/main/packages/blue-sdk-viem) , you need to install it along with its peer dependencies: Copy `yarn add @morpho-org/blue-sdk @morpho-org/blue-sdk-viem @morpho-org/morpho-ts viem dotenv` Setup[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#setup) ---------------------------------------------------------------------------- First, import the necessary modules and set up your environment: Copy `import { MarketParams, Market, AccrualPosition, MarketId } from "@morpho-org/blue-sdk"; import "@morpho-org/blue-sdk-viem/lib/augment/MarketParams"; import "@morpho-org/blue-sdk-viem/lib/augment/Market"; import "@morpho-org/blue-sdk-viem/lib/augment/Position"; import { createClient, http } from "viem"; import { mainnet } from "viem/chains"; import "dotenv/config"; // Set up the client const client = createClient({ chain: mainnet, transport: http(process.env.RPC_URL_MAINNET), });` Make sure to set up your `.env` file with the `RPC_URL_MAINNET` variable pointing to your Ethereum node URL. Class Augmentation[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#class-augmentation) ------------------------------------------------------------------------------------------------------ The blue-sdk-viem package uses an opt-in augmentation pattern. You can import augmentations granularly or all at once: ### Granular Augmentation (Recommended)[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#granular-augmentation-recommended) Copy `import "@morpho-org/blue-sdk-viem/lib/augment/AccrualPosition"; import "@morpho-org/blue-sdk-viem/lib/augment/Holding"; import "@morpho-org/blue-sdk-viem/lib/augment/Market"; import "@morpho-org/blue-sdk-viem/lib/augment/MarketParams"; import "@morpho-org/blue-sdk-viem/lib/augment/Position"; import "@morpho-org/blue-sdk-viem/lib/augment/Token"; import "@morpho-org/blue-sdk-viem/lib/augment/VaultConfig"; import "@morpho-org/blue-sdk-viem/lib/augment/Vault"; import "@morpho-org/blue-sdk-viem/lib/augment/VaultUser"; import "@morpho-org/blue-sdk-viem/lib/augment/VaultMarketAllocation"; import "@morpho-org/blue-sdk-viem/lib/augment/VaultMarketConfig"; import "@morpho-org/blue-sdk-viem/lib/augment/VaultMarketPublicAllocatorConfig";` ### Full Augmentation[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#full-augmentation) Copy `// Import all augmentations at once import "@morpho-org/blue-sdk-viem/lib/augment";` Basic Usage[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#basic-usage) ---------------------------------------------------------------------------------------- ### Fetching Market Configuration[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#fetching-market-configuration) To fetch the configuration of a specific market from the blockchain: Copy `const marketId = "0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc" as MarketId; async function fetchMarketConfig() { console.log("Fetching market config..."); const config = await MarketParams.fetch(marketId, client); console.log("Collateral Token:", config.collateralToken); console.log("Loan Token:", config.loanToken); console.log("LLTV:", config.lltv); }` ### Fetching Market Data[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#fetching-market-data) To fetch live data for a specific market: Copy `import { Time } from "@morpho-org/morpho-ts"; async function fetchMarketData() { console.log("Fetching market data..."); const market = await Market.fetch(marketId, client); console.log("Market Utilization:", market.utilization); console.log("Market Liquidity:", market.liquidity); console.log("Market APY at Target:", market.apyAtTarget); console.log("Borrow APY:", market.borrowApy); // Accrue interest to the latest timestamp const accruedMarket = market.accrueInterest(Time.timestamp()); // Convert supply shares to assets const shares = 1_000000000000000000n; // 1 share const assets = accruedMarket.toSupplyAssets(shares); console.log("Supply Assets for 1 Share:", assets); }` ### Fetching Position Data[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#fetching-position-data) To fetch data for a user's position in a specific market: Copy `async function fetchUserPosition() { console.log("Fetching user position..."); const userAddress = "0x7f65e7326F22963e2039734dDfF61958D5d284Ca"; const position = await AccrualPosition.fetch(userAddress, marketId, client); console.log("Borrow Assets:", position.borrowAssets); console.log("Supply Assets:", position.supplyAssets); console.log("Collateral:", position.collateral); console.log("Is Position Healthy:", position.isHealthy); console.log("Max Borrowable Assets:", position.maxBorrowableAssets); // Accrue interest on the position const accruedPosition = position.accrueInterest(Time.timestamp()); console.log("Accrued Borrow Assets:", accruedPosition.borrowAssets); }` ### Fetching Historical Data[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#fetching-historical-data) You can fetch market or position data at a specific block: Copy `async function fetchHistoricalData() { const blockNumber = 18000000n; // Example block number // Fetch market data at a specific block const historicalMarket = await Market.fetch(marketId, client, { blockNumber, }); console.log("Historical Market Utilization:", historicalMarket.utilization); }` Advanced Usage[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#advanced-usage) ---------------------------------------------------------------------------------------------- ### Error Handling[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#error-handling) Always wrap your main function in a try-catch block to handle any errors: Copy `async function main() { try { await fetchMarketConfig(); await fetchMarketData(); await fetchUserPosition(); } catch (error) { console.error("An error occurred:", error); } } main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });` ### Multi-Chain Support[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#multi-chain-support) To work with multiple chains, create separate clients: Copy `import { base } from "viem/chains"; const baseClient = createClient({ chain: base, transport: http(process.env.RPC_URL_BASE), }); // Fetch from Base chain const baseMarket = await Market.fetch(marketId, baseClient);` ### Complex Scenarios[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#complex-scenarios) * Fetch data from multiple markets simultaneously * Compare positions across different markets * Track historical APY changes over time * Monitor vault allocations and rebalancing Conclusion[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#conclusion) -------------------------------------------------------------------------------------- This documentation provides a comprehensive overview of how to use the [**blue-sdk-viem**](https://github.com/morpho-org/sdks/tree/main/packages/blue-sdk-viem) package to interact with Morpho markets and positions onchain. For more advanced usage and examples, visit the [GitHub repository](https://github.com/morpho-org/sdks/tree/main/packages/blue-sdk-viem) . Examples[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#examples) ---------------------------------------------------------------------------------- ### Market Metrics and Position[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#market-metrics-and-position) Copy `import { AccrualPosition, Market, MarketParams, MarketId, } from "@morpho-org/blue-sdk"; import "@morpho-org/blue-sdk-viem/lib/augment/MarketParams"; import "@morpho-org/blue-sdk-viem/lib/augment/Market"; import "@morpho-org/blue-sdk-viem/lib/augment/Position"; import { createClient, http } from "viem"; import { mainnet } from "viem/chains"; import "dotenv/config"; import { Time } from "@morpho-org/morpho-ts"; const client = createClient({ chain: mainnet, transport: http(process.env.RPC_URL_MAINNET), }); const marketId: MarketId = "0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc" as MarketId; async function fetchMarketConfig() { console.log("Fetching market config..."); const config = await MarketParams.fetch(marketId, client); console.log("Collateral Token:", config.collateralToken); console.log("Loan Token:", config.loanToken); console.log("LLTV:", config.lltv); console.log("Liquidation Incentive Factor:", config.liquidationIncentiveFactor); } async function fetchMarketData() { console.log("Fetching market data..."); const market = await Market.fetch(marketId, client); console.log("Market Utilization:", market.utilization); console.log("Market Liquidity:", market.liquidity); console.log("Market APY at Target:", market.apyAtTarget); console.log("Borrow APY:", market.borrowApy); const accruedMarket = market.accrueInterest(Time.timestamp()); const assets = accruedMarket.toSupplyAssets(BigInt(1e18)); console.log("Supply Assets for 1 Share:", assets); } async function fetchUserPosition() { console.log("Fetching user position..."); const userAddress = "0x7f65e7326F22963e2039734dDfF61958D5d284Ca"; const position = await AccrualPosition.fetch(userAddress, marketId, client); console.log("Borrow Assets:", position.borrowAssets); console.log("Supply Assets:", position.supplyAssets); console.log("Collateral:", position.collateral); console.log("Is Position Healthy:", position.isHealthy); console.log("Max Borrowable Assets:", position.maxBorrowableAssets); const accruedPosition = position.accrueInterest(Time.timestamp()); console.log("Accrued Borrow Assets:", accruedPosition.borrowAssets); } async function main() { try { await fetchMarketConfig(); await fetchMarketData(); await fetchUserPosition(); } catch (error) { console.error("An error occurred:", error); } } main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });` ### Historical APY Calculation (1D, 7D, 30D)[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem/#historical-apy-calculation-1d-7d-30d) Copy ``import { http, Address, PublicClient, createPublicClient } from "viem"; import "dotenv/config"; import { getChainAddresses, Market, MarketId, Vault, } from "@morpho-org/blue-sdk"; import "@morpho-org/blue-sdk-viem/lib/augment"; import { base, mainnet } from "viem/chains"; interface APYData { oneDayAPY: number; sevenDayAPY: number; thirtyDayAPY: number; } // Chain-specific blocks per day const BLOCKS_PER_DAY = { MAINNET: BigInt(7000), // Ethereum mainnet: ~7000 blocks per day BASE: BigInt(7000 * 7), // Base: ~7x faster than mainnet }; async function initializeClientAndLoader(chainId: number) { const rpcUrl = chainId === 1 ? process.env.RPC_URL_MAINNET : chainId === 8453 ? process.env.RPC_URL_BASE : undefined; if (!rpcUrl) throw new Error(`No RPC URL configured for chain ID: ${chainId}`); const client = createPublicClient({ chain: chainId === 1 ? mainnet : chainId === 8453 ? base : mainnet, transport: http(rpcUrl), }); const config = getChainAddresses(chainId); if (!config) throw new Error(`Unsupported chain ID: ${chainId}`); return { client, config }; } async function getBlockNumberFromDaysAgo( client: PublicClient, daysAgo: number, chainId: number ): Promise { const currentBlock = await client.getBlockNumber(); const blocksPerDay = chainId === 1 ? BLOCKS_PER_DAY.MAINNET : BLOCKS_PER_DAY.BASE; const blockDelta = blocksPerDay * BigInt(daysAgo); const targetBlock = currentBlock > blockDelta ? currentBlock - blockDelta : BigInt(0); return targetBlock; } async function calculateAPY( currentValue: bigint, previousValue: bigint, daysPeriod: number ): Promise { if (previousValue === BigInt(0)) return 0; const percentageChange = (Number(currentValue - previousValue) / Number(previousValue)) * 100; // Convert to annual rate const annualRate = (Math.pow(1 + percentageChange / 100, 365 / daysPeriod) - 1) * 100; return Number(annualRate.toFixed(2)); } async function fetchHistoricalVaultData( vaultAddress: Address, chainId: number ): Promise { const { client } = await initializeClientAndLoader(chainId); // Get current vault state const currentVault = await Vault.fetch(vaultAddress, client); const currentAssets = currentVault.toAssets(BigInt(1e18)); // Get historical block numbers const oneDayAgoBlock = await getBlockNumberFromDaysAgo( client as PublicClient, 1, chainId ); const sevenDaysAgoBlock = await getBlockNumberFromDaysAgo( client as PublicClient, 7, chainId ); const thirtyDaysAgoBlock = await getBlockNumberFromDaysAgo( client as PublicClient, 30, chainId ); console.log("Block numbers being queried:", { oneDayAgo: oneDayAgoBlock.toString(), sevenDaysAgo: sevenDaysAgoBlock.toString(), thirtyDaysAgo: thirtyDaysAgoBlock.toString(), current: (await client.getBlockNumber()).toString(), }); // Fetch historical vault states const oneDayAgoVault = await Vault.fetch(vaultAddress, client, { blockNumber: oneDayAgoBlock, }); const sevenDaysAgoVault = await Vault.fetch(vaultAddress, client, { blockNumber: sevenDaysAgoBlock, }); const thirtyDaysAgoVault = await Vault.fetch(vaultAddress, client, { blockNumber: thirtyDaysAgoBlock, }); // Calculate historical assets const oneDayAgoAssets = oneDayAgoVault.toAssets(BigInt(1e18)); const sevenDaysAgoAssets = sevenDaysAgoVault.toAssets(BigInt(1e18)); const thirtyDaysAgoAssets = thirtyDaysAgoVault.toAssets(BigInt(1e18)); // Calculate APYs const oneDayAPY = await calculateAPY(currentAssets, oneDayAgoAssets, 1); const sevenDayAPY = await calculateAPY(currentAssets, sevenDaysAgoAssets, 7); const thirtyDayAPY = await calculateAPY( currentAssets, thirtyDaysAgoAssets, 30 ); return { oneDayAPY, sevenDayAPY, thirtyDayAPY, }; } async function fetchHistoricalMarketData( marketId: MarketId, chainId: number ): Promise { const { client } = await initializeClientAndLoader(chainId); // Get current market state const currentMarket = await Market.fetch(marketId, client); const currentAsset = currentMarket.totalBorrowAssets; const currentShare = currentMarket.totalBorrowShares; const currentRatio = currentShare / (currentAsset + 1n); // Get historical block numbers const oneDayAgoBlock = await getBlockNumberFromDaysAgo( client as PublicClient, 1, chainId ); const sevenDaysAgoBlock = await getBlockNumberFromDaysAgo( client as PublicClient, 7, chainId ); const thirtyDaysAgoBlock = await getBlockNumberFromDaysAgo( client as PublicClient, 30, chainId ); // Fetch historical market states const oneDayAgoMarket = await Market.fetch(marketId, client, { blockNumber: oneDayAgoBlock, }); const sevenDaysAgoMarket = await Market.fetch(marketId, client, { blockNumber: sevenDaysAgoBlock, }); const thirtyDaysAgoMarket = await Market.fetch(marketId, client, { blockNumber: thirtyDaysAgoBlock, }); // Calculate historical ratios const oneDayAgoRatio = oneDayAgoMarket.totalBorrowShares / (oneDayAgoMarket.totalBorrowAssets + 1n); const sevenDaysAgoRatio = sevenDaysAgoMarket.totalBorrowShares / (sevenDaysAgoMarket.totalBorrowAssets + 1n); const thirtyDaysAgoRatio = thirtyDaysAgoMarket.totalBorrowShares / (thirtyDaysAgoMarket.totalBorrowAssets + 1n); // Calculate APYs and make them positive const oneDayAPY = Math.abs( await calculateAPY(currentRatio, oneDayAgoRatio, 1) ); const sevenDayAPY = Math.abs( await calculateAPY(currentRatio, sevenDaysAgoRatio, 7) ); const thirtyDayAPY = Math.abs( await calculateAPY(currentRatio, thirtyDaysAgoRatio, 30) ); return { oneDayAPY, sevenDayAPY, thirtyDayAPY, }; } // Example usage async function main() { const testCases = [ { chain: "Base", chainId: 8453, vaultAddress: "0xc1256Ae5FF1cf2719D4937adb3bbCCab2E00A2Ca" as Address, marketId: "0x1c21c59df9db44bf6f645d854ee710a8ca17b479451447e9f56758aee10a2fad" as MarketId, }, ]; for (const test of testCases) { try { console.log(`\nFetching APY data for ${test.chain}...`); const vaultApyData = await fetchHistoricalVaultData( test.vaultAddress, test.chainId ); console.log("Vault APY Data:", { "1D APY": `${vaultApyData.oneDayAPY}%`, "7D APY": `${vaultApyData.sevenDayAPY}%`, "30D APY": `${vaultApyData.thirtyDayAPY}%`, }); const marketApyData = await fetchHistoricalMarketData( test.marketId, test.chainId ); console.log("Market APY Data:", { "1D APY": `${marketApyData.oneDayAPY}%`, "7D APY": `${marketApyData.sevenDayAPY}%`, "30D APY": `${marketApyData.thirtyDayAPY}%`, }); } catch (error) { console.error(`Error fetching data for ${test.chain}:`, error); } } } main().catch(console.error);`` --- # Guide: Integrating Gasless Crypto-Backed Loans with Gelato – Morpho Docs [Skip to content](https://docs.morpho.org/build/borrow/guides/gelato/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Guides On this page Chevron Right This tutorial provides a complete guide for developers to integrate non-custodial, crypto-backed loans into their applications using Morpho's lending protocol and Gelato's Smart Wallet SDK. This powerful combination allows you to offer your users a seamless, Web2-like experience with features like social logins and gasless transactions, all while leveraging Morpho's robust and efficient onchain infrastructure. We will walk through the entire process, from initial setup to implementing the core supply and borrow functionalities. **Final Product:** By the end of this guide, you'll be able to build a user flow similar to the official **[Morpho x Gelato Demo](https://morpho-aa.demo.gelato.cloud/) **. Architecture Overview[](https://docs.morpho.org/build/borrow/guides/gelato/#architecture-overview) ----------------------------------------------------------------------------------------------------- The integration relies on two key components working in concert: 1. **Morpho Protocol**: Provides the core, permissionless lending infrastructure. Morpho's smart contracts handle all the logic for supplying collateral, borrowing assets, managing interest rates, and ensuring protocol solvency. 2. **Gelato Smart Wallet SDK**: Acts as the abstraction layer between your application and the blockchain. It converts traditional wallets (EOAs) into smart accounts, enabling features like one-click social logins, gas fee sponsorship, and batching multiple transactions into a single, atomic operation. Here is a high-level view of the interaction flow: Copy `┌─────────────────┐ │ End User │ └─────────────────┘ │ │ Interacts with ▼ ┌─────────────────┐ │ Your Application│ └─────────────────┘ │ │ Uses ▼ ┌─────────────────┐ │ Gelato Smart │ │ Wallet SDK │ └─────────────────┘ │ │ 1. Creates Smart Account & Session │ 2. Bundles & Sponsors Transactions ▼ ┌─────────────────┐ │ Blockchain │ └─────────────────┘ │ │ Executes atomic calls ▼ ┌─────────────────┐ │ Morpho Protocol │ │ Contracts │ │ (supply, borrow)│ └─────────────────┘` ### Part 1: Setup and Configuration[](https://docs.morpho.org/build/borrow/guides/gelato/#part-1-setup-and-configuration) This guide assumes you are building a React application with TypeScript. A correct setup is critical for a stable and secure application. #### Step 1: Install Dependencies[](https://docs.morpho.org/build/borrow/guides/gelato/#step-1-install-dependencies) First, install all necessary packages from Gelato, Dynamic, and other required libraries. Copy `npm install @gelatonetwork/smartwallet @dynamic-labs/sdk-react-core @dynamic-labs/wagmi-connector @tanstack/react-query viem wagmi` #### Step 2: Obtain API Keys[](https://docs.morpho.org/build/borrow/guides/gelato/#step-2-obtain-api-keys) You will need two API keys: 1. **Gelato API Key**: This key is used to sponsor transactions (i.e., pay for your users' gas fees). * Go to the **[Gelato Relay App](https://relay.gelato.network/) **. * Create a new app, select the required networks, and copy your Sponsor API Key. 2. **Dynamic Environment ID**: This key connects your application to Dynamic's wallet-as-a-service infrastructure. * Sign up at the **[Dynamic Dashboard](https://www.dynamic.xyz/) **. * Create a new project and copy your Environment ID. #### Step 3: Define Constants and ABIs[](https://docs.morpho.org/build/borrow/guides/gelato/#step-3-define-constants-and-abis) For a clean implementation, define your contract addresses, ABIs, and market parameters in a separate constants file. Copy `// constants.ts import { base, arbitrum, optimism, polygon, scroll } from "viem/chains"; // 1. Supported Networks export const SUPPORTED_NETWORKS = { [base.id]: base, [arbitrum.id]: arbitrum, [optimism.id]: optimism, [polygon.id]: polygon, [scroll.id]: scroll, }; // 2. Contract Addresses (Example for Base Mainnet) export const MORPHO_BLUE_ADDRESS = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"; export const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; // Note: Use the correct USDC address for your network export const CBBTC_ADDRESS = "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"; // Note: Use the correct cbBTC address for your network // 3. Morpho Market Parameters (Example for cbBTC/USDC market) // NOTE: For a production app, fetch these dynamically. See the "Get Data" tutorials. export const CBBTC_USDC_MARKET_PARAMS = { loanToken: USDC_ADDRESS, collateralToken: CBBTC_ADDRESS, oracle: "0x...", // The specific oracle for this market irm: "0x...", // The specific IRM for this market lltv: BigInt("860000000000000000"), // 86% }; // 4. Minimal ABI fragments export const ERC20_ABI = [ { "inputs": [{"name":"spender","type":"address"}, {"name":"amount","type":"uint256"}], "name": "approve", "outputs": [{"name":"","type":"bool"}], "stateMutability": "nonpayable", "type": "function", }, ]; export const MORPHO_BLUE_ABI = [ // supplyCollateral, borrow, repay etc. // NOTE: A more complete ABI is needed. See official Morpho resources. ];` #### Step 4: Configure the Context Provider[](https://docs.morpho.org/build/borrow/guides/gelato/#step-4-configure-the-context-provider) Wrap your application's root with the `GelatoSmartWalletContextProvider` and `QueryClientProvider`. This makes the smart wallet client and user session available throughout your component tree. Copy `// In your main App.tsx or a layout component import { GelatoSmartWalletContextProvider } from "@gelatonetwork/smartwallet"; import { dynamic } from "@gelatonetwork/smartwallet/adapters"; import { wagmi } from "@gelatonetwork/smartwallet/networks"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { http } from "viem"; import { SUPPORTED_NETWORKS } from "./constants"; const queryClient = new QueryClient(); const chains = Object.values(SUPPORTED_NETWORKS); const transports = chains.reduce((acc, chain) => { acc[chain.id] = http(); return acc; }, {} as Record>); const App = ({ children }: { children: React.ReactNode }) => { return ( {children} ); };` * * * ### Part 2: Building a Complete Lending Component[](https://docs.morpho.org/build/borrow/guides/gelato/#part-2-building-a-complete-lending-component) Now, let's build a complete React component that handles user authentication and the core borrow functionality. Copy ``// components/MorphoLendingComponent.tsx import React, { useState } from "react"; import { useGelatoSmartWalletProviderContext } from "@gelatonetwork/smartwallet"; import { encodeFunctionData, parseUnits } from "viem"; import { sponsored } from "@gelatonetwork/smartwallet"; // Import constants and ABIs from your constants file import { CBBTC_ADDRESS, USDC_ADDRESS, MORPHO_BLUE_ADDRESS, CBBTC_USDC_MARKET_PARAMS, ERC20_ABI, MORPHO_BLUE_ABI, } from "../constants"; const GELATO_API_KEY = process.env.NEXT_PUBLIC_GELATO_API_KEY as string; export const MorphoLendingComponent = () => { const [borrowAmount, setBorrowAmount] = useState(""); const [collateralAmount, setCollateralAmount] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [txHash, setTxHash] = useState(null); const { client: smartWalletClient, smartWallet, connect, disconnect, isConnected, } = useGelatoSmartWalletProviderContext(); const handleBorrow = async () => { if (!smartWalletClient || !smartWallet || !borrowAmount || !collateralAmount) return; setLoading(true); setError(null); setTxHash(null); try { const parsedCollateral = parseUnits(collateralAmount, 8); // cbBTC has 8 decimals const parsedBorrow = parseUnits(borrowAmount, 6); // USDC has 6 decimals const calls = [ // 1. Approve Morpho to spend the collateral { to: CBBTC_ADDRESS as `0x${string}`, data: encodeFunctionData({ abi: ERC20_ABI, functionName: "approve", args: [MORPHO_BLUE_ADDRESS, parsedCollateral], }), }, // 2. Supply collateral to the market { to: MORPHO_BLUE_ADDRESS as `0x${string}`, data: encodeFunctionData({ abi: MORPHO_BLUE_ABI, functionName: "supplyCollateral", args: [CBBTC_USDC_MARKET_PARAMS, parsedCollateral, smartWallet.address, "0x"], }), }, // 3. Borrow the loan asset { to: MORPHO_BLUE_ADDRESS as `0x${string}`, data: encodeFunctionData({ abi: MORPHO_BLUE_ABI, functionName: "borrow", args: [ CBBTC_USDC_MARKET_PARAMS, parsedBorrow, BigInt(0), // shares smartWallet.address, // receiver smartWallet.address, // onBehalf ], }), }, ]; // Execute the bundled, sponsored transaction const response = await smartWalletClient.execute({ payment: sponsored(GELATO_API_KEY), calls, }); const receipt = await response.wait(); setTxHash(receipt.id); } catch (e: any) { console.error("Borrow failed:", e); setError(e.message || "An unknown error occurred."); } finally { setLoading(false); } }; // UI Rendering if (!isConnected) { return ; } return (

Borrow USDC with cbBTC Collateral

setCollateralAmount(e.target.value)} disabled={loading} /> setBorrowAmount(e.target.value)} disabled={loading} /> {txHash &&

Success! Transaction: {txHash}

} {error &&

Error: {error}

}
); };`` * * * ### Part 3: Production Considerations[](https://docs.morpho.org/build/borrow/guides/gelato/#part-3-production-considerations) #### Security Best Practices[](https://docs.morpho.org/build/borrow/guides/gelato/#security-best-practices) * **Key Management**: Never expose private keys or API keys in client-side code. Use secure environment variables. * **Input Validation**: Always validate and sanitize user inputs before constructing transactions to prevent injection attacks. * **Slippage Protection**: For production applications, especially those involving swaps, it is crucial to implement slippage protection. The Gelato SDK can be combined with DEX aggregators that handle this. * **Dependency Management**: Keep all SDKs and libraries updated to their latest stable versions to benefit from security patches. #### Common Issues & Troubleshooting[](https://docs.morpho.org/build/borrow/guides/gelato/#common-issues--troubleshooting) | Issue | Solution | | --- | --- | | **Transaction fails silently** | Check the browser console for detailed error messages. Common causes include incorrect contract addresses or ABI definitions. | | **"Insufficient Allowance"** | Ensure the `approve` call is included in your bundle and the amount is sufficient. | | **"Provider Not Found"** | Verify that `GelatoSmartWalletContextProvider` correctly wraps your entire application or component tree. | | **Gas Estimation Fails** | This often points to an onchain error. Ensure the user's smart wallet is funded (if not sponsored) or that the contract logic is sound. | Key Resources & Next Steps[](https://docs.morpho.org/build/borrow/guides/gelato/#key-resources--next-steps) -------------------------------------------------------------------------------------------------------------- You now have the building blocks to integrate a powerful, abstracted lending experience. To learn more, explore these resources: [### Live Demo\ \ Try the complete user flow in the official Morpho x Gelato demo application.\ \ View Demo →](https://morpho-aa.demo.gelato.cloud/) [### Gelato Smart Wallet SDK Docs\ \ Dive deeper into the Gelato SDK's features, including different account types and payment options.\ \ Read Docs →](https://docs.gelato.cloud/Smart-Wallets/React-SDK/Overview) [### Morpho Borrow Concepts\ \ Understand the core concepts of Morpho Markets, including LTV, health factor, and liquidations.\ \ Learn More →](https://docs.morpho.org/build/borrow/get-started) [### Community Support\ \ Join the Morpho Discord to ask questions and get help from the community and core contributors.\ \ Join Discord →](https://discord.morpho.org/) --- # Create a Rewards Program – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/tutorials/create-program#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Tutorials On this page Chevron Right This tutorial guides you through creating a new rewards program for Morpho Vaults or Markets using **Merkl**, the current standard for reward distribution. Prerequisites[](https://docs.morpho.org/build/rewards/tutorials/create-program#prerequisites) ------------------------------------------------------------------------------------------------ Before creating a rewards program, ensure you have: * [ ] A clear incentive strategy (what behavior do you want to encourage?) * [ ] Reward tokens ready for distribution * [ ] Knowledge of target Morpho Markets or Vaults * [ ] A wallet with funds to deposit reward tokens * [ ] Understanding of [Reward Program Types](https://docs.morpho.org/build/rewards/concepts/reward-campaigns) Overview: Merkl for Rewards Programs[](https://docs.morpho.org/build/rewards/tutorials/create-program#overview-merkl-for-rewards-programs) --------------------------------------------------------------------------------------------------------------------------------------------- [Merkl](https://merkl.xyz/) is the standard distribution system for Morpho rewards. It provides: * **Automated Distribution**: Rewards calculated and distributed every 8 hours * **Flexible Configuration**: Target specific markets, vaults, or user groups * **Multi-Chain Support**: Works across all chains where Morpho is deployed * **Transparent Tracking**: Real-time visibility into reward distribution Creating a Program via Merkl[](https://docs.morpho.org/build/rewards/tutorials/create-program#creating-a-program-via-merkl) ------------------------------------------------------------------------------------------------------------------------------ Merkl provides a user-friendly interface for creating reward campaigns. The process differs slightly between Vault and Market programs. #### Jump on the studio[](https://docs.morpho.org/build/rewards/tutorials/create-program#jump-on-the-studio) [https://studio.merkl.xyz/create-campaign/lend](https://studio.merkl.xyz/create-campaign/lend) #### Select `Morpho` as protocol[](https://docs.morpho.org/build/rewards/tutorials/create-program#select-morpho-as-protocol) ![Merkl Studio](https://docs.morpho.org/img/build/rewards/merkl-studio.png) #### Fill the inputs as per Merkl doc[](https://docs.morpho.org/build/rewards/tutorials/create-program#fill-the-inputs-as-per-merkl-doc) Next Steps[](https://docs.morpho.org/build/rewards/tutorials/create-program#next-steps) ------------------------------------------------------------------------------------------ * **Fetch campaign data**: Follow the [Fetch Rewards Data tutorial](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data) * **Integrate display**: Check out the [Integrate Display tutorial](https://docs.morpho.org/build/rewards/tutorials/integrate-display) * **Enable claiming**: See the [Claim Rewards tutorial](https://docs.morpho.org/build/rewards/tutorials/claim-rewards) --- # Combining Actions – Morpho Docs [Skip to content](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Combining Actions On this page Chevron Right Using Solidity[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#using-solidity) --------------------------------------------------------------------------------------------------- Feel free to refer to the [testing suite](https://github.com/morpho-org/bundler3/blob/main/test/ERC4626AdapterLocalTest.sol) Using SDK Encoding Library[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#using-sdk-encoding-library) --------------------------------------------------------------------------------------------------------------------------- The `BundlerAction` module from `@morpho-org/bundler-sdk-viem` provides a comprehensive set of utility functions for encoding various actions that can be bundled together in a single transaction. This tutorial covers the main functions and provides examples of how to use them. ### Installation[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#installation) First, install the package in your project, use [viem](https://viem.sh/) or [ethers](https://docs.ethers.org/v6/) depending on your preference. yarnnpm Terminal yarn Copy `yarn add @morpho-org/bundler-sdk-viem` ### Importing BundlerAction[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#importing-bundleraction) Import the `BundlerAction` module in your TypeScript or JavaScript file: viem Copy `import { BundlerAction } from "@morpho-org/bundler-sdk-viem";` ### Add Available Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#add-available-actions) #### ERC20 and Native Token Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#erc20-and-native-token-actions) 1. **nativeTransfer**: Transfer native tokens (e.g. ETH, MATIC) 2. **erc20Transfer**: Transfer ERC20 tokens 3. **erc20TransferFrom**: Transfer ERC20 tokens from sender to the Bundler Example: Copy `const recipient = "0x1234..."; const amount = 1000000000000000000n; // 1 ETH const nativeTransferAction = BundlerAction.nativeTransfer(recipient, amount); const tokenAddress = "0x5678..."; const erc20TransferAction = BundlerAction.erc20Transfer( tokenAddress, recipient, amount );` #### Permit and Permit2 Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#permit-and-permit2-actions) 1. **permit**: Permit an ERC20 token 2. **permitDai**: Permit DAI token 3. **approve2**: Approve using Permit2 4. **transferFrom2**: Transfer tokens using Permit2 Example: Copy `import { Signature } from "viem"; const permitSingle = { details: { token: "0x1234...", amount: 1000000000n, nonce: 0n, expiration: 2n ** 48n - 1, }, spender: bundlerAddress, sigDeadline: 2n ** 48n - 1, }; const signature = Signature.from("0xabcdef..."); const approveAction = BundlerAction.approve2(permitSingle, signature, false);` #### Morpho Markets Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#morpho-markets-actions) 1. **morphoSetAuthorizationWithSig**: Authorize an account on Morpho 2. **morphoSupply**: Supply assets to a Morpho market 3. **morphoSupplyCollateral**: Supply collateral to a Morpho market 4. **morphoBorrow**: Borrow from a Morpho market 5. **morphoRepay**: Repay a Morpho loan 6. **morphoWithdraw**: Withdraw supplied assets from Morpho 7. **morphoWithdrawCollateral**: Withdraw supplied collateral from Morpho 8. **morphoFlashLoan**: Execute a flash loan on Morpho 9. **metaMorphoReallocateTo**: Trigger a public reallocation on the PublicAllocator Example: Copy `const marketParams = { collateralToken: "0x1234...", loanToken: "0x5678...", irm: "0xABCD...", oracle: "0xEFGH...", lltv: 860000000000000000n, // 86% LLTV }; const borrowAmount = 100000000n; // 100 USDC (6 decimals) const borrower = "0x9876..."; const slippageAmount = 99500000n; // 99.50 USDC, minimum amount of assets to borrow const borrowAction = BundlerAction.morphoBorrow( marketParams, borrowAmount, 0n, slippageAmount, borrower );` #### Morpho Vaults (ERC4626) Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#morpho-vaults-erc4626-actions) 1. **erc4626Mint**: Mint shares of an ERC4626 vault 2. **erc4626Deposit**: Deposit assets into an ERC4626 vault 3. **erc4626Withdraw**: Withdraw assets from an ERC4626 vault 4. **erc4626Redeem**: Redeem shares from an ERC4626 vault Example: Copy `const vaultAddress = "0xABCD..."; const assets = 1000000000000000000n; // 1 token const minShares = 900000000000000000n; // 0.9 shares const receiver = "0xEFGH..."; const depositAction = BundlerAction.erc4626Deposit( vaultAddress, assets, minShares, receiver );` #### Universal Rewards Distributor Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#universal-rewards-distributor-actions) 1. **urdClaim**: Claim rewards from the Universal Rewards Distributor Example: Copy `const distributor = "0x1234..."; const account = "0x5678..."; const reward = "0xABCD..."; const amount = 1000000000000000000n; // 1 token const proof = ["0xabcd...", "0xdef..."]; const skipRevert = false; const claimAction = BundlerAction.urdClaim( distributor, account, reward, amount, proof, skipRevert );` #### Wrapped Native Token Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#wrapped-native-token-actions) 1. **wrapNative**: Wrap native tokens (e.g. ETH to WETH) 2. **unwrapNative**: Unwrap native tokens (e.g. WETH to ETH) Example: Copy `const wrapAmount = 1000000000000000000n; // 1 ETH const wrapAction = BundlerAction.wrapNative(wrapAmount);` #### stETH and wstETH Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#steth-and-wsteth-actions) 1. **stakeEth**: Stake ETH using Lido 2. **wrapStEth**: Wrap stETH to wstETH 3. **unwrapStEth**: Unwrap wstETH to stETH Example: Copy `const stakeAmount = 1000000000000000000n; // 1 ETH const minShares = 950000000000000000n; // 0.95 stETH const referral = "0x0000..."; const stakeAction = BundlerAction.stakeEth(stakeAmount, minShares, referral);` #### Protocol-Specific Migration Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#protocol-specific-migration-actions) These actions are available on specific migration bundler instances: * AaveV2: repay, withdraw * AaveV3: repay, withdraw * AaveV3 Optimizer: repay, withdraw, withdrawCollateral, approveManagerWithSig * CompoundV2: repay, redeem * CompoundV3: repay, withdrawFrom, allowBySig Example (AaveV3): Copy `const asset = "0x1234..."; const amount = 1000000000000000000n; // 1 token const rateMode = 2; // Variable rate const aaveV3RepayAction = BundlerAction.aaveV3Repay(asset, amount, rateMode);` ### Combining Actions[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#combining-actions-1) You can combine multiple actions into a single transaction using the `multicall` function of your bundler contract: Copy `await bundler .connect(signer) .multicall([ BundlerAction.wrapNative(1000000000000000000n), BundlerAction.erc20Transfer(wethAddress, recipient, 500000000000000000n), BundlerAction.morphoSupplyCollateral( marketParams, 500000000000000000n, borrower, "0x" ), BundlerAction.morphoBorrow( marketParams, 100000000n, 0n, slippageAmount, borrower ), ]);` This executes all the encoded actions in a single transaction, saving gas and simplifying complex operations. Slippage Considerations[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#slippage-considerations) --------------------------------------------------------------------------------------------------------------------- Several Bundler actions, particularly those involving Morpho and ERC4626 vaults, include slippage protection parameters. These parameters help protect users from unexpected price movements between transaction submission and execution. For example, `morphoSupply`, `morphoBorrow`, `morphoRepay`, `morphoWithdraw`, and other ERC4626 actions all include a `slippageAmount` or similar parameter. This value represents the minimum (for withdrawals/borrows) or maximum (for deposits/repayments) amount of assets or shares to be transferred, ensuring the transaction reverts if market conditions change unfavorably. When using these actions, carefully calculate and set appropriate slippage tolerances based on the asset's volatility and expected transaction time to balance between execution success and protection against adverse price movements. Best Practices[](https://docs.morpho.org/tools/onchain/bundlers/combine-actions/#best-practices) --------------------------------------------------------------------------------------------------- 1. Always use `bigint` for numeric values to avoid precision loss. 2. Double-check addresses and parameters before encoding actions. 3. Use descriptive variable names to improve code readability. 4. Leverage TypeScript for better type checking and autocomplete support. 5. Test your encoded actions thoroughly before deploying to mainnet. 6. Be aware of the specific bundler instances required for certain actions (e.g. protocol-specific migration actions). 7. Implement proper error handling and transaction confirmation in your application. 8. Consider gas optimization by ordering actions efficiently within your multicall. By mastering these `BundlerAction` functions, you can create complex, gas-efficient interactions with Morpho and various DeFi protocols in a streamlined manner. --- # Bundler Resources – Morpho Docs [Skip to content](https://docs.morpho.org/tools/onchain/bundlers/resources/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Bundler Resources On this page Chevron Right This page contains key resources, links, and contract information for Morpho Bundlers. | Resource | Link | Description | | --- | --- | --- | | **Official Contract Addresses** | **[/get-started/resources/addresses/#bundlers](https://docs.morpho.org/get-started/resources/addresses#bundlers)
** | Deployed addresses for the `Bundler3` contracts and adapters on all supported networks. | | **Contract Specifications** | **[/get-started/resources/contracts/bundlers/](https://docs.morpho.org/get-started/resources/contracts/bundlers)
** | Detailed specifications for the `Bundler3` contract and its adapters. | | **Bundler SDKs** | **[/tools/offchain/sdks/bundler-sdk-viem/](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem)
** | The recommended SDK for interacting with bundlers in a dApp. | | **GitHub Repository** | **[https://github.com/morpho-org/bundler3](https://github.com/morpho-org/bundler3)
** | The source code for the `Bundler3` smart contracts and adapters. | --- # Using LLMs – Morpho Docs [Skip to content](https://docs.morpho.org/tools/ai/llms/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Using LLMs On this page Chevron Right Morpho’s docs are LLM-friendly to help developers integrate with Morpho faster. Use the Morpho docs llms-full.txt file You can provide your code editor with a llms-full.txt file to use Morpho's docs as a context for your code. The following steps show how to do this for Cursor. #### Navigate to `Cursor Settings` > `Features` > `Docs`[](https://docs.morpho.org/tools/ai/llms/#navigate-to-cursor-settings--features--docs) #### Select “Add new doc” and paste the following URL:[](https://docs.morpho.org/tools/ai/llms/#select-add-new-doc-and-paste-the-following-url) Copy `https://docs.morpho.org/llms-full.txt` #### Use @docs -> Morpho to reference Morpho's docs in your code.[](https://docs.morpho.org/tools/ai/llms/#use-docs---morpho-to-reference-morphos-docs-in-your-code) --- # Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu On this page Chevron Right Introduction[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#introduction) ------------------------------------------------------------------------------------- The [**blue-sdk**](https://github.com/morpho-org/sdks/tree/main/packages/blue-sdk) is the core SDK in the Morpho Stack. It provides the foundational components necessary to interact with Morpho's offchain ecosystem. This SDK is framework-agnostic, making it versatile for various applications. Key features include: * Market configuration management * Market data manipulation * User position management * Token and vault interactions Installation[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#installation) ------------------------------------------------------------------------------------- First, install the necessary dependencies: Copy `yarn add @morpho-org/blue-sdk @morpho-org/morpho-ts` Setup[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#setup) ----------------------------------------------------------------------- Import the necessary modules and set up your environment: Copy `import { MarketParams, Market, AccrualPosition, Position, } from "@morpho-org/blue-sdk"; import { Time } from "@morpho-org/morpho-ts";` Basic Usage[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#basic-usage) ----------------------------------------------------------------------------------- Here's a script that demonstrates the basic usage of the [**blue-sdk**](https://github.com/morpho-org/sdks/tree/main/packages/blue-sdk) : Copy `// Create a new market configuration using MarketParams const config = new MarketParams({ loanToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH collateralToken: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", // wstETH oracle: "0x2a01EB9496094dA03c4E364Def50f5aD1280AD72", irm: "0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC", // AdaptiveCurveIrm lltv: 94_5000000000000000n, // 94.5% }); console.log("Market Config ID:", config.id); console.log("Liquidation Incentive Factor:", config.liquidationIncentiveFactor); // Create a new market with the specified configuration const market = new Market({ config, totalSupplyAssets: 1000_000000000000000000n, totalBorrowAssets: 920_000000000000000000n, totalSupplyShares: 1000_000000000000000000000000n, totalBorrowShares: 920_000000000000000000000000n, lastUpdate: 1721000000n, fee: 0n, price: 1_100000000000000000000000000000000000n, rateAtTarget: 94850992095n, }); console.log("Market Utilization:", market.utilization); console.log("Market Liquidity:", market.liquidity); console.log("Market APY at Target:", market.apyAtTarget); // Accrue interest to the latest timestamp const accruedMarket = market.accrueInterest(Time.timestamp()); // Convert supply shares to assets const shares = 1000000000000000000n; console.log("Supply Assets for Shares:", accruedMarket.toSupplyAssets(shares)); // Create a new position in the market const position = new AccrualPosition( new Position({ user: "0xCDB238D68d8Da74487711bC1F8f13f3d00667D1A", // Replace with actual user address marketId: market.id, supplyShares: 0n, borrowShares: 20_000000000000000000000000n, collateral: 27_000000000000000000n, }), market ); console.log("Borrow Assets:", position.borrowAssets); console.log("Is Position Healthy:", position.isHealthy); console.log("Max Borrowable Assets:", position.maxBorrowableAssets); // Accrue interest for the position to the latest timestamp const accruedPosition = position.accrueInterest(Time.timestamp()); console.log("Accrued Borrow Assets:", accruedPosition.borrowAssets);` Key Classes[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#key-classes) ----------------------------------------------------------------------------------- ### MarketParams[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#marketparams) Represents the immutable configuration of a market on Morpho. This class replaces the previous `MarketConfig` class and provides: * Market configuration parameters (loan token, collateral token, oracle, IRM, LLTV) * Computed properties like `liquidationIncentiveFactor` * Unique market identifier ### Market[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#market) Represents the state of a market on Morpho, including: * Total supply and borrow amounts * Utilization and liquidity metrics * Interest rate calculations * Share-to-asset conversions ### Position[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#position) Represents a user's position on a specific market, including: * Supply and borrow shares * Collateral amounts * Health factor calculations * Maximum borrowable asset calculations Advanced Usage[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#advanced-usage) ----------------------------------------------------------------------------------------- ### Integrating with Other SDKs[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#integrating-with-other-sdks) * Integrate with [blue-sdk-viem](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/-viem) for onchain interactions. ### Custom Address Registration[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#custom-address-registration) For testing or custom networks, you can register custom addresses: Copy `import { registerCustomAddresses } from "@morpho-org/blue-sdk"; registerCustomAddresses({ addresses: { 31337: { morpho: "0x123...", // ... other required addresses }, }, unwrappedTokens: { 31337: { "0xWrappedToken": "0xUnwrappedToken", }, }, });` ### Error Handling[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#error-handling) Always implement proper error handling and input validation in production code. ### Complex Scenarios[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#complex-scenarios) Explore more complex scenarios such as: * Multi-market interactions * Vault allocations * Token management Conclusion[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#conclusion) --------------------------------------------------------------------------------- This tutorial provides a comprehensive overview of how to use the [**blue-sdk**](https://github.com/morpho-org/sdks/tree/main/packages/blue-sdk) to interact with Morpho markets and positions. For more detailed information, refer to the official Morpho documentation. Full Code Example[](https://docs.morpho.org/tools/offchain/sdks/blue-sdk/#full-code-example) ----------------------------------------------------------------------------------------------- Copy `import { MarketParams, Market, AccrualPosition, Position, } from "@morpho-org/blue-sdk"; import { Time } from "@morpho-org/morpho-ts"; // Create a new market configuration using MarketParams const config = new MarketParams({ loanToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH collateralToken: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", // wstETH oracle: "0x2a01EB9496094dA03c4E364Def50f5aD1280AD72", irm: "0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC", // AdaptiveCurveIrm lltv: 94_5000000000000000n, // 94.5% }); console.log("Market Config ID:", config.id); console.log("Liquidation Incentive Factor:", config.liquidationIncentiveFactor); // Create a new market with the specified configuration const market = new Market({ params: config, totalSupplyAssets: 1000_000000000000000000n, totalBorrowAssets: 920_000000000000000000n, totalSupplyShares: 1000_000000000000000000000000n, totalBorrowShares: 920_000000000000000000000000n, lastUpdate: 1721000000n, fee: 0n, price: 1_100000000000000000000000000000000000n, rateAtTarget: 94850992095n, }); console.log("Market Utilization:", market.utilization); console.log("Market Liquidity:", market.liquidity); console.log("Market APY at Target:", market.apyAtTarget); // Accrue interest to the latest timestamp const accruedMarket = market.accrueInterest(Time.timestamp()); // Convert supply shares to assets const shares = 1000000000000000000n; console.log("Supply Assets for Shares:", accruedMarket.toSupplyAssets(shares)); // Create a new position in the market const position = new AccrualPosition( new Position({ user: "0xCDB238D68d8Da74487711bC1F8f13f3d00667D1A", // Replace with actual user address marketId: market.id, supplyShares: 0n, borrowShares: 20_000000000000000000000000n, collateral: 27_000000000000000000n, }), market ); console.log("Borrow Assets:", position.borrowAssets); console.log("Is Position Healthy:", position.isHealthy); console.log("Max Borrowable Assets:", position.maxBorrowableAssets); // Accrue interest for the position to the latest timestamp const accruedPosition = position.accrueInterest(Time.timestamp()); console.log("Accrued Borrow Assets:", accruedPosition.borrowAssets);` --- # Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu On this page Chevron Right Introduction[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#introduction) --------------------------------------------------------------------------------------------- The [bundler-sdk-viem](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem) enables atomic execution of complex DeFi operations on Morpho by bundling multiple actions into a single transaction. This eliminates the need for multiple approvals, reduces gas costs, and prevents intermediate state changes that could affect your position. **Prerequisites**: This guide assumes you have: * Working knowledge of [blue-sdk](https://docs.morpho.org/tools/offchain/sdks/blue-sdk) and [blue-sdk-viem](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem) * A configured [Viem client](https://viem.sh/docs/clients/intro) * Understanding of Morpho's market mechanics * Familiarity with TypeScript and async/await patterns **Important**: The bundler SDK requires deep understanding of Morpho's transaction flows. Study the [SDK tests](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem/test) and reference implementations before building production features. Architecture Overview[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#architecture-overview) --------------------------------------------------------------------------------------------------------------- The bundler transforms high-level user operations into optimized transaction bundles through three phases: 1. **Population**: Convert user operations into low-level bundler operations 2. **Finalization**: Optimize operations (merge duplicates, redirect tokens, add skims) 3. **Encoding**: Package operations into executable transactions with signature requirements Installation[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#installation) --------------------------------------------------------------------------------------------- Copy `yarn add @morpho-org/bundler-sdk-viem @morpho-org/blue-sdk @morpho-org/morpho-ts @morpho-org/simulation-sdk viem` Core Concepts[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#core-concepts) ----------------------------------------------------------------------------------------------- ### Operation Types[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#operation-types) The bundler supports three categories of operations: #### Blue Operations (No `address` field)[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#blue-operations-no-address-field) * `Blue_Supply` - Supply assets to a market * `Blue_Borrow` - Borrow assets from a market * `Blue_Repay` - Repay borrowed assets * `Blue_Withdraw` - Withdraw supplied assets * `Blue_SupplyCollateral` - Supply collateral * `Blue_WithdrawCollateral` - Withdraw collateral * `Blue_SetAuthorization` - Authorize an address * `Blue_FlashLoan` - Execute a flash loan **Critical**: Blue operations do not have an `address` field. They always operate on the Morpho contract address. #### MetaMorpho Operations (Have `address` field)[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#metamorpho-operations-have-address-field) * `MetaMorpho_Deposit` - Deposit into a vault * `MetaMorpho_Withdraw` - Withdraw from a vault * `MetaMorpho_PublicReallocate` - Trigger public reallocation #### ERC20 Operations (Have `address` field)[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#erc20-operations-have-address-field) * `Erc20_Approve` - Standard approval * `Erc20_Permit` - Gasless approval via signature * `Erc20_Permit2` - Uniswap Permit2 approval * `Erc20_Transfer` - Transfer tokens * `Erc20_Wrap` - Wrap tokens (e.g., ETH → WETH) * `Erc20_Unwrap` - Unwrap tokens (e.g., WETH → ETH) ### Type Guards[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#type-guards) Always use the correct type guards when processing operations: Copy `import { isBlueBundlerOperation, isMetaMorphoBundlerOperation, isErc20BundlerOperation, } from "@morpho-org/bundler-sdk-viem"; operations.forEach((operation) => { if (isBlueBundlerOperation(operation)) { // No address field - operates on Morpho contract if ("id" in operation.args) { const marketParams = MarketParams.get(operation.args.id); } } if (isMetaMorphoBundlerOperation(operation) || isErc20BundlerOperation(operation)) { // Has address field const { address } = operation; } });` ### SimulationState[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#simulationstate) `SimulationState` represents the complete protocol state at a specific block. It's required for: * Simulating operations before execution * Validating transaction feasibility * Calculating required approvals and transfers * Optimizing operation sequences **Getting SimulationState**: Reference production implementations like [compound-blue](https://github.com/papercliplabs/compound-blue/blob/main/src/actions/data/rpc/getSimulationState.ts) to understand proper state fetching patterns. Critical Security Practices[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#critical-security-practices) --------------------------------------------------------------------------------------------------------------------------- ### 1\. Never Approve Bundler 3[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#1-never-approve-bundler-3) **NEVER** set token approvals for Bundler 3 directly. This is a critical security risk. See the [official security notice](https://github.com/morpho-org/bundler3?tab=readme-ov-file#security-notice-on-approvals-to-bundler3) . The bundler SDK handles approvals correctly through Permit/Permit2 flows. ### 2\. Always Skim Residual Tokens[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#2-always-skim-residual-tokens) Every transaction involving tokens must include skim operations to return any residual tokens to the user. Failing to skim can result in: * Lost user funds trapped in adapters/bundler * Transaction surplus not returned to users * Poor user experience Copy `// Always skim both input and output tokens const skimOperations = [ { type: "Erc20_Transfer", sender: user, address: tokenAddress, args: { recipient: user, amount: MaxUint256, // Transfers all remaining balance } } ];` ### 3\. Handle Swap Surplus Correctly[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#3-handle-swap-surplus-correctly) When using DEX integrations (e.g., exact output swaps), you may receive more tokens than expected. Always skim **both**: * The token you sent * The token you received Example from production: Copy `// Skim shares back to user { type: "Erc20_Transfer", args: [vaultAddress, account.address, maxUint256, generalAdapter1, false] }, // Skim asset tokens back to user { type: "Erc20_Transfer", args: [vaultAsset.address, account.address, maxUint256, generalAdapter1, false] }` Key Functions[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#key-functions) ----------------------------------------------------------------------------------------------- ### populateBundle[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#populatebundle) Converts high-level user operations into a bundle of low-level operations by simulating each action. Copy `const { operations, steps } = populateBundle( inputOperations: InputBundlerOperation[], simulationState: SimulationState, bundlingOptions?: BundlingOptions );` **Returns**: * `operations`: Array of bundler operations to execute * `steps`: Simulation steps for debugging ### finalizeBundle[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#finalizebundle) Optimizes the operation bundle by merging duplicates, redirecting tokens, and adding necessary skims. Copy `const optimizedOperations = finalizeBundle( operations: BundlerOperation[], simulationState: SimulationState, receiverAddress: Address, unwrapTokens?: Set
, unwrapSlippage?: bigint );` **Key optimizations**: * Merges duplicate ERC20 approvals * Redirects token flows when possible * Adds skim operations for residual tokens * Handles token unwrapping with slippage protection ### encodeBundle[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#encodebundle) Packages optimized operations into an executable transaction with signature requirements. Copy `const bundle = encodeBundle( operations: BundlerOperation[], simulationState: SimulationState, supportsSignature?: boolean );` **Returns**: `ActionBundle` containing: * `tx()`: Function to get the main transaction * `requirements.signatures`: Permits/Permit2s to sign * `requirements.txs`: Prerequisite transactions (if any) Bundling Options[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#bundling-options) ----------------------------------------------------------------------------------------------------- Fine-tune bundler behavior with `BundlingOptions`: Copy `interface BundlingOptions { // Tokens to use simple permit (not Permit2) withSimplePermit?: Set
; // Enable public allocator for liquidity reallocation publicAllocatorOptions?: { enabled: boolean; supplyTargetUtilization?: Record; withdrawTargetUtilization?: Record; defaultSupplyTargetUtilization?: bigint; defaultWithdrawTargetUtilization?: bigint; }; // Custom function to handle required token amounts getRequirementOperations?: ( requiredTokenAmounts: Record ) => InputBundlerOperation[]; }` ### Public Allocator Example[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#public-allocator-example) The public allocator automatically reallocates vault liquidity when market utilization exceeds thresholds: Copy `const bundlingOptions: BundlingOptions = { publicAllocatorOptions: { enabled: true, supplyTargetUtilization: { [marketId]: 905000000000000000n, // 90.5% target for specific market }, defaultSupplyTargetUtilization: 900000000000000000n, // 90% default }, };` Production Implementation Pattern[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#production-implementation-pattern) --------------------------------------------------------------------------------------------------------------------------------------- Here's the recommended pattern for building bundler transactions: Copy ``import { type Account, WalletClient, zeroAddress } from "viem"; import { parseAccount } from "viem/accounts"; import { type Address, DEFAULT_SLIPPAGE_TOLERANCE, MarketId, MarketParams, UnknownMarketParamsError, getUnwrappedToken, } from "@morpho-org/blue-sdk"; import { type BundlingOptions, type InputBundlerOperation, encodeBundle, finalizeBundle, populateBundle, isBlueBundlerOperation, isMetaMorphoBundlerOperation, isErc20BundlerOperation, } from "@morpho-org/bundler-sdk-viem"; import "@morpho-org/blue-sdk-viem/lib/augment"; import { SimulationState } from "@morpho-org/simulation-sdk"; export const setupBundle = async ( client: WalletClient, startData: SimulationState, inputOperations: InputBundlerOperation[], { account: account_ = client.account, supportsSignature, unwrapTokens, unwrapSlippage, onBundleTx, ...options }: BundlingOptions & { account?: Address | Account; supportsSignature?: boolean; unwrapTokens?: Set
; unwrapSlippage?: bigint; onBundleTx?: (data: SimulationState) => Promise | void; } = {} ) => { if (!account_) throw new Error("Account is required"); const account = parseAccount(account_); // Phase 1: Populate bundle with simulated operations let { operations } = populateBundle(inputOperations, startData, { ...options, withSimplePermit: options?.withSimplePermit, publicAllocatorOptions: { enabled: true, ...options.publicAllocatorOptions, }, }); // Phase 2: Finalize bundle (optimize and add skims) operations = finalizeBundle( operations, startData, account.address, unwrapTokens, unwrapSlippage ); // Phase 3: Encode bundle for execution const bundle = encodeBundle(operations, startData, supportsSignature); // Log bundle composition (useful for debugging) console.log(`\nBundle: ${operations.length} operations`); const operationsByType = operations.reduce((acc, op) => { acc[op.type] = (acc[op.type] || 0) + 1; return acc; }, {} as Record); Object.entries(operationsByType).forEach(([type, count]) => { console.log(` ${type}: ${count}`); }); // Collect all tokens involved (for monitoring/analytics) const tokens = new Set
(); operations.forEach((operation) => { if (isBlueBundlerOperation(operation) && "id" in operation.args) { try { const marketParams = MarketParams.get(operation.args.id); if (marketParams.loanToken !== zeroAddress) tokens.add(marketParams.loanToken); if (marketParams.collateralToken !== zeroAddress) tokens.add(marketParams.collateralToken); } catch (error) { if (!(error instanceof UnknownMarketParamsError)) throw error; } } if (isMetaMorphoBundlerOperation(operation)) { const { address } = operation; tokens.add(address); const vault = startData.tryGetVault(address); if (vault) tokens.add(vault.asset); } if (isErc20BundlerOperation(operation)) { const { address } = operation; tokens.add(address); const unwrapped = getUnwrappedToken(address, startData.chainId); if (unwrapped != null) tokens.add(unwrapped); } }); console.log(`Tokens: ${tokens.size} unique`); // Callback before signing (for UI updates) await onBundleTx?.(startData); // Sign required permits/permit2s if (bundle.requirements.signatures.length > 0) { console.log(`\nSignatures required: ${bundle.requirements.signatures.length}`); await Promise.all( bundle.requirements.signatures.map((requirement) => requirement.sign(client, account) ) ); } // Execute all transactions (prerequisites + main bundle) const txs = bundle.requirements.txs.map(({ tx }) => tx).concat([bundle.tx()]); const txHashes: `0x${string}`[] = []; for (let i = 0; i < txs.length; i++) { const tx = txs[i]; const isMainBundle = i === txs.length - 1; console.log(`\nTx ${i + 1}/${txs.length} ${isMainBundle ? '[Bundle]' : '[Prerequisite]'}`); const hash = await client.sendTransaction({ ...tx, account } as any); txHashes.push(hash); console.log(` Hash: ${hash}`); } console.log("\nAll transactions submitted"); return { operations, bundle, txHashes }; };`` Common Patterns[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#common-patterns) --------------------------------------------------------------------------------------------------- ### Supply + Supply Collateral + Borrow[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#supply--supply-collateral--borrow) Copy `export const supplySupplyCollateralBorrow = async ( marketId: MarketId, client: WalletClient, simulationState: SimulationState, amountSupply: bigint, amountSupplyCollateral: bigint, amountBorrow: bigint ) => { const user = client.account?.address; if (!user) throw new Error("User address is required"); return setupBundle(client, simulationState, [ { type: "Blue_Supply", sender: user, args: { id: marketId, assets: amountSupply, onBehalf: user, slippage: DEFAULT_SLIPPAGE_TOLERANCE, }, }, { type: "Blue_SupplyCollateral", sender: user, args: { id: marketId, assets: amountSupplyCollateral, onBehalf: user, }, }, { type: "Blue_Borrow", sender: user, args: { id: marketId, assets: amountBorrow, onBehalf: user, receiver: user, slippage: DEFAULT_SLIPPAGE_TOLERANCE, }, }, ]); };` Error Handling[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#error-handling) ------------------------------------------------------------------------------------------------- Always wrap bundler operations in comprehensive error handling: Copy ``try { const result = await setupBundle(client, simulationState, operations); // Monitor transaction confirmations for (const hash of result.txHashes) { const receipt = await client.waitForTransactionReceipt({ hash }); if (receipt.status !== 'success') { throw new Error(`Transaction failed: ${hash}`); } } return result; } catch (error) { console.error("Bundle execution failed"); console.error(` Market: ${marketId}`); console.error(` Error: ${error instanceof Error ? error.message : 'Unknown error'}`); // Log operation details for debugging if (operations.length > 0) { console.error(` Operations: ${operations.map(op => op.type).join(', ')}`); } throw error; }`` Browser Compatibility Warning[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#browser-compatibility-warning) ------------------------------------------------------------------------------------------------------------------------------- Some browsers (notably Opera) perform aggressive optimizations that reduce API calls and data fetching. This can cause: * Stale data being used in transactions * Missing real-time price updates * Transaction failures due to outdated state **Mitigation strategies**: * Add data staleness checks before transaction execution * Implement fallback data fetching for critical operations * Consider blocking certain browsers for high-value transactions * Add explicit "refresh data" options in UI Reference Implementations[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#reference-implementations) ----------------------------------------------------------------------------------------------------------------------- Study these production implementations to understand real-world patterns: ### compound-blue by Paperclip Labs[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#compound-blue-by-paperclip-labs) * [Repository](https://github.com/papercliplabs/compound-blue) * Demonstrates explicit transaction building * Clean deposit/withdraw/supply/borrow flows * Good example of simulation state management: [getSimulationState.ts](https://github.com/papercliplabs/compound-blue/blob/main/src/actions/data/rpc/getSimulationState.ts) ### SDK Tests[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#sdk-tests) * [bundler-sdk-viem tests](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem/test) * Comprehensive coverage of all operation types * Edge case handling examples * Not documented elsewhere but extremely valuable Performance Optimization[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#performance-optimization) --------------------------------------------------------------------------------------------------------------------- ### Caching with Apollo/GraphQL[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#caching-with-apollographql) Use Morpho's SDK cache policies for efficient data fetching: Copy `import { typePolicies } from "@morpho-org/blue-api-sdk"; import { InMemoryCache } from "@apollo/client"; export const inMemoryCache = new InMemoryCache({ typePolicies });` The SDK provides pre-configured cache transformations and merge functions. Reference: [blue-api-sdk](https://github.com/morpho-org/sdks/tree/main/packages/blue-api-sdk) ### SDK Utility Functions[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#sdk-utility-functions) Leverage built-in helpers instead of building from scratch: * Direct price fetching * Rate calculations * Offchain price computations * Market data aggregation These utilities significantly accelerate development and ensure consistency with the protocol. Complete Working Example[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#complete-working-example) --------------------------------------------------------------------------------------------------------------------- Copy ``import { type Account, WalletClient, zeroAddress } from "viem"; import { parseAccount } from "viem/accounts"; import { type Address, DEFAULT_SLIPPAGE_TOLERANCE, MarketId, MarketParams, UnknownMarketParamsError, getUnwrappedToken, } from "@morpho-org/blue-sdk"; import { type BundlingOptions, type InputBundlerOperation, encodeBundle, finalizeBundle, populateBundle, isBlueBundlerOperation, isMetaMorphoBundlerOperation, isErc20BundlerOperation, } from "@morpho-org/bundler-sdk-viem"; import "@morpho-org/blue-sdk-viem/lib/augment"; import { SimulationState } from "@morpho-org/simulation-sdk"; /** * Core bundle setup function * Handles the complete lifecycle: populate → finalize → encode → sign → execute */ export const setupBundle = async ( client: WalletClient, startData: SimulationState, inputOperations: InputBundlerOperation[], { account: account_ = client.account, supportsSignature, unwrapTokens, unwrapSlippage, onBundleTx, ...options }: BundlingOptions & { account?: Address | Account; supportsSignature?: boolean; unwrapTokens?: Set
; unwrapSlippage?: bigint; onBundleTx?: (data: SimulationState) => Promise | void; } = {} ) => { if (!account_) throw new Error("Account is required"); const account = parseAccount(account_); // Phase 1: Populate bundle with simulated operations let { operations } = populateBundle(inputOperations, startData, { ...options, withSimplePermit: options?.withSimplePermit, publicAllocatorOptions: { enabled: true, ...options.publicAllocatorOptions, }, }); // Phase 2: Finalize bundle (optimize and add skims) operations = finalizeBundle( operations, startData, account.address, unwrapTokens, unwrapSlippage ); // Phase 3: Encode bundle for execution const bundle = encodeBundle(operations, startData, supportsSignature); // Log bundle composition console.log(`\nBundle: ${operations.length} operations`); const operationsByType = operations.reduce((acc, op) => { acc[op.type] = (acc[op.type] || 0) + 1; return acc; }, {} as Record); Object.entries(operationsByType).forEach(([type, count]) => { console.log(` ${type}: ${count}`); }); // Collect all involved tokens const tokens = new Set
(); operations.forEach((operation) => { if (isBlueBundlerOperation(operation) && "id" in operation.args) { try { const marketParams = MarketParams.get(operation.args.id); if (marketParams.loanToken !== zeroAddress) tokens.add(marketParams.loanToken); if (marketParams.collateralToken !== zeroAddress) tokens.add(marketParams.collateralToken); } catch (error) { if (!(error instanceof UnknownMarketParamsError)) throw error; } } if (isMetaMorphoBundlerOperation(operation)) { const { address } = operation; tokens.add(address); const vault = startData.tryGetVault(address); if (vault) tokens.add(vault.asset); } if (isErc20BundlerOperation(operation)) { const { address } = operation; tokens.add(address); const unwrapped = getUnwrappedToken(address, startData.chainId); if (unwrapped != null) tokens.add(unwrapped); } }); console.log(`Tokens: ${tokens.size} unique`); // Execute callback before signing await onBundleTx?.(startData); // Sign required permits/permit2s if (bundle.requirements.signatures.length > 0) { console.log(`\nSignatures required: ${bundle.requirements.signatures.length}`); bundle.requirements.signatures.forEach((req, i) => { console.log(` ${i + 1}. ${req.action.type}`); }); await Promise.all( bundle.requirements.signatures.map((requirement) => requirement.sign(client, account) ) ); } // Execute all transactions const txs = bundle.requirements.txs.map(({ tx }) => tx).concat([bundle.tx()]); const txHashes: `0x${string}`[] = []; for (let i = 0; i < txs.length; i++) { const tx = txs[i]; const isMainBundle = i === txs.length - 1; console.log(`\nTx ${i + 1}/${txs.length} ${isMainBundle ? '[Bundle]' : '[Prerequisite]'}`); console.log(` To: ${tx.to}`); if (tx.value && tx.value > 0n) { console.log(` Value: ${tx.value}`); } const hash = await client.sendTransaction({ ...tx, account } as any); txHashes.push(hash); console.log(` Hash: ${hash}`); } console.log("\nAll transactions submitted"); return { operations, bundle, txHashes }; }; /** * Example: Supply assets, supply collateral, and borrow in one transaction * This pattern is commonly used for opening leveraged positions */ export const supplySupplyCollateralBorrow = async ( marketId: MarketId, client: WalletClient, simulationState: SimulationState, amountSupply: bigint, amountSupplyCollateral: bigint, amountBorrow: bigint ) => { const user = client.account?.address; if (!user) throw new Error("User address is required"); console.log("\nOperation: Supply + SupplyCollateral + Borrow"); console.log(`Market: ${marketId}`); console.log(`User: ${user}`); console.log(`Amounts: ${amountSupply} (supply), ${amountSupplyCollateral} (collateral), ${amountBorrow} (borrow)`); return setupBundle(client, simulationState, [ { type: "Blue_Supply", sender: user, args: { id: marketId, assets: amountSupply, onBehalf: user, slippage: DEFAULT_SLIPPAGE_TOLERANCE, }, }, { type: "Blue_SupplyCollateral", sender: user, args: { id: marketId, assets: amountSupplyCollateral, onBehalf: user, }, }, { type: "Blue_Borrow", sender: user, args: { id: marketId, assets: amountBorrow, onBehalf: user, receiver: user, slippage: DEFAULT_SLIPPAGE_TOLERANCE, }, }, ]); }; /** * Example: Repay debt and withdraw collateral in one transaction * Useful for closing or reducing leveraged positions */ export const repayAndWithdrawCollateral = async ( marketId: MarketId, client: WalletClient, simulationState: SimulationState, repayAmount: bigint, withdrawCollateralAmount: bigint ) => { const user = client.account?.address; if (!user) throw new Error("User address is required"); console.log("\nOperation: Repay + WithdrawCollateral"); console.log(`Market: ${marketId}`); console.log(`Amounts: ${repayAmount} (repay), ${withdrawCollateralAmount} (withdraw collateral)`); return setupBundle(client, simulationState, [ { type: "Blue_Repay", sender: user, args: { id: marketId, assets: repayAmount, onBehalf: user, slippage: DEFAULT_SLIPPAGE_TOLERANCE, }, }, { type: "Blue_WithdrawCollateral", sender: user, args: { id: marketId, assets: withdrawCollateralAmount, onBehalf: user, receiver: user, }, }, ]); }; /** * Example usage with error handling and transaction monitoring */ export const executeBundle = async () => { try { // Fetch current simulation state // See: https://github.com/papercliplabs/compound-blue/blob/main/src/actions/data/rpc/getSimulationState.ts const simulationState = await getSimulationState(client); // Execute bundle const result = await supplySupplyCollateralBorrow( marketId, client, simulationState, parseUnits("1000", 18), // Supply 1000 tokens parseUnits("500", 18), // Supply 500 collateral parseUnits("200", 18) // Borrow 200 tokens ); console.log(`\nBundle execution initiated`); console.log(`Operations: ${result.operations.length}`); console.log(`Transactions: ${result.txHashes.length}`); // Wait for confirmations for (const hash of result.txHashes) { console.log(`\nWaiting for confirmation: ${hash}`); const receipt = await client.waitForTransactionReceipt({ hash }); if (receipt.status === 'success') { console.log(`✓ Transaction confirmed`); } else { throw new Error(`Transaction failed: ${hash}`); } } console.log("\n✓ All transactions confirmed successfully"); return result; } catch (error) { console.error("\n✗ Bundle execution failed"); console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`); throw error; } };`` Additional Resources[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#additional-resources) ------------------------------------------------------------------------------------------------------------- * [bundler-sdk-viem Repository](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem) * [SDK Tests](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem/test) * [compound-blue Implementation](https://github.com/papercliplabs/compound-blue) * [Bundler 3 Security Notice](https://github.com/morpho-org/bundler3?tab=readme-ov-file#security-notice-on-approvals-to-bundler3) Summary[](https://docs.morpho.org/tools/offchain/sdks/bundler-sdk-viem/#summary) ----------------------------------------------------------------------------------- The bundler-sdk-viem enables atomic execution of complex DeFi operations with: * **Explicit transaction construction** for transparency and safety * **Automatic optimization** of operations and gas costs * **Built-in security** through proper approval and skim handling * **Production-ready patterns** from reference implementations Master the fundamentals by studying SDK tests and reference implementations before building production features. Always skim residual tokens, never approve Bundler 3 directly, and handle edge cases explicitly. --- # Morpho Bundlers – Morpho Docs [Skip to content](https://docs.morpho.org/tools/onchain/bundlers/get-started/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Morpho Bundlers On this page Chevron Right Morpho Bundlers are powerful smart contracts that enable developers to combine multiple onchain actions into a single, atomic transaction. Instead of forcing users through a sequence of separate transactions (e.g., approve, wrap, supply, borrow), you can bundle them all into one click, creating a seamless and gas-efficient user experience. The bundler is the recommended way to build user-facing applications on Morpho. ![bundlers3 plot](https://docs.morpho.org/img/bundlers/bundler3-flow.png) Why Use Morpho Bundlers?[](https://docs.morpho.org/tools/onchain/bundlers/get-started/#why-use-morpho-bundlers) ------------------------------------------------------------------------------------------------------------------ * **Superior User Experience**: Abstract away the complexity of DeFi. Actions like leveraging a position or depositing into a vault become a single, intuitive step for the user. * **Gas Efficiency**: Combining multiple operations into one transaction significantly reduces the overall gas cost. * **Atomicity and Safety**: If any step in the bundled sequence fails, the entire transaction reverts. This prevents users from getting stuck in partial states (e.g., approved tokens but a failed deposit). * **Powerful Composability**: Combine actions across the Morpho ecosystem and even with external protocols like DEXs. Key Features & Capabilities[](https://docs.morpho.org/tools/onchain/bundlers/get-started/#key-features--capabilities) ------------------------------------------------------------------------------------------------------------------------ Bundlers can combine a wide array of actions, including: * **Token Management**: Approve ERC20 tokens (with `permit` or `permit2`), wrap/unwrap native tokens (e.g., ETH/WETH), and transfer tokens. * **Morpho Market Actions**: `supply`, `supplyCollateral`, `borrow`, `repay`, and `withdraw`. * **Morpho Vault Actions**: `deposit` and `withdraw` from any ERC4626-compliant vault. * **Public Allocator**: Trigger a `reallocateTo` call to move liquidity on-demand. * **Reward Claims**: Claim rewards from the Universal Rewards Distributor (URD). * **DEX Swaps**: Execute swaps through integrated DEX aggregators like ParaSwap. * **Protocol Migrations**: Move positions from other protocols like Aave or Compound to Morpho. Get Started[](https://docs.morpho.org/tools/onchain/bundlers/get-started/#get-started) ----------------------------------------------------------------------------------------- This section provides all the information you need to integrate bundlers. * **[How It Works](https://docs.morpho.org/tools/onchain/bundlers/how-it-works) **: Start here for a conceptual overview of the bundler's onchain and offchain architecture. * **[Tutorials](https://docs.morpho.org/tools/onchain/bundlers/app-integration) **: Follow our step-by-step guides to build, simulate, and execute bundled transactions in your application. The **App Integration** tutorial is the recommended path for most developers. * **[Resources](https://docs.morpho.org/tools/onchain/bundlers/resources) **: Find contract addresses, SDK links, and source code. Product-Specific Integration Guides[](https://docs.morpho.org/tools/onchain/bundlers/get-started/#product-specific-integration-guides) ----------------------------------------------------------------------------------------------------------------------------------------- See how bundlers are used to enhance the user experience for both of Morpho's core products: * **For Earn**: [Use Bundlers for Vaults Tutorial](https://docs.morpho.org/build/earn/tutorials/bundlers) * **For Borrow**: [Use Bundlers for Complex Borrows Tutorial](https://docs.morpho.org/build/borrow/tutorials/bundlers) --- # Borrow: Developer Resources – Morpho Docs [Skip to content](https://docs.morpho.org/build/borrow/resources/all#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Resources On this page Chevron Right This page is your central hub for all the tools, links, and data sources you need to build on Morpho's Borrow product (Morpho Markets). Onchain Data & Contracts[](https://docs.morpho.org/build/borrow/resources/all#onchain-data--contracts) --------------------------------------------------------------------------------------------------------- These resources are for interacting directly with the blockchain. * **Market Parameters**: Every Morpho Market is defined by 5 immutable parameters. The easiest way to fetch these for all markets is via the [Morpho API](https://docs.morpho.org/build/borrow/tutorials/get-data#get-data) . * **Contract Specifications**: For detailed function signatures, events, and errors, refer to the canonical contract specs: * [Morpho Core Contract](https://docs.morpho.org/get-started/resources/contracts/morpho) * [Public Allocator](https://docs.morpho.org/get-started/resources/contracts/public-allocator) * [Bundlers](https://docs.morpho.org/get-started/resources/contracts/bundlers) * **GitHub Repositories**: * [`morpho-blue`](https://github.com/morpho-org/morpho-blue) : The core protocol contracts. * [`public-allocator`](https://github.com/morpho-org/public-allocator) : The contract for just-in-time liquidity. * [`bundler3`](https://github.com/morpho-org/bundler3) : The latest multicall bundler for atomic transactions. Offchain Data & Tools[](https://docs.morpho.org/build/borrow/resources/all#offchain-data--tools) --------------------------------------------------------------------------------------------------- These tools provide easier access to onchain data for frontends, backends, and analytics. * **Morpho API (Recommended)**: The simplest way to fetch comprehensive data about markets, their states, APYs, and user positions. * **API Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql) * **Tutorial**: [Using the API for Markets](https://docs.morpho.org/build/borrow/tutorials/get-data#get-data) * **Morpho Subgraphs**: For developers who prefer querying via The Graph protocol. * **Tutorial**: [Using Subgraphs for Markets](https://docs.morpho.org/tools/offchain/subgraphs) * **SDKs**: A suite of TypeScript libraries to accelerate your development. * **`@morpho-org/blue-sdk`**: Core, framework-agnostic classes for entities like Markets. * **`@morpho-org/blue-sdk-viem`**: Adds Viem-based fetchers to the core SDK classes for easy onchain data retrieval. * **`@morpho-org/liquidity-sdk-viem`**: A specialized SDK to calculate available liquidity, including from the Public Allocator. * **`@morpho-org/bundler-sdk-viem`**: The essential tool for creating one-click borrow, repay, or leverage actions. * **Learn more**: [Introduction to Morpho SDKs](https://docs.morpho.org/tools/offchain/sdks/get-started) Code & Examples[](https://docs.morpho.org/build/borrow/resources/all#code--examples) --------------------------------------------------------------------------------------- * **Example Application**: The [`bundler-basic-app`](https://github.com/morpho-org/bundler-basic-app) is a minimal but complete example of a React application for executing complex borrow-side actions. * **Solidity Snippets**: The [`morpho-blue-snippets`](https://github.com/morpho-org/morpho-blue-snippets) repository contains simple, educational Solidity contracts for common market interactions. * **Liquidation Bots**: For advanced developers, the community has provided open-source liquidation bot examples. * **Learn more**: [Community Liquidations Resources](https://docs.morpho.org/tools/community/liquidations) --- # Morpho Apps – Morpho Docs [Skip to content](https://docs.morpho.org/curate/app-ecosystem/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Morpho Apps On this page Chevron Right This section details the critical applications developed by the Morpho Association for effective vault management and ecosystem participation. Each application serves specific functions in the curation workflow. Prime[](https://docs.morpho.org/curate/app-ecosystem/#prime) --------------------------------------------------------------- ### Curator App - [curator.morpho.org](https://curator.morpho.org/) [](https://docs.morpho.org/curate/app-ecosystem/#curator-app--curatormorphoorg) **Purpose:** Delivers specialized tools for vault curators to manage vault operations. **Key Features:** * Create and deploy new vaults * Manage market listings and parameters * Configure vault settings and permissions * Set allocation caps and strategies **Version:** Beta deployment with ongoing feature development **Implementation Note:** For actions not yet implemented in the Curator App, use direct interaction with vault contracts through verified sources such as Etherscan. Always verify contract addresses before interaction. Utility[](https://docs.morpho.org/curate/app-ecosystem/#utility) ------------------------------------------------------------------- ### Oracle Decoder - [oracles.morpho.dev](https://oracles.morpho.dev/oracle-decoder) [](https://docs.morpho.org/curate/app-ecosystem/#oracle-decoder--oraclesmorphodev) **Purpose:** Aid oracle configurations to ensure price feed accuracy and security. **Key Features:** * Decode oracle configurations * Verify price accuracy against reference sources * Test oracle configurations * Identify configuration issues **Version:** Production **Implementation Note:** Always verify oracle data configurations before deploying to production environments. Use this tool to: 1. Confirm correct asset pricing 2. Validate operational parameters 3. Test edge case scenarios ### Liquidation App - [liquidation.morpho.org](https://liquidation.morpho.org/) [](https://docs.morpho.org/curate/app-ecosystem/#liquidation-app--liquidationmorphoorg) **Purpose:** Provides manual liquidation capabilities for unhealthy positions. **Key Features:** * Identify liquidatable positions * Execute manual liquidations * Calculate liquidation profitability * Monitor position health metrics **Version:** Production and requires supplemental automation **Implementation Note:** Develop and deploy automated liquidation bots for production environments. The liquidation app serves primarily as a backup mechanism when bots fail or for testing purposes. Consumer[](https://docs.morpho.org/curate/app-ecosystem/#consumer) --------------------------------------------------------------------- ### Main App - [app.morpho.org](https://app.morpho.org/) [](https://docs.morpho.org/curate/app-ecosystem/#main-app--appmorphoorg) **Purpose:** Interface for both lenders interacting with Morpho vaults and Borrowers interacting with Morpho Markets. **Key Features:** * View all Morpho Markets & Morpho Vaults * Deposit, manage, and exit positions in Morpho Vaults * Enter, manage, and exit from borrow positions * Track vault performance metrics * Monitor position health and market statistics **Version: Production** ### Fallback App - [fallback.morpho.org/](https://fallback.morpho.org/) [](https://docs.morpho.org/curate/app-ecosystem/#fallback-app---fallbackmorphoorg) **Purpose:** Built for emergencies, this app prioritizes resilience over speed. This interface is for both lenders interacting with Morpho vaults and Borrowers interacting with Morpho Markets. **Key Features:** * View your Morpho Markets & Morpho Vaults positions * Exit positions from Morpho Vaults and Morpho Markets **Version: Production** External - Rewards[](https://docs.morpho.org/curate/app-ecosystem/#external---rewards) ----------------------------------------------------------------------------------------- Rewards on Morpho are distributed via the Merkl stack. One can create rewards programs, monitor rewards programs details at protocol level or for a specific user, and claim rewards via the Merkl app. This external application is provided by [Merkl](https://x.com/merkl_xyz) . The Morpho Association does not endorse or guarantee its functionality. Use at your own discretion. * [Merkl](https://app.merkl.xyz/?protocol=morpho&tokenType=all&sort=tvl-desc) --- # Complete Integration Example – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/guides/complete-integration#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Guides On this page Chevron Right This guide provides a complete, working reference implementation for integrating Morpho rewards (both Merkl and Legacy URD) into your application. We'll walk through the **Morpho + Merkl Integration Demo** repository, which demonstrates best practices for production-ready rewards integration. Repository Overview[](https://docs.morpho.org/build/rewards/guides/complete-integration#repository-overview) --------------------------------------------------------------------------------------------------------------- ### Tech Stack[](https://docs.morpho.org/build/rewards/guides/complete-integration#tech-stack) * **Next.js 15** - React framework * **TypeScript** - Type safety * **Morpho API** - GraphQL for vault/market data * **Merkl API** - REST API for Merkl rewards * **Morpho Rewards API** - REST API for URD rewards ### Project Structure[](https://docs.morpho.org/build/rewards/guides/complete-integration#project-structure) Copy `src/ ├── app/ # Next.js app router ├── components/ # React components │ ├── VaultMetricsPanel.tsx # Display vault APY + rewards │ ├── UserRewardsPanel.tsx # User claimable rewards │ ├── VaultRewardsDisplay.tsx # Rewards breakdown │ └── ClaimImplementationPanel.tsx # Claim code examples ├── hooks/ # React hooks │ ├── useVaultData.ts # Fetch vault data │ └── useClipboard.ts # Utility hook ├── lib/ # Core logic │ ├── api.ts # API clients │ ├── claiming.ts # Claim functions │ ├── simulation.ts # Transaction simulation │ └── helpers/ │ └── rewards.ts # Reward calculations └── types/ # TypeScript types └── index.ts` Key Concepts Demonstrated[](https://docs.morpho.org/build/rewards/guides/complete-integration#key-concepts-demonstrated) --------------------------------------------------------------------------------------------------------------------------- ### 1\. Combining Morpho and Merkl Data[](https://docs.morpho.org/build/rewards/guides/complete-integration#1-combining-morpho-and-merkl-data) The demo shows how to fetch and combine data from multiple sources to provide a complete picture: **File: `src/lib/api.ts`** Copy `export async function getVaultData(vaultAddress: string, chainId: number) { // Fetch from Morpho API const morphoData = await fetchMorphoVault(vaultAddress, chainId); // Extract rewards information const rewards = morphoData.vault.state.rewards.map((r) => ({ token: r.asset.symbol, apr: parseFloat(r.supplyApr), yearlySupplyTokens: r.yearlySupplyTokens, })); // Calculate combined APY const baseApy = parseFloat(morphoData.vault.state.apy); const rewardsApr = rewards.reduce((sum, r) => sum + r.apr, 0); return { vault: morphoData.vault, baseApy, rewardsApr, totalApy: baseApy + rewardsApr, rewards, }; }` ### 2\. Fetching User Rewards from Both Systems[](https://docs.morpho.org/build/rewards/guides/complete-integration#2-fetching-user-rewards-from-both-systems) **File: `src/lib/helpers/rewards.ts`** Copy `export async function getUserRewards(userAddress: string, chainId: number) { const [merklRewards, urdRewards] = await Promise.all([ fetchMerklUserRewards(userAddress, chainId), fetchURDUserRewards(userAddress), ]); return { merkl: merklRewards, urd: urdRewards, combined: combineRewardsByToken(merklRewards, urdRewards), }; } function combineRewardsByToken(merkl: Reward[], urd: Reward[]) { const combined = new Map(); for (const reward of [...merkl, ...urd]) { if (combined.has(reward.token)) { const existing = combined.get(reward.token)!; existing.amount += reward.amount; } else { combined.set(reward.token, { ...reward }); } } return Array.from(combined.values()); }` ### 3\. Implementing Claims[](https://docs.morpho.org/build/rewards/guides/complete-integration#3-implementing-claims) **File: `src/lib/claiming.ts`** The demo includes claim implementations for both systems: **Merkl Claim:** Copy ``export async function claimMerklRewards( userAddress: string, chainId: number, walletClient: WalletClient ) { // 1. Fetch claim data const claimData = await fetch( `https://api.merkl.xyz/v4/claim?user=${userAddress}&chainId=${chainId}` ).then((r) => r.json()); // 2. Execute claim transaction const hash = await walletClient.writeContract({ address: MERKL_DISTRIBUTOR_ADDRESS, abi: MERKL_ABI, functionName: "claim", args: [ claimData.user, claimData.tokens, claimData.amounts, claimData.proofs, ], }); // 3. Wait for confirmation return await walletClient.waitForTransactionReceipt({ hash }); }`` **URD Claim:** Copy ``export async function claimURDRewards( userAddress: string, walletClient: WalletClient ) { // 1. Fetch all distributions const distributions = await fetch( `https://rewards.morpho.org/v1/users/${userAddress}/distributions` ).then((r) => r.json()); const results = []; // 2. Claim each distribution for (const dist of distributions) { // Check if already claimed const claimed = await checkClaimedAmount( dist.distributor, userAddress, dist.asset.address ); if (BigInt(claimed) >= BigInt(dist.claimable)) { continue; // Nothing to claim } // Execute claim using pre-formatted tx_data const hash = await walletClient.sendTransaction({ to: dist.distributor, data: dist.tx_data, }); const receipt = await walletClient.waitForTransactionReceipt({ hash }); results.push({ distribution: dist, receipt }); } return results; }`` ### 4\. React Components for Display[](https://docs.morpho.org/build/rewards/guides/complete-integration#4-react-components-for-display) **File: `src/components/VaultMetricsPanel.tsx`** Copy `export function VaultMetricsPanel({ vaultAddress, chainId }) { const { data, loading, error } = useVaultData(vaultAddress, chainId); if (loading) return ; if (error) return ; return (
{/* Vault Header */}

{data.vault.name}

{data.vault.symbol}

{/* APY Display */}
Total APY {data.totalApy.toFixed(2)}%
Base APY: {data.baseApy.toFixed(2)}%
{data.rewardsApr > 0 && (
Rewards: +{data.rewardsApr.toFixed(2)}%
)}
{/* Rewards List */} {data.rewards.length > 0 && ( )}
); }` **File: `src/components/UserRewardsPanel.tsx`** Copy `export function UserRewardsPanel({ userAddress, chainId }) { const [rewards, setRewards] = useState(null); const [claiming, setClaiming] = useState(false); useEffect(() => { getUserRewards(userAddress, chainId).then(setRewards); }, [userAddress, chainId]); const handleClaimAll = async () => { setClaiming(true); try { // Claim from both systems await Promise.all([ claimMerklRewards(userAddress, chainId, walletClient), claimURDRewards(userAddress, walletClient), ]); alert("Rewards claimed successfully!"); // Refresh rewards data getUserRewards(userAddress, chainId).then(setRewards); } catch (error) { console.error("Claim failed:", error); alert("Claim failed. See console for details."); } finally { setClaiming(false); } }; return (

Your Claimable Rewards

{rewards?.combined.map((reward) => (
{reward.token} {formatAmount(reward.amount)} {reward.token}
))} {/* Show source breakdown */}
View breakdown
Merkl: {rewards?.merkl.length || 0} rewards
URD: {rewards?.urd.length || 0} rewards
); }` Running the Demo[](https://docs.morpho.org/build/rewards/guides/complete-integration#running-the-demo) --------------------------------------------------------------------------------------------------------- ### Prerequisites[](https://docs.morpho.org/build/rewards/guides/complete-integration#prerequisites) * Node.js 18+ and yarn * A wallet with Morpho positions (for testing user rewards) ### Quick Start[](https://docs.morpho.org/build/rewards/guides/complete-integration#quick-start) Copy `# Clone the repository git clone https://github.com/morpho-org/merkl-morpho-recipe.git cd merkl-morpho-recipe # Install dependencies yarn install # Run the development server yarn dev # Open http://localhost:3000` ### Explore via Scripts[](https://docs.morpho.org/build/rewards/guides/complete-integration#explore-via-scripts) The demo includes standalone scripts to understand the data flow: Copy `# See vault APY + rewards calculation yarn demo:yield # Check user claimable rewards yarn demo:rewards # Complete integration flow yarn demo:full` **Example Output:** Copy `$ yarn demo:yield === Vault Metrics === Vault: Steakhouse USDC Base APY: 8.45% Rewards APR: 2.13% Total APY: 10.58% Reward Programs: - MORPHO: 1.85% APR - STEAK: 0.28% APR` Key Takeaways from the Demo[](https://docs.morpho.org/build/rewards/guides/complete-integration#key-takeaways-from-the-demo) ------------------------------------------------------------------------------------------------------------------------------- ### 1\. Error Handling[](https://docs.morpho.org/build/rewards/guides/complete-integration#1-error-handling) The demo implements graceful error handling: Copy `try { const data = await fetchVaultData(address, chain); return data; } catch (error) { console.error("Failed to fetch vault data:", error); return null; // Fallback to null, don't crash the app }` ### 2\. Type Safety[](https://docs.morpho.org/build/rewards/guides/complete-integration#2-type-safety) Full TypeScript coverage ensures correctness: Copy `export interface VaultReward { token: string; apr: number; yearlySupplyTokens: string; tokenAddress: string; } export interface UserClaimableReward { token: string; amount: bigint; source: "merkl" | "urd"; }` ### 3\. Caching Strategy[](https://docs.morpho.org/build/rewards/guides/complete-integration#3-caching-strategy) Copy `const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes const cache = new Map(); export function getCached( key: string, fetcher: () => Promise ): Promise { const cached = cache.get(key); if (cached && Date.now() - cached.timestamp < CACHE_DURATION) { return Promise.resolve(cached.data); } return fetcher().then((data) => { cache.set(key, { data, timestamp: Date.now() }); return data; }); }` ### 4\. Simulation Before Execution[](https://docs.morpho.org/build/rewards/guides/complete-integration#4-simulation-before-execution) Copy `// File: src/lib/simulation.ts export async function simulateClaimTransaction( distributorAddress: string, txData: string, userAddress: string ) { const publicClient = createPublicClient({ chain: mainnet, transport: http(), }); try { await publicClient.call({ to: distributorAddress, data: txData, from: userAddress, }); return { success: true }; } catch (error) { return { success: false, error }; } }` Adapting the Demo for Production[](https://docs.morpho.org/build/rewards/guides/complete-integration#adapting-the-demo-for-production) ----------------------------------------------------------------------------------------------------------------------------------------- When building on this demo for production, consider: ### Security[](https://docs.morpho.org/build/rewards/guides/complete-integration#security) * **Never expose private keys**: Use secure wallet connection libraries (RainbowKit, Wagmi, etc.) * **Validate all inputs**: Sanitize user addresses, vault addresses, chain IDs * **Handle transaction failures**: Implement retry logic with exponential backoff * **Rate limiting**: Respect API rate limits and implement client-side throttling ### Performance[](https://docs.morpho.org/build/rewards/guides/complete-integration#performance) * **Lazy load components**: Use React.lazy for routes * **Optimize bundle size**: Code split by route and feature * **Implement pagination**: For users with many rewards * **Use a state management solution**: Redux, Zustand, or React Query for complex state ### User Experience[](https://docs.morpho.org/build/rewards/guides/complete-integration#user-experience) * **Transaction notifications**: Toast notifications for claim status * **Transaction history**: Show past claims * **Gas estimation**: Display estimated gas costs before claiming * **Batch claiming**: Allow users to claim multiple rewards in one transaction (using Bundlers) ### Monitoring[](https://docs.morpho.org/build/rewards/guides/complete-integration#monitoring) * **Error tracking**: Sentry, Bugsnag, or similar * **Analytics**: Track claim success rates, popular vaults, etc. * **Logging**: Structured logging for debugging Next Steps from the Demo[](https://docs.morpho.org/build/rewards/guides/complete-integration#next-steps-from-the-demo) ------------------------------------------------------------------------------------------------------------------------- After exploring the demo: 1. **Fork and modify**: Adapt it to your use case 2. **Add wallet connection**: Integrate RainbowKit or ConnectKit 3. **Customize UI**: Apply your brand's design system 4. **Deploy**: Vercel, Netlify, or your preferred platform Resources[](https://docs.morpho.org/build/rewards/guides/complete-integration#resources) ------------------------------------------------------------------------------------------- * **Demo Repository**: [github.com/morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe) * **Morpho API**: [api.morpho.org/graphql](https://api.morpho.org/graphql) * **Merkl Docs**: [docs.merkl.xyz](https://docs.merkl.xyz/) * **Rewards API**: [rewards.morpho.org/docs](https://rewards.morpho.org/docs) **Tutorials** * [Fetch Rewards Data](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data) * [Claim Rewards](https://docs.morpho.org/build/rewards/tutorials/claim-rewards) * [Integrate Display](https://docs.morpho.org/build/rewards/tutorials/integrate-display) --- # Public Allocator – Morpho Docs [Skip to content](https://docs.morpho.org/tools/onchain/public-allocator/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Public Allocator On this page Chevron Right The Public Allocator is a powerful onchain tool that solves liquidity fragmentation across isolated markets. For developers, it provides a mechanism to programmatically move liquidity on-demand, ensuring a user's borrow transaction can be fulfilled even if the target market initially has insufficient funds. This creates a user experience similar to a single, deep liquidity pool while retaining the risk-isolated benefits of Morpho's market design. ![Morpho Public Allocator Concept](https://docs.morpho.org/img/homepage/concepts/concepts_publicAllocator_light.png) Core Integration: `reallocateTo`[](https://docs.morpho.org/tools/onchain/public-allocator/#core-integration-reallocateto) ---------------------------------------------------------------------------------------------------------------------------- The primary function for interacting with the Public Allocator is `reallocateTo`. This function pulls assets from multiple source markets within a vault and supplies them to a single destination market in one atomic transaction. ### Function Signature[](https://docs.morpho.org/tools/onchain/public-allocator/#function-signature) Copy `function reallocateTo( address vault, Withdrawal[] calldata withdrawals, MarketParams calldata supplyMarketParams ) external payable;` ### Parameters[](https://docs.morpho.org/tools/onchain/public-allocator/#parameters) * **`vault`**: The address of the MetaMorpho vault containing the liquidity. * **`withdrawals`**: An array of `Withdrawal` structs, each specifying a source market and an amount to withdraw. * **`supplyMarketParams`**: A `MarketParams` struct defining the single destination market where all withdrawn funds will be deposited. ### Important Requirements[](https://docs.morpho.org/tools/onchain/public-allocator/#important-requirements) To successfully call `reallocateTo`, you must adhere to the following rules: * **Sorted Withdrawals**: The `withdrawals` array **must be sorted in ascending order by market ID**. * **Pay the Fee**: The transaction must be sent with the correct `fee` in ETH as `msg.value`. You can query this fee by calling the `fee(vaultAddress)` view function on the Public Allocator contract. * **Respect Flow Caps**: The withdrawal and supply amounts must not exceed the `maxOut` and `maxIn` flow caps configured by the vault curator for each market. * **Valid Markets**: All source and destination markets must be enabled in the vault's configuration. * **No Self-Supply**: The destination market (`supplyMarketParams`) cannot be included in the `withdrawals` array. ### Example: Solidity Integration[](https://docs.morpho.org/tools/onchain/public-allocator/#example-solidity-integration) Here is a simplified example of how you might construct and call `reallocateTo` within a smart contract. Copy `// Assuming IPublicAllocator and IMetaMorpho interfaces are available IPublicAllocator publicAllocator = IPublicAllocator(PA_ADDRESS); IMetaMorpho vault = IMetaMorpho(VAULT_ADDRESS); // 1. Check prerequisites require(vault.isAllocator(address(publicAllocator)), "PA: Not an allocator"); uint256 requiredFee = publicAllocator.fee(address(vault)); // 2. Prepare withdrawal parameters (must be sorted by market ID) Withdrawal[] memory withdrawals = new Withdrawal[](2); // Withdrawal from Market A (e.g., Idle Market) withdrawals[0] = Withdrawal({ marketParams: marketAParams, // MarketParams for Market A amount: 70 * 1e18 }); // Withdrawal from Market B (e.g., wstETH Market) // The ID of Market B must be greater than the ID of Market A withdrawals[1] = Withdrawal({ marketParams: marketBParams, // MarketParams for Market B amount: 800 * 1e18 }); // 3. Define the destination market MarketParams memory supplyMarketParams = rETHMarketParams; // MarketParams for rETH Market // 4. Execute the reallocation publicAllocator.reallocateTo{value: requiredFee}( address(vault), withdrawals, supplyMarketParams );` Recommended Integration Flow[](https://docs.morpho.org/tools/onchain/public-allocator/#recommended-integration-flow) ----------------------------------------------------------------------------------------------------------------------- For a robust dApp integration, the onchain `reallocateTo` call should be the final step in a flow that uses offchain data to ensure success. #### 1\. Check Target Market Liquidity[](https://docs.morpho.org/tools/onchain/public-allocator/#1-check-target-market-liquidity) First, check if the user's borrow can be fulfilled by the target market's existing liquidity. If so, no reallocation is needed. #### 2\. Query for Reallocatable Liquidity[](https://docs.morpho.org/tools/onchain/public-allocator/#2-query-for-reallocatable-liquidity) If more liquidity is required, use the **[Morpho API](https://docs.morpho.org/tools/onchain/public-allocator/#api-data-endpoints) ** to query the `publicAllocatorSharedLiquidity` for the target market. This will return a list of all source markets across all vaults that can provide liquidity. #### 3\. Simulate and Build Transaction[](https://docs.morpho.org/tools/onchain/public-allocator/#3-simulate-and-build-transaction) Using the data from the API, construct the `withdrawals` array. It is highly recommended to use the **Morpho SDKs** to simulate the transaction before asking the user to sign. This verifies that flow caps are respected and the call will succeed. #### 4\. Bundle and Execute[](https://docs.morpho.org/tools/onchain/public-allocator/#4-bundle-and-execute) For the best user experience, bundle the `reallocateTo` call with the user's `borrow` call into a single transaction using a **Morpho Bundler**. This ensures atomicity: if the reallocation fails, the entire operation (including the borrow) reverts, preventing failed transactions for the user. Key Resources[](https://docs.morpho.org/tools/onchain/public-allocator/#key-resources) ----------------------------------------------------------------------------------------- | Resource | Link | Description | | --- | --- | --- | | **Step-by-Step Tutorial** | **[/build/borrow/tutorials/public-allocator/](https://docs.morpho.org/build/borrow/tutorials/public-allocator)
** | A practical guide on how to trigger a reallocation, including an Etherscan walkthrough. | | **Contract Addresses** | **[/get-started/resources/addresses/](https://docs.morpho.org/get-started/resources/addresses)
** | Official addresses for the Public Allocator contract on all supported chains. | | **Solidity Specs & Errors** | **[/get-started/resources/contracts/public-allocator/](https://docs.morpho.org/get-started/resources/contracts/public-allocator)
** | Detailed contract specifications, function descriptions, and a table of common error messages. | | **API & Data Endpoints** | **[/tools/offchain/api/](https://docs.morpho.org/tools/offchain/api/get-started)
** | How to query GraphQL for flow caps, fees, and available reallocatable liquidity. | --- # App Integration – Morpho Docs [Skip to content](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu App Integration On this page Chevron Right This tutorial assumes you are already familiar with Morpho’s core packages (such as [blue-sdk](https://docs.morpho.org/tools/offchain/sdks/blue-sdk) and [blue-sdk-viem](https://docs.morpho.org/tools/offchain/sdks/blue-sdk-viem) ) and have set up a [Viem client](https://viem.sh/docs/clients/intro#introduction-to-clients--transports) for onchain interactions. For working examples, check out the [bundler-basic-app](https://github.com/morpho-org/bundler-basic-app) or the [earn-basic-app](https://github.com/morpho-org/earn-basic-app) repositories. Prerequisites Using SDKs[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#prerequisites-using-sdks) ----------------------------------------------------------------------------------------------------------------------- The [bundler-sdk-viem](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem) package extends Morpho’s simulation and interaction capabilities by converting simple user interactions (e.g., supply, borrow, repay, withdraw) into a bundled transaction. This bundle automatically includes all necessary ERC20 approvals, transfers, token wrapping/unwrapping, and even public liquidity reallocations. In short, it enables you to execute complex DeFi operations atomically, thereby reducing gas fees and minimizing the risk of intermediate state changes. The bundler works by: * Simulating the full sequence of operations. * Populating a bundle with required ERC20 operations. * Optimizing the operations (merging duplicates, redirecting tokens when possible). * Encoding the bundle for submission using Viem. ### Installation[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#installation) Install the bundler package along with its required peer dependencies: Copy `yarn add @morpho-org/bundler-sdk-viem @morpho-org/blue-sdk @morpho-org/morpho-ts viem` ### Setup[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#setup) First, import the basic key functions and types from [bundler-sdk-viem](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem) as well as from Morpho’s other packages: Copy `import { populateBundle, finalizeBundle, encodeBundle, type BundlingOptions, type InputBundlerOperation, } from "@morpho-org/bundler-sdk-viem"; import { MarketId, DEFAULT_SLIPPAGE_TOLERANCE } from "@morpho-org/blue-sdk"; import { SimulationState } from "@morpho-org/simulation-sdk"; import { WalletClient } from "viem";` Also, set up your [Viem client](https://viem.sh/docs/clients/intro#introduction-to-clients--transports) and [simulation state](https://github.com/morpho-org/sdks/tree/main/packages/simulation-sdk-wagmi#getting-started) as needed for your application. As a reminder, an example has been implemented in this [bundler-basic-app](https://github.com/morpho-org/bundler-basic-app/blob/main/src/hooks/usePopulatedSimulationState.ts) . Core Concepts[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#core-concepts) ------------------------------------------------------------------------------------------------- ### Bundled Operations[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#bundled-operations) The [bundler-sdk-viem](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem) transforms input operations—which represent simple user actions—into a bundle of low-level onchain operations. Here is the list of all the input operations: #### Blue Operations:[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#blue-operations) * Blue\_SetAuthorization * Blue\_Borrow * Blue\_Repay * Blue\_Supply * Blue\_SupplyCollateral * Blue\_Withdraw * Blue\_WithdrawCollateral #### Morpho Vaults Operations:[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#morpho-vaults-operations) * MetaMorpho\_Deposit * MetaMorpho\_Withdraw * MetaMorpho\_PublicReallocate For example, when a user wants to 1. Supply assets, 2. Supply collateral, 3. and then borrow in one transaction, you can pass three input operations: * Blue\_Supply * Blue\_SupplyCollateral * Blue\_Borrow The bundler automatically adds: * The required ERC20 approvals (via Erc20\_Approve, Erc20\_Permit, or Erc20\_Permit2) * ERC20 transfers from the user to the bundler * Additional steps such as token wrapping or unwrapping #### Using Slippage Tolerance[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#using-slippage-tolerance) When working with DeFi operations, including slippage tolerance is crucial for transaction success. Slippage occurs because between the time a transaction is simulated and when it's actually mined onchain: * Accrued interest might change the expected output amount * Market states may be updated by other transactions * Vault conditions might shift slightly The `DEFAULT_SLIPPAGE_TOLERANCE` parameter (imported from `@morpho-org/blue-sdk`) covers these minor discrepancies to ensure your transactions succeed even when market conditions change slightly. **Important**: Always include the slippage parameter in operations that involve asset conversions, including: * `Blue_Supply` * `Blue_Borrow` * `Blue_Repay` * `Blue_Withdraw` * `MetaMorpho_Deposit` * `MetaMorpho_Withdraw` #### Assets vs Shares Parameters[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#assets-vs-shares-parameters) Morpho operations often allow you to specify either an `assets` or `shares` parameter, depending on your use case, please read this section about [Assets vs Shares](https://docs.morpho.org/build/borrow/tutorials/assets-flow) Full RepayPartial Vault WithdrawFull Vault Withdraw Full Repay Copy `{ type: "Blue_Repay", sender: userAddress, address: morpho, args: { id: marketId, shares: position.borrowShares, // Full repayment onBehalf: userAddress, slippage: DEFAULT_SLIPPAGE_TOLERANCE, // Always include slippage }, }` ### Key Functions[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#key-functions) #### populateBundle[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#populatebundle) This function is the entry point to convert an array of InputBundlerOperation into a bundle of low-level operations. It: * Simulates each input operation using the current SimulationState. * Returns an object containing the bundled operations along with the simulation steps. Copy `const { operations, steps } = populateBundle( inputOperations, simulationState, bundlingOptions );` #### finalizeBundle[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#finalizebundle) After populating the bundle, finalizeBundle is used to: * Merge duplicate operations (e.g., multiple ERC20 approvals or transfers). * Optimize the operation sequence by redirecting tokens (e.g., from the bundler to the receiver). * Append any additional transfer operations to “skim” any remaining tokens. Copy `const optimizedOperations = finalizeBundle( operations, simulationState, receiverAddress, unwrapTokensSet, unwrapSlippage );` #### encodeBundle[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#encodebundle) Once the operations are optimized, they are encoded into a single transaction using encodeBundle. This function packages all the operations along with the requirements for signatures so that the transaction can be submitted onchain. ### Simulation & Error Handling[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#simulation--error-handling) The [bundler-sdk-viem](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem) integrates tightly with [simulation-sdk](https://github.com/morpho-org/sdks/tree/main/packages/simulation-sdk) . Functions such as `simulateRequiredTokenAmounts`, `simulateBundlerOperations`, and `getSimulatedBundlerOperation` are used to: * Simulate the effect of each bundled operation on your current state. * Determine how much of each token is required (especially for ERC20 transfers). * Handle errors by providing detailed simulation steps, which can be very useful during development and testing. Always wrap your bundling logic in a try-catch block to capture and log errors. ### Advanced Bundling Options[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#advanced-bundling-options) You can customize the bundling behavior via the BundlingOptions parameter: Copy `const bundlingOptions: BundlingOptions = { withSimplePermit: new Set(["0xTokenAddress1", "0xTokenAddress2"]), publicAllocatorOptions: { enabled: true, supplyTargetUtilization: { [marketId]: 905000000000000000n, // For a specific market }, defaultSupplyTargetUtilization: 905000000000000000n, }, getRequirementOperations: (requiredTokenAmounts) => { // Optionally, add custom operations to handle token requirements. return []; }, };` These options allow you to: * Force simple permit flows on certain tokens * Trigger liquidity reallocation when the market’s utilization exceeds a target threshold * Inject custom logic to handle required token amounts ### Sending the Transaction[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#sending-the-transaction) Once the bundle is encoded and signed, the transaction is sent to the blockchain via your Viem wallet client. The setupBundle function iterates through the individual transactions (including any signature requirements) and sends them sequentially. Example Implementation[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#example-implementation) ------------------------------------------------------------------------------------------------------------------- Let's walk through a practical example that demonstrates how to bundle multiple Morpho actions into a single transaction. This example shows how to: 1. Supply assets to a market 2. Supply collateral 3. Borrow assets You can find a complete working implementation in our [bundler-basic-app](https://github.com/morpho-org/bundler-basic-app) repository. Copy `import { type Account, WalletClient, zeroAddress } from "viem"; import { parseAccount } from "viem/accounts"; import { type Address, addresses, ChainId, DEFAULT_SLIPPAGE_TOLERANCE, MarketId, MarketParams, UnknownMarketParamsError, getUnwrappedToken, } from "@morpho-org/blue-sdk"; import { type BundlingOptions, type InputBundlerOperation, encodeBundle, finalizeBundle, populateBundle, } from "@morpho-org/bundler-sdk-viem"; import "@morpho-org/blue-sdk-viem/lib/augment"; import { withSimplePermit } from "@morpho-org/morpho-test"; import { type SimulationState, SimulationState, isBlueOperation, isErc20Operation, isMetaMorphoOperation, } from "@morpho-org/simulation-sdk"; export const setupBundle = async ( client: WalletClient, startData: SimulationState, inputOperations: InputBundlerOperation[], { account: account_ = client.account, supportsSignature, unwrapTokens, unwrapSlippage, onBundleTx, ...options }: BundlingOptions & { account?: Address | Account; supportsSignature?: boolean; unwrapTokens?: Set
; unwrapSlippage?: bigint; onBundleTx?: (data: SimulationState) => Promise | void; } = {} ) => { if (!account_) throw new Error("Account is required"); const account = parseAccount(account_); let { operations } = populateBundle(inputOperations, startData, { ...options, withSimplePermit: new Set([ ...withSimplePermit[startData.chainId], ...(options?.withSimplePermit ?? []), ]), publicAllocatorOptions: { enabled: true, ...options.publicAllocatorOptions, }, }); operations = finalizeBundle( operations, startData, account.address, unwrapTokens, unwrapSlippage ); const bundle = encodeBundle(operations, startData, supportsSignature); const tokens = new Set
(); operations.forEach((operation) => { const { address } = operation; if ( isBlueOperation(operation) && operation.type !== "Blue_SetAuthorization" ) { try { const marketParams = MarketParams.get(operation.args.id); if (marketParams.loanToken !== zeroAddress) tokens.add(marketParams.loanToken); if (marketParams.collateralToken !== zeroAddress) tokens.add(marketParams.collateralToken); } catch (error) { if (!(error instanceof UnknownMarketParamsError)) throw error; } } if (isMetaMorphoOperation(operation)) { tokens.add(address); const vault = startData.tryGetVault(address); if (vault) tokens.add(vault.asset); } if (isErc20Operation(operation)) { tokens.add(address); const unwrapped = getUnwrappedToken(address, startData.chainId); if (unwrapped != null) tokens.add(unwrapped); } }); await onBundleTx?.(startData); // here EOA should sign tx, if it is a contract, this can be ignored/removed await Promise.all( bundle.requirements.signatures.map((requirement) => requirement.sign(client, account) ) ); const txs = bundle.requirements.txs.map(({ tx }) => tx).concat([bundle.tx()]); for (const tx of txs) { await client.sendTransaction({ ...tx, account }); } return { operations, bundle }; }; const { morpho } = addresses[ChainId.EthMainnet]; /** * Executes a series of Morpho operations: supply, supply collateral, and borrow * @param marketId - The ID of the market to interact with * @param client - The wallet client instance * @param simulationState - The current simulation state * @param amountSupply - Amount to supply as lending position * @param amountSupplyCollateral - Amount to supply as collateral * @param amountBorrow - Amount to borrow * @returns Array of transaction responses */ export const supplySupplyCollateralBorrow = async ( marketId: MarketId, client: WalletClient, simulationState: SimulationState, amountSupply: bigint, amountSupplyCollateral: bigint, amountBorrow: bigint ) => { const user = client.account?.address; if (!user) throw new Error("User address is required"); return setupBundle(client, simulationState, [ { type: "Blue_Supply", sender: user, address: morpho, args: { id: marketId, assets: amountSupply, onBehalf: user, slippage: DEFAULT_SLIPPAGE_TOLERANCE, }, }, { type: "Blue_SupplyCollateral", sender: user, address: morpho, args: { id: marketId, assets: amountSupplyCollateral, onBehalf: user, }, }, { type: "Blue_Borrow", sender: user, address: morpho, args: { id: marketId, assets: amountBorrow, onBehalf: user, receiver: user, slippage: DEFAULT_SLIPPAGE_TOLERANCE, }, }, ]); };` #### Main SDK Repository:[](https://docs.morpho.org/tools/onchain/bundlers/app-integration/#main-sdk-repository) For more detailed source code and additional functions, visit the [bundler-sdk-viem](https://github.com/morpho-org/sdks/tree/main/packages/bundler-sdk-viem) repository. --- # Yield Generation – Morpho Docs [Skip to content](https://docs.morpho.org/curate/concepts/yield/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Yield Generation On this page Chevron Right Understanding how yield is generated, accounted for, and distributed is fundamental to curating a successful Morpho Vault. The mechanism for handling yield has evolved from a fully automated onchain system in Vaults V1 to an even more streamlined, adapter-based model in Vaults V2. ![Vault Architecture](https://docs.morpho.org/img/build/earn/morpho-v2-archi.png) Yield in Morpho Vaults V1[](https://docs.morpho.org/curate/concepts/yield/#yield-in-morpho-vaults-v1) -------------------------------------------------------------------------------------------------------- In Vaults V1, yield generation is a direct and automatic process tied exclusively to **Morpho Market V1**. ### The V1 Yield Flow[](https://docs.morpho.org/curate/concepts/yield/#the-v1-yield-flow) 1. **Allocation**: The vault allocates capital to one or more Morpho Market V1 instances, as directed by the `Allocator`. 2. **Interest Paid by Borrowers**: Borrowers in those markets pay interest on their loans according to the market's specific Interest Rate Model (IRM). 3. **Onchain Accrual**: This interest automatically accrues to all lenders in the market, including the Morpho Vault. 4. **Automatic `totalAssets` Update**: When any user interacts with the vault (e.g., deposits or withdraws), the vault contract automatically calculates its total assets by summing up its underlying positions on Morpho Market V1. This process is fully onchain and reflects the real, up-to-the-second value of its holdings. 5. **Share Price Growth**: As `totalAssets` increases from the accrued interest, the value of each vault share appreciates, delivering yield to depositors. The key takeaway for V1 is that yield is **passively received and automatically accounted for**. The Curator's job is to select the right markets, not to manage the yield calculation itself. Yield in Morpho Vaults V2[](https://docs.morpho.org/curate/concepts/yield/#yield-in-morpho-vaults-v2) -------------------------------------------------------------------------------------------------------- Vaults V2 are designed to be future-proof, capable of allocating assets to countless different yield sources. Like V1, the yield calculation remains fully automated through a streamlined adapter-based architecture. ### Automatic Asset Reporting via Adapters[](https://docs.morpho.org/curate/concepts/yield/#automatic-asset-reporting-via-adapters) Each **Adapter** in Vaults V2 implements a `realAssets()` function that reports the current value of all investments it manages. This allows the vault to automatically aggregate yield from diverse sources. * **Adapter Responsibility**: Each adapter is responsible for accurately reporting the current value of its investments through `realAssets()`. * **Automatic Aggregation**: The vault calculates its total assets by summing the `realAssets()` from all adapters plus any idle assets. * **Protocol Flexibility**: This model allows the vault to account for yield from any source while maintaining automated, onchain accuracy. ### The V2 Yield Flow[](https://docs.morpho.org/curate/concepts/yield/#the-v2-yield-flow) 1. **Allocation**: The `Allocator` deploys capital to various protocols through **Adapters** (e.g., to Morpho Market V1, Morpho Vault V1, etc.). 2. **Yield Generation**: Each underlying position generates yield according to its own protocol's rules. 3. **Real-time Reporting**: Each adapter continuously tracks the current value of its investments and reports this via `realAssets()`. 4. **Vault Accrual**: When a user interacts with the vault, the vault automatically queries all adapters' `realAssets()` and updates its `totalAssets` accordingly. 5. **Share Price Growth**: As the real asset values increase from yield generation, the vault's share price increases automatically, delivering yield to depositors. ### Adapter Examples[](https://docs.morpho.org/curate/concepts/yield/#adapter-examples) The initial adapter implementations demonstrate this automatic approach: * **`MorphoMarketV1Adapter`**: Automatically queries Morpho Market V1 to report the current value of supply positions, including any accrued interest. * **`MorphoVaultV1Adapter`**: Automatically queries the share price of the underlying Morpho Vault V1 to report current asset values. ### Interest Rate Controls[](https://docs.morpho.org/curate/concepts/yield/#interest-rate-controls) While yield tracking is automatic, Curators can set additional controls: * **`maxRate`**: A curator-controlled parameter that caps how quickly `totalAssets` can grow, useful for implementing fixed-rate distributions or preventing unrealistic yield spikes. ### Practical Implications for Curators[](https://docs.morpho.org/curate/concepts/yield/#practical-implications-for-curators) * **V1 Curation**: Focus on **market selection** and **capital allocation**. Yield accounting is handled by the protocol. * **V2 Curation**: Focus on **protocol selection**, **adapter enablement**, and **capital allocation**. Yield accounting remains automated through adapter reporting, with optional rate controls via `maxRate`. * **Simplified Management**: Unlike manual rate-setting systems, the adapter-based approach eliminates the risk of mispricing yield while maintaining the flexibility to integrate with any protocol. --- # Fees – Morpho Docs [Skip to content](https://docs.morpho.org/curate/concepts/fee/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Fees On this page Chevron Right Morpho Vaults include fee mechanisms that allow vault managers to generate revenue from the yield they produce. The implementation and capabilities of these fees have evolved significantly from Vaults V1 to Vaults V2, offering curators more flexibility in designing their business models. Fee Structure in Morpho Vaults V2[](https://docs.morpho.org/curate/concepts/fee/#fee-structure-in-morpho-vaults-v2) ---------------------------------------------------------------------------------------------------------------------- Vaults V2 introduce a sophisticated, dual-fee structure, giving curators precise control over revenue streams. All fee-related changes are managed by the `Curator` and are subject to a **timelock**, ensuring transparency and giving users time to react to proposed changes. ### 1\. Performance Fee[](https://docs.morpho.org/curate/concepts/fee/#1-performance-fee) The performance fee is a percentage of the yield generated by the vault, aligning the curator's revenue with the vault's success. * **Fee Basis**: Charged as a percentage of the interest generated by the vault's investments. This is automatically calculated based on the real asset values reported by adapters. * **Maximum Rate**: Capped at **50%** of the generated interest. * **Control**: The `Curator` sets the fee rate and the recipient address. ### 2\. Management Fee[](https://docs.morpho.org/curate/concepts/fee/#2-management-fee) The management fee is a continuous fee charged on the vault's total assets under management (AUM), providing a steady revenue stream for the vault's managers. * **Fee Basis**: Calculated as an annualized percentage of the vault's `totalAssets`. A small portion of this fee is collected each time interest is accrued. * **Maximum Rate**: Capped at **5% per year**. * **Control**: The `Curator` sets the fee rate and the recipient address. ### Fee Collection Mechanism in V2[](https://docs.morpho.org/curate/concepts/fee/#fee-collection-mechanism-in-v2) Fees in Vaults V2 are collected seamlessly without affecting depositors' principal. 1. An interaction (like a deposit, withdrawal, or a direct `accrueInterest` call) triggers interest and fee calculations. 2. The vault aggregates asset values from all adapters to determine the total interest generated. 3. The performance and management fees are calculated based on this interest and the total assets. 4. New vault shares corresponding to the fee amounts are minted directly to the `performanceFeeRecipient` and `managementFeeRecipient` addresses. 5. The vault's `totalAssets` are updated to reflect the new state after interest distribution. This share-minting mechanism ensures that fees are taken from the profits, while the principal of all depositors remains fully intact. Fee Structure in Morpho Vaults V1[](https://docs.morpho.org/curate/concepts/fee/#fee-structure-in-morpho-vaults-v1) ---------------------------------------------------------------------------------------------------------------------- The fee system in Vaults V1 is simpler, consisting of a single performance-based fee controlled by the `Owner`. * **Fee Type**: A single **performance fee**. There is no management fee. * **Fee Basis**: The fee is a percentage of the **actual interest** accrued onchain from the underlying Morpho Market V1 positions. * **Control**: The `Owner` of the vault sets the fee rate and the recipient. * **Security**: Fee parameter changes are **immediate** and do not have a timelock. * **Maximum Rate**: Capped at **50%** of the generated interest. * **Collection**: Like in V2, fees are collected by minting new vault shares to the `feeRecipient`. Comparison: Vaults V2 vs. Vaults V1[](https://docs.morpho.org/curate/concepts/fee/#comparison-vaults-v2-vs-vaults-v1) ------------------------------------------------------------------------------------------------------------------------ | Feature | Morpho Vaults V2 | Morpho Vaults V1 (MetaMorpho) | | --- | --- | --- | | **Fee Types** | **Performance Fee** + **Management Fee** | Performance Fee Only | | **Performance Fee Basis** | Interest automatically calculated from adapter asset values | **Actual onchain interest** from Morpho Market V1 positions | | **Management Fee Basis** | Percentage of **Total Assets** (AUM) | N/A | --- # Roles & Capabilities – Morpho Docs [Skip to content](https://docs.morpho.org/curate/concepts/roles/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Roles & Capabilities On this page Chevron Right The roles and capabilities for managing Morpho Vaults differ significantly between the future-proof Vaults V2 and the original Morpho Market V1-centric Vaults V1. This document outlines the responsibilities and permissions for each version. Morpho Vaults V2 Roles[](https://docs.morpho.org/curate/concepts/roles/#morpho-vaults-v2-roles) -------------------------------------------------------------------------------------------------- The Vault V2 architecture introduces a refined role system with a clear separation of concerns, designed for enhanced security and operational flexibility. ### Owner[](https://docs.morpho.org/curate/concepts/roles/#owner) The **Owner** holds the highest-level administrative power, responsible for appointing and managing the key roles that govern the vault. * **Recommended Approach:** A secure multisig (e.g., 4-of-6) or an equivalent institutional-grade MPC wallet. A single EOA is highly discouraged for production vaults. * **Impact of Compromise:** Full administrative control loss. The Owner can replace the Curator, who controls the vault's strategy. #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities) * Only one address can have this role. * Transfer ownership of the vault (`setOwner`). * Appoint or change the `Curator` (`setCurator`). * Add or remove `Sentinels` (`setIsSentinel`). * Set the vault's ERC-20 `name` and `symbol`. ### Curator[](https://docs.morpho.org/curate/concepts/roles/#curator) The **Curator** is the vault's chief risk officer and strategist. They define the investment thesis, set risk parameters, and enable the tools for the Allocator. * **Recommended Approach:** A multisig (e.g., 2-of-4 or 3-of-5) or an MPC wallet. * **Impact of Compromise:** Can propose and, after a timelock, execute changes that alter the vault's risk profile. The `Sentinel` and depositors have the timelock duration to react. #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-1) * Only one address can have this role. * **Protocol Management**: * `[Timelocked]` Enable or disable yield sources via Adapters (`addAdapter`, `removeAdapter`). * **Risk Curation**: * `[Timelocked]` Increase absolute or relative caps for any risk `id` (`increaseAbsoluteCap`, `increaseRelativeCap`). * Instantly decrease absolute or relative caps (`decreaseAbsoluteCap`, `decreaseRelativeCap`). * **Yield & Fee Management**: * `[Timelocked]` Set the maximum rate at which assets can grow (`setMaxRate`). * `[Timelocked]` Set the `performanceFee` and `managementFee`. * `[Timelocked]` Set the `performanceFeeRecipient` and `managementFeeRecipient`. * **Operational Management**: * `[Timelocked]` Add or remove `Allocators` (`setIsAllocator`). * `[Timelocked]` Set `Gate` contracts for onchain compliance (`setSharesGate`, `setReceiveAssetsGate`, `setSendAssetsGate`). * `[Timelocked]` Set the penalty for `forceDeallocate` (`setForceDeallocatePenalty`). * **Timelock Management**: * Instantly increase the duration of any timelock (`increaseTimelock`). * `[Timelocked, 3 weeks]` Decrease the duration of any timelock (`decreaseTimelock`). * `[Timelocked]` Irreversibly disable a timelocked action (`abdicate`). ### Allocator[](https://docs.morpho.org/curate/concepts/roles/#allocator) The **Allocator** is the active portfolio manager, responsible for executing the vault's strategy within the boundaries set by the Curator. * **Recommended Approach:** A smart contract with automated logic, a hot-key EOA operated by a bot, or a fast-response multisig. * **Impact of Compromise:** Can misallocate funds between _already approved_ adapters, potentially leading to suboptimal yield or temporary liquidity imbalances. Cannot introduce new, unapproved risks. #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-2) * Multiple addresses can have this role. * Allocate capital from the vault's idle assets to enabled Adapters (`allocate`). * Deallocate capital from Adapters back to the vault's idle assets (`deallocate`). * Set and manage the `liquidityAdapter` to handle user deposits and withdrawals. ### Sentinel[](https://docs.morpho.org/curate/concepts/roles/#sentinel) The **Sentinel** is a safety-oriented role designed for reactive risk mitigation. It acts as a check on the Curator and can intervene in emergencies. * **Recommended Approach:** Can be a hot key, a DAO governance contract (e.g., Snapshot), or a trusted third party. * **Impact of Compromise:** Minimal. A compromised Sentinel can only take actions that reduce risk (e.g., deallocate funds) or halt pending changes. It cannot introduce new risk. #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-3) * Multiple addresses can have this role. * Deallocate funds from any enabled Adapter back to the vault's idle assets (`deallocate`). * Instantly decrease absolute or relative caps for any risk `id`. * Revoke any pending timelocked action submitted by the Curator (`revoke`). ### Any Address[](https://docs.morpho.org/curate/concepts/roles/#any-address) #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-4) * Execute any action submitted by the Curator once its timelock has expired. * Trigger a `forceDeallocate` to provide in-kind redemption liquidity (subject to a penalty). Morpho Vaults V1 Roles[](https://docs.morpho.org/curate/concepts/roles/#morpho-vaults-v1-roles) -------------------------------------------------------------------------------------------------- For reference, here are the roles and capabilities for the Morpho Vaults V1 architecture. ### Owner[](https://docs.morpho.org/curate/concepts/roles/#owner-1) #### Roles[](https://docs.morpho.org/curate/concepts/roles/#roles) * **Highly Recommended Approaches:** * Deploy a multisig with minimum 4/6 signers, OR * Use an enterprise MPC wallet with equivalent security controls * Implement strict operational security protocols * Distribute signing authority across trusted entities * Never use single-key EOA (Externally Owned Account) control * **Impact of Compromise:** Complete vault control loss without recovery options #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-5) * Only a single address can have this role. * Change owner (2 steps: the new owner has to accept ownership). * Renounce ownership. * Set the curator. * Add/remove addresses with the allocator role (including the Public Allocator). * \[Time-locked\] Set the guardian. * Increase the timelock duration for every time-locked function. * \[Time-locked if already set\] Decrease the timelock duration for every time-locked function. * Set the performance fee. * Set the fee recipient. * Set the rewards distributor address. * All the capabilities of the Curator, the Allocator and the Guardian. ### Curator[](https://docs.morpho.org/curate/concepts/roles/#curator-1) #### Roles[](https://docs.morpho.org/curate/concepts/roles/#roles-1) * **Recommended Approaches:** * Deploy a multisig with minimum 2/4 or 3/5 signers, OR * Use an enterprise MPC wallet with multi-party authorization policies * Implement robust operational security protocols * Distribute signing authority with geographical redundancy * **Impact of Compromise:** Elevated risk exposure, recoverable by owner intervention #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-6) * Only a single address can have this role. * Decrease a supply cap on a Morpho market. * \[Time-locked\] Increase a supply cap on a Morpho market, which includes enabling a new market (by setting a non-zero cap on a not yet enabled market). * \[Time-locked\] Submit the forced removal of a market. * Revoke the pending supply cap on a Morpho market. * Revoke the pending removal of a Morpho market. * All the capabilities of the Allocator. Note: the Curator can't pause the withdrawal of funds. ### Allocator[](https://docs.morpho.org/curate/concepts/roles/#allocator-1) #### Roles[](https://docs.morpho.org/curate/concepts/roles/#roles-2) * **Recommended Options:** * Smart contract with automated reallocation logic * EOA operated by monitoring bot * Multisig with fast response capabilities (1/3 or 2/4), OR * Enterprise MPC wallet with appropriate authorization controls * **Mitigation Strategy:** Set restrictive market caps to limit potential damage #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-7) * Multiple addresses can have this role. * Can modify the allocation between markets and the idle supply in the vault within the bounds set by the Curator. * Set the supply queue to some arbitrary queue of markets. * Re-order the withdraw queue by applying a permutation to it. Can omit markets on which the vault has 0 supply and 0 cap to remove it form the withdraw queue. ### Guardian[](https://docs.morpho.org/curate/concepts/roles/#guardian) #### Roles[](https://docs.morpho.org/curate/concepts/roles/#roles-3) * **Implementation Options:** * Snapshot-based governance system * Aragon DAO integration * Multisig managed by community representatives * **Security Benefit:** Provides emergency intervention capability for users #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-8) * Only a single address can have this role. * Can revoke a pending timelock decrease until the previous timelock ends and the new timelock is accepted (by the Owner). * Can revoke a pending guardian until the timelock ends and the new guardian is accepted (by the Owner). * Can revoke each pending market cap increase until the timelock ends and the new market cap is accepted (by the Owner or the Curator). * In particular, it cannot revoke a pending fee (submitted by the Owner). ### Any address[](https://docs.morpho.org/curate/concepts/roles/#any-address-1) #### Capabilities[](https://docs.morpho.org/curate/concepts/roles/#capabilities-9) * Can accept the new cap after timelock. * Can accept the new fee after timelock. * Can accept the new guardian after timelock. * Can accept the new Timelock value after the current timelock duration. --- # Liquidity Curation – Morpho Docs [Skip to content](https://docs.morpho.org/curate/concepts/liquidity/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Liquidity Curation On this page Chevron Right Liquidity Curation is the art and science of curating a vault's capital to optimize yield while adhering to a specific risk strategy. It is a dynamic process performed by the vault's `Curator` and `Allocator`, who work together to define risk parameters and deploy assets effectively. The methodology for curation differs significantly between Morpho's vault versions: * **Vaults V2** use a powerful, future-proof framework based on **Adapters** and a granular **ID & Cap System**. * **Vaults V1** use a more direct model focused on allocating to **Morpho Market V1** instances via **Supply and Withdraw Queues**. Curation in Morpho Vaults V2[](https://docs.morpho.org/curate/concepts/liquidity/#curation-in-morpho-vaults-v2) ------------------------------------------------------------------------------------------------------------------ Curation in Vaults V2 is a two-tiered process that separates high-level strategy from tactical execution. The `Curator` sets the rules of the game, and the `Allocator` plays within them. ### The Core Components of V2 Curation[](https://docs.morpho.org/curate/concepts/liquidity/#the-core-components-of-v2-curation) A V2 Curator has three primary tools to build the vault's risk framework: #### 1\. Adapters: The Gateway to Protocols[](https://docs.morpho.org/curate/concepts/liquidity/#1-adapters-the-gateway-to-protocols) An **Adapter** is a smart contract that allows the vault to interact with an external protocol. The Curator's first job is to decide which protocols the vault can trust by enabling their respective adapters. This makes the vault a universal gateway, capable of allocating to: * Morpho Market V1 (via `MorphoMarketV1Adapter`) * Morpho Vault V1 (via `MorphoVaultV1Adapter`) * Future Morpho versions and any other yield-bearing protocol with an adapter. #### 2\. The ID & Cap System: Granular Risk Control[](https://docs.morpho.org/curate/concepts/liquidity/#2-the-id--cap-system-granular-risk-control) This is the heart of V2 risk curation. Instead of setting a simple cap on a single market, the Curator can manage exposure across abstract **risk factors**, each identified by a unique `id`. An `id` can represent anything an adapter can define, such as: * A specific collateral asset (e.g., `stETH`) * A specific oracle (e.g., `Chainlink`) * An entire protocol (e.g., all of Morpho Market V1) * A highly specific market configuration The Curator can apply two types of caps to any `id`: * **Absolute Cap**: A fixed maximum amount of assets (e.g., "no more than 20M USDC allocated to markets with `wBTC` as collateral"). * **Relative Cap**: A maximum percentage of the vault's total assets (e.g., "no more than 30% of the vault may be exposed to Protocol X"). This system allows for sophisticated, multi-dimensional risk policies that were impossible in V1. #### 3\. The Liquidity Adapter: Managing Active Liquidity[](https://docs.morpho.org/curate/concepts/liquidity/#3-the-liquidity-adapter-managing-active-liquidity) The `Allocator` can designate one enabled adapter as the vault's **`liquidityAdapter`**. This adapter serves two critical functions: 1. **Receiving Deposits**: All new user deposits are automatically routed to this adapter, ensuring capital is immediately put to work. 2. **Fulfilling Withdrawals**: If the vault's idle assets are insufficient to cover a user's withdrawal, funds are automatically pulled from this adapter. It is typically set to a highly liquid and safe yield source to ensure smooth vault operations. ### The Curation Workflow in Practice[](https://docs.morpho.org/curate/concepts/liquidity/#the-curation-workflow-in-practice) 1. **Strategic Curation (The `Curator`)**: * **Enables Adapters**: Decides which protocols are in-scope for the vault's strategy. * **Defines the Risk Framework**: Sets absolute and relative caps on various `ids` to control exposure. * **Appoints Allocators**: Delegates the active portfolio management to trusted entities or smart contracts. _(All these actions are timelocked for security)._ 2. **Tactical Allocation (The `Allocator`)**: * **Operates Within Boundaries**: The Allocator uses `allocate` and `deallocate` to move funds between the vault's idle pool and the various enabled adapters. * **Optimizes Yield**: They can shift capital to adapters offering the best risk-adjusted returns, as long as no caps are breached. * **Manages Liquidity**: They set the `liquidityAdapter` to ensure there are sufficient funds for user deposits and withdrawals. | Feature | **In Morpho Vault V2** | | --- | --- | | **Allocation Target** | Any protocol with an enabled **Adapter**. | | **Risk Control** | Granular **ID & Cap System** (absolute and relative caps on risk factors). | | **Liquidity Management** | A dedicated **`liquidityAdapter`** for deposits and withdrawals. | Curation in Morpho Vaults V1[](https://docs.morpho.org/curate/concepts/liquidity/#curation-in-morpho-vaults-v1) ------------------------------------------------------------------------------------------------------------------ Curation in Vaults V1 is focused exclusively on allocating capital across **Morpho Market V1** instances. The system is more direct, relying on queues and per-market caps. ### Strategic Market Curation[](https://docs.morpho.org/curate/concepts/liquidity/#strategic-market-curation) The `Curator`'s primary role is to select a basket of Morpho Market V1 instances that align with the vault's strategy and set a hard **supply cap** on each one. This provides a simple but effective way to limit exposure to any single market. ### The Queue System: How Capital Moves[](https://docs.morpho.org/curate/concepts/liquidity/#the-queue-system-how-capital-moves) The `Allocator` is responsible for managing two critical queues that dictate how capital flows in and out of the vault: #### Supply and Withdraw Queues[](https://docs.morpho.org/curate/concepts/liquidity/#supply-and-withdraw-queues) The supply queue determines the order in which markets receive new deposits. When a user deposits assets, the vault attempts to supply liquidity to each market in sequence until the deposit is fully allocated or all market caps are reached. The withdraw queue determines the order in which markets are tapped to fulfill user withdrawals. This queue contains all markets where the vault has a non-zero supply or a non-zero cap. ### Recommended Queue Setup[](https://docs.morpho.org/curate/concepts/liquidity/#recommended-queue-setup) **Supply Queue:** `[Idle]` **Withdraw Queue:** `[Idle, Market 1, Market 2, …]` This configuration is recommended for all Morpho Vaults V1 and V1.1 as it completely prevents any misallocation of funds through normal operations or malicious intent. This setup: * **Keeps the strategy intact**: Deposits land in idle first and withdrawals exit idle first, so routine user activity can't move funds out of your yield strategy. * **Protects APY and risk settings**: Idle acts as a neutral buffer; reallocations happen only when you decide, preventing erosion of returns or allocations to assets beyond your current selection. * **Stops accidental drift**: Even well-meaning users can shuffle money between markets if queues start with different pools. Using "Idle first" on both sides blocks that. * **Thwarts quick "hit-and-run" attacks**: Flash-loan or high-balance tricks lose their leverage because idle simply drains and refills itself, leaving active markets unchanged. Practical Implementation[](https://docs.morpho.org/curate/concepts/liquidity/#practical-implementation) ---------------------------------------------------------------------------------------------------------- The market management system requires continuous monitoring and adjustment: * **Data-Driven Decisions**: Base cap adjustments and queue positioning on utilization metrics, yield comparisons, and risk assessments * **Capital Flow Analysis**: Monitor deposit and withdrawal patterns to optimize queue configurations * **Risk Mitigation**: Implement gradual transitions to prevent rate spikes that could drive borrowers to competitors * **Stress Testing**: Regularly simulate extreme market conditions to ensure queue systems remain robust --- # Adapter Registry – Morpho Docs [Skip to content](https://docs.morpho.org/curate/concepts/adapter-registry/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Adapter Registry On this page Chevron Right Vault V2 introduces the concept of an **Adapter Registry** — a [smart contract](https://docs.morpho.org/get-started/resources/addresses#morpho-v2-contracts) that defines which adapters a vault can use to allocate assets. Why Registries Matter[](https://docs.morpho.org/curate/concepts/adapter-registry/#why-registries-matter) ----------------------------------------------------------------------------------------------------------- [Vault V2](https://github.com/morpho-org/vault-v2) is future-proof: any curator can add adapters to deposit assets into external protocols. This flexibility is powerful but also introduces risk: a vault could attract liquidity using the Morpho ecosystem and later redirect funds to other protocols that may be less secure or less aligned with Morpho’s safety and quality standards. Adapter Registries solve this by giving curators (and end users) a way to lock the vault’s allocation perimeter. * Without a registry → any adapter can be added. * With a registry → only adapters explicitly approved by that registry can be used. * The curator can abdicate the `setAdapterRegistry` function (by timelocking it forever) to make this restriction permanent and non-custodial. For implementation details, see the [vault-V2-adapter-registries repository](https://github.com/morpho-org/vault-v2-adapter-registries) . The Morpho Registry[](https://docs.morpho.org/curate/concepts/adapter-registry/#the-morpho-registry) ------------------------------------------------------------------------------------------------------- The **Morpho Registry** is an official registry maintained by the Morpho governance. It lists adapters approved by the Morpho governance — including Morpho Markets (V1, V2) and Morpho Vaults V1 — and allows new ones to be added over time. Vaults that: 1. Set their adapter registry to the Morpho Registry, and 2. Abdicate the ability to change it are considered Morpho Vaults V2. These Morpho Vaults V2 gain access to Morpho ecosystem benefits, such as: * Eligibility for display and distribution in the Morpho App. * Access to Morpho’s support, incentive programs and Prime apps suite. * Confidence for depositors that the vault will remain within the Morpho-approved adapter perimeter. Developers can explore the Morpho Registry contract and other registry implementations in the [vault-V2-adapter-registries GitHub repo](https://github.com/morpho-org/vault-v2-adapter-registries) . Key Properties[](https://docs.morpho.org/curate/concepts/adapter-registry/#key-properties) --------------------------------------------------------------------------------------------- **Future proof**: vaults can add a new adapter, benefiting from it while preserving the liquidity the vault has built. **Add-only**: Once an adapter is approved, it stays; adapters can’t be removed to avoid breaking existing vaults. **Non-custodial guarantees**: Users can always exit before any configuration change (thanks to timelocks and in-kind redemptions). **Composable**: Builders can create their own registries if they want different adapter rules. --- # Timelock – Morpho Docs [Skip to content](https://docs.morpho.org/curate/concepts/timelock/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Timelock On this page Chevron Right The timelock is a cornerstone of security in Morpho Vaults. It is a mandatory waiting period for sensitive administrative actions, designed to protect depositors by ensuring transparency and providing a window to react to proposed changes. This mechanism is fundamental to the non-custodial nature of the vaults. ### The Timelock Process[](https://docs.morpho.org/curate/concepts/timelock/#the-timelock-process) A timelock enforces a simple but powerful workflow for critical changes: 1. **Submit**: An administrator (the `Curator` in V2 and `Owner` in V1) proposes a change by submitting it to the vault contract. 2. **Wait**: The proposal becomes pending and enters a waiting period. The duration of this period is defined by the timelock. During this time, the change cannot be executed, and anyone can review it onchain. 3. **Execute**: Once the timelock duration has passed, anyone can call the function to execute the proposed change, making it final. This delay is crucial, as it prevents malicious or erroneous changes from taking effect instantly, giving users and safety roles (`Sentinel`/`Guardian`) time to intervene or withdraw their funds. Timelocks in Morpho Vaults V2: Granular and Flexible Security[](https://docs.morpho.org/curate/concepts/timelock/#timelocks-in-morpho-vaults-v2-granular-and-flexible-security) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Vaults V2 upgrade the timelock concept significantly by introducing **per-function timelocks**. This allows for a more nuanced and sophisticated approach to security. ### How It Works: Timelocks per Selector[](https://docs.morpho.org/curate/concepts/timelock/#how-it-works-timelocks-per-selector) Instead of a single, global timelock for the entire vault, a V2 `Curator` can assign a different timelock duration to each sensitive action, identified by its function `selector`. This flexibility allows for risk-based security policies. For example, a Curator might configure their vault with: * A **7-day timelock** for high-risk actions like enabling a new, untested adapter. * A **1-day timelock** for routine, lower-risk actions like appointing a new `Allocator`. * A **0-second timelock** for actions they deem completely safe (though this is less common for production vaults). ### Timelock Management in V2[](https://docs.morpho.org/curate/concepts/timelock/#timelock-management-in-v2) The `Curator` has a specific set of tools to manage these timelocks, each with its own security logic: * **Increasing Timelocks (`increaseTimelock`)**: A Curator can increase the duration of any timelock **instantly**. Because making a safety delay longer is always a security-enhancing action, it does not require a waiting period. * **Decreasing Timelocks (`decreaseTimelock`)**: This action is highly sensitive and is itself subject to a long, **2-week timelock**. This prevents a malicious actor from instantly reducing all safety delays to zero. * **Abdicating Actions (`abdicateSubmit`)**: A Curator can choose to **permanently and irreversibly** disable their ability to submit a certain type of change by setting its timelock to infinity. This is a powerful "trust-hardening" feature. For example, a vault could abdicate the ability to ever set a `Gate`, guaranteeing to its users that it will remain permissionless forever. Timelocks in Morpho Vaults V1[](https://docs.morpho.org/curate/concepts/timelock/#timelocks-in-morpho-vaults-v1) ------------------------------------------------------------------------------------------------------------------- In contrast, Morpho Vaults V1 use a **global timelock** system. A single timelock duration applies to all protected actions within the vault, such as increasing a market's supply cap or setting the `Guardian`. ### Key Characteristics of V1 Timelocks[](https://docs.morpho.org/curate/concepts/timelock/#key-characteristics-of-v1-timelocks) * **Flexible Initial Setup**: The timelock can be set to zero at deployment. This is a major convenience that allows vault administrators to perform the initial configuration and market setup instantly without waiting periods. * **Post-Setup Security**: After the initial setup, any change to the timelock must set its duration to be between **1 day and 2 weeks**. * **Asymmetric Updates**: * **Increasing** the timelock takes effect immediately. * **Decreasing** the timelock is itself a timelocked action, requiring a wait equal to the _current_ (longer) timelock duration. This V1 model provides robust security while allowing for practical initial vault deployment. ### Viewing Timelock Settings[](https://docs.morpho.org/curate/concepts/timelock/#viewing-timelock-settings) You can check the current timelock value(s) for any Morpho Vault by visiting the "Read Contract" section on a blockchain explorer and querying the `timelock` function. * In **V2**, this function takes a function `selector` as an argument. * In **V1**, it returns the single, global timelock duration in seconds. Comparison: Vaults V2 vs. Vaults V1[](https://docs.morpho.org/curate/concepts/timelock/#comparison-vaults-v2-vs-vaults-v1) ----------------------------------------------------------------------------------------------------------------------------- | Feature | Morpho Vaults V2 | Morpho Vaults V1 (MetaMorpho) | | --- | --- | --- | | **Timelock Structure** | **Per-function timelocks** (granular control) | **Global timelock** (single duration for all actions) | | **Timelock Assignment** | Different durations per function selector | One duration applies to all protected actions | | **Increasing Timelocks** | **Instant** (security-enhancing) | **Instant** (takes effect immediately) | | **Decreasing Timelocks** | **2-week timelock** (highly protected) | Subject to **current timelock** duration | | **Initial Setup** | Standard timelock rules apply | **Can be set to zero** at deployment | | **Permitted Range** | Flexible (can be set to infinity via abdication) | **1 day to 2 weeks** (after initial setup) | | **Abdication Feature** | **Yes** (can permanently disable actions) | **No** | --- # Vault as asset – Morpho Docs [Skip to content](https://docs.morpho.org/curate/concepts/vault-as-asset/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Vault as asset On this page Chevron Right In this section, we outline security considerations and recommendations for listing 4626 vaults as an asset, collateral, or loan asset. Vault as collateral[](https://docs.morpho.org/curate/concepts/vault-as-asset/#vault-as-collateral) ----------------------------------------------------------------------------------------------------- ### Liquid & flashloanable 4626 assets with share price decrease[](https://docs.morpho.org/curate/concepts/vault-as-asset/#liquid--flashloanable-4626-assets-with-share-price-decrease) ERC4626 vaults with the following properties can incur a loss of funds. * Most of the shares of the vault can be flash loaned. * Most of the vault is liquid. * The vault's share price can decrease notably and instantly. This is not specific to Morpho but a general statement for all ERC4626 vaults. Since assets deposited on Morpho can always be flash loaned, it is important to keep in mind. The loss is bounded by: totalLoss≤δ11−min⁡(AWA,SLS)totalLoss \\le \\delta\\frac{1}{1-\\min(\\frac{A\_W}{A}, \\frac{S\_L}{S})} totalLoss≤δ1−min(AAW​​,SSL​​)1​ where: * The loss on the vault (that creates the share price decrease): δ\\delta δ * The liquid portion of the vault: AWA\\frac{A\_W}{A} AAW​​ * The loanable portion of the vault: SLS\\frac{S\_L}{S} SSL​​ ### Recommendations for Morpho Vaults used as collateral[](https://docs.morpho.org/curate/concepts/vault-as-asset/#recommendations-for-morpho-vaults-used-as-collateral) For Morpho Vaults **with bad debt realization** (created with [the MetaMorpho Factory V1.0](https://github.com/morpho-org/metamorpho) ), the share price can decrease in the event of a bad debt realization in one of the listed markets. If the vault is highly liquid, the supply queue has a specific order, and most of the shares can be flashloaned, then the liquidator of the market could amplify bad debt realized by the vault. Since using vaults as collateral increases the proportion of the vault that can be flashloaned, it could favor this amplification. Although very unlikely, it is thus not recommended using those vaults as collateral. For Morpho vaults **without bad debt realization** (created with [the MetaMorpho Factory V1.1](https://github.com/morpho-org/metamorpho-v1.1) ), the share price of the vault can't decrease, and the above-described scenario can't happen. That said, the vault users won't have bad debt realized in their vault. Credit to [100proof](https://x.com/1_00_proof) on helping the Morpho team providing those security guidelines to vault curators. Vault as loan asset[](https://docs.morpho.org/curate/concepts/vault-as-asset/#vault-as-loan-asset) ----------------------------------------------------------------------------------------------------- ### Pricing method[](https://docs.morpho.org/curate/concepts/vault-as-asset/#pricing-method) One of the main consideration when onboarding an asset is what price it should have. A natural way to price vault shares is by using the exchange rate (supported by the [Morpho Oracle V2](https://github.com/morpho-org/morpho-blue-oracles) ). We summarise here the risks associated with using this pricing method and recommendations when doing so. ### Manipulations & share price changes[](https://docs.morpho.org/curate/concepts/vault-as-asset/#manipulations--share-price-changes) General manipulations of an ERC4626 are detailed in an [Euler article](https://www.euler.finance/blog/exchange-rate-manipulation-in-erc4626-vaults) . Additionally, we should take into account the other possible ways that the share price of a vault can change. We have in the general case: 1. **donations** in general to ERC4626 vaults can cause a sudden price increase. Vaults can have mitigations to this, but most are vulnerable. Morpho Vaults can be affected because of supply on behalf. 2. **rounding errors** (including stealth donations) can change the share price. They are not expected to be significant, including for Morpho Vaults when the vault has a large enough total assets. And the ones specific to each vaults. For example in Morpho vaults: 3. **“economic”**, known scenarios could decrease the share price on Morpho Vaults. They should be accepted by the user for what they are, so they are not considered as blocking. It includes bad debt realization for Morpho Vaults V1.0 (note that public reallocation can be an aggravating factor in this scenario) and forced market removal. ### Conclusions[](https://docs.morpho.org/curate/concepts/vault-as-asset/#conclusions) The price change by donation causes a price increase, so it naturally is an issue for listing a vault as a loan asset. In particular, it leads to: * the possibility of a future attack like the Cream hack, as soon as the position of those shares is priced * liquidations having an extra incentive that is extremely difficult to mitigate, resulting in borrowers taking unpredictable risks (or not joining at all). **Because of those risks, it is not recommended to list any ERC4626 vault as a loan asset in a Morpho market at the moment.** --- # Manage Vault V2 Roles – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v2/roles/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Manage Vault V2 Roles On this page Chevron Right This tutorial guides you through setting up and managing roles for a **Morpho Vault V2**. A clear understanding and proper assignment of roles are critical for the vault's security, governance, and operational success. The Role Setup Workflow[](https://docs.morpho.org/curate/tutorials-v2/roles/#the-role-setup-workflow) -------------------------------------------------------------------------------------------------------- Setting up roles for a new Vault V2 follows a specific sequence. The `Owner` first assigns the `Curator` and `Sentinels` (actions which are immediate). Then, the `Curator` proposes strategic changes, such as appointing an `Allocator`. Crucially, most of the `Curator`'s actions are **timelocked**. The process for these actions depends on whether a timelock duration is set. Managing Roles via Scripts (Recommended)[](https://docs.morpho.org/curate/tutorials-v2/roles/#managing-roles-via-scripts-recommended) ---------------------------------------------------------------------------------------------------------------------------------------- The official deployment repository handles role management efficiently: **[https://github.com/morpho-org/vault-v2-deployment](https://github.com/morpho-org/vault-v2-deployment) ** ### Scenario 1: Initial Vault Setup (Zero Timelock)[](https://docs.morpho.org/curate/tutorials-v2/roles/#scenario-1-initial-vault-setup-zero-timelock) The `DeployVaultV2.s.sol` script handles the complete initial setup. Here's how it manages roles: Copy `// The script sets the broadcaster as temporary owner and curator VaultV2 vaultV2 = new VaultV2(broadcaster, vaultV1.asset()); vaultV2.setCurator(broadcaster); // Submit allocator role assignments vaultV2.submit(abi.encodeCall(vaultV2.setIsAllocator, (broadcaster, true))); vaultV2.submit(abi.encodeCall(vaultV2.setIsAllocator, (allocator, true))); // Execute immediately (timelock is 0 by default) vaultV2.setIsAllocator(broadcaster, true); vaultV2.setIsAllocator(allocator, true); // After configuration, transfer roles to final addresses vaultV2.setCurator(curator); if (sentinel != address(0)) { vaultV2.setIsSentinel(sentinel, true); } vaultV2.setOwner(owner);` ### Scenario 2: Production Management (Non-Zero Timelock)[](https://docs.morpho.org/curate/tutorials-v2/roles/#scenario-2-production-management-non-zero-timelock) Once a vault has non-zero timelocks, role changes require a two-step process: #### Step 1: Submitting a Role Change[](https://docs.morpho.org/curate/tutorials-v2/roles/#step-1-submitting-a-role-change) Create a script to submit the proposal: **`script/SubmitRoleChange.s.sol`** Copy `pragma solidity 0.8.28; import {Script} from "forge-std/Script.sol"; import {IVaultV2} from "vault-v2/interfaces/IVaultV2.sol"; contract SubmitRoleChange is Script { function run() external { address vaultAddress = vm.envAddress("VAULT_V2_ADDRESS"); address newAllocator = vm.envAddress("NEW_ALLOCATOR_ADDRESS"); IVaultV2 vault = IVaultV2(vaultAddress); vm.startBroadcast(); // Submit the proposal bytes memory data = abi.encodeCall(IVaultV2.setIsAllocator, (newAllocator, true)); vault.submit(data); vm.stopBroadcast(); uint256 timelock = vault.timelock(IVaultV2.setIsAllocator.selector); console.log("Proposal submitted. Execute after", timelock, "seconds"); } }` #### Step 2: Executing the Role Change[](https://docs.morpho.org/curate/tutorials-v2/roles/#step-2-executing-the-role-change) After the timelock expires, execute the change: **`script/ExecuteRoleChange.s.sol`** Copy `pragma solidity 0.8.28; import {Script} from "forge-std/Script.sol"; import {IVaultV2} from "vault-v2/interfaces/IVaultV2.sol"; contract ExecuteRoleChange is Script { function run() external { address vaultAddress = vm.envAddress("VAULT_V2_ADDRESS"); address newAllocator = vm.envAddress("NEW_ALLOCATOR_ADDRESS"); IVaultV2 vault = IVaultV2(vaultAddress); vm.startBroadcast(); // Execute the timelocked action vault.setIsAllocator(newAllocator, true); vm.stopBroadcast(); console.log("Allocator role assigned successfully"); } }` ### Revoking Proposals[](https://docs.morpho.org/curate/tutorials-v2/roles/#revoking-proposals) Curators and Sentinels can revoke pending proposals: Copy `// To revoke a pending proposal bytes memory dataToRevoke = abi.encodeCall(IVaultV2.setIsAllocator, (address, bool)); vault.revoke(dataToRevoke);` Managing Roles via Etherscan[](https://docs.morpho.org/curate/tutorials-v2/roles/#managing-roles-via-etherscan) ------------------------------------------------------------------------------------------------------------------ For manual management, the process mirrors the scripted approach. ### Owner Actions (Immediate)[](https://docs.morpho.org/curate/tutorials-v2/roles/#owner-actions-immediate) As the `Owner`, connect your wallet to the Vault V2 contract on Etherscan and use the `Write Contract` tab to: * Execute `setCurator(address newCurator)` to appoint the Curator. * Execute `setIsSentinel(address account, bool newIsSentinel)` to add or remove Sentinels. * Execute `setOwner(address newOwner)` to transfer ownership. ### Curator Actions (Timelocked)[](https://docs.morpho.org/curate/tutorials-v2/roles/#curator-actions-timelocked) As the `Curator`, connect your wallet to: 1. **Submit the Proposal**: * Use a tool like [Foundry's `cast calldata`](https://book.getfoundry.sh/reference/cast/cast-calldata) to ABI-encode your intended function call (e.g., `setIsAllocator(0x..., true)`). * Call the `submit(bytes)` function with the encoded data. 2. **Wait for the Timelock**: Check `executableAt(bytes data)` to see when execution is allowed. 3. **Execute the Proposal**: After the timelock, **anyone** can call the original function to finalize the change. ### Checking Role Status[](https://docs.morpho.org/curate/tutorials-v2/roles/#checking-role-status) Use the `Read Contract` tab to verify current roles: * `owner()`: Returns the current owner * `curator()`: Returns the current curator * `isAllocator(address)`: Check if an address is an allocator * `isSentinel(address)`: Check if an address is a sentinel --- # Checklist to Validate Vault V1 Configuration – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v1/checklist/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Checklist to Validate Vault V1 Configuration On this page Chevron Right This tutorial provides two comprehensive checklists for validating your vault configuration and integrating them before going live. Vault and Market creation checklist[](https://docs.morpho.org/curate/tutorials-v1/checklist/#vault-and-market-creation-checklist) ------------------------------------------------------------------------------------------------------------------------------------ Below is a Vault and market checklist for you to review after following the previous process. * [ ] Create a new market. * [ ] Verify the market Oracles. * [ ] Set the correct rate at target for the new market. * [ ] Set the dead deposit for the new market. * [ ] Create a 1.1 Morpho Vault. * [ ] Set the correct caps for all listed markets. * [ ] Set the dead deposit for the new vault. * [ ] Check that all listed markets have a dead deposit. * [ ] Set the correct roles and permissions. * [ ] Configure the correct timelock after vault creation. * [ ] Submit a market and vault form for Front End listing (For whitelisted curators only). * [ ] (optional) Submit rewards program and rewards for the new asset. * [ ] List and price your vault on Coingecko. * [ ] List your tokens on Etherscan. * [ ] (optional) Set and configure the Public Allocator. * [ ] Configure your reallocation bot for rate targeting and liquidations. * [ ] Submit a Forum post. Integration checklist[](https://docs.morpho.org/curate/tutorials-v1/checklist/#integration-checklist) -------------------------------------------------------------------------------------------------------- Morpho has multiple integrations will help distribute the vaults and markets you created * [ ] Integrate your Vaults in Superform, IPOR Fusion, lazy [Summer.fi](http://summer.fi/) , Yearn, Beefy * [ ] Integrate your Markets in Defisaver, Contango, Summer.fi --- # Bundler3 & Bundler2 – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/bundlers/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Bundler3 & Bundler2 On this page Chevron Right [← Back to contracts](https://docs.morpho.org/get-started/resources/contracts) Code[](https://docs.morpho.org/get-started/resources/contracts/bundlers/#code) --------------------------------------------------------------------------------- [Bundler3 repository](https://github.com/morpho-org/bundler3) [Bundler2 repository](https://github.com/morpho-org/morpho-blue-bundlers) Bundler3 Structure[](https://docs.morpho.org/get-started/resources/contracts/bundlers/#bundler3-structure) ------------------------------------------------------------------------------------------------------------- ![bundlers3 plot](https://docs.morpho.org/img/bundlers/bundler3-flow.png) 1. The core [`Bundler3`](https://github.com/morpho-org/bundler3/blob/main/src/Bundler3.sol) contract implements `multicall(Call[] calldata bundle)`, where each call is defined by: * **`to`**: Target address * **`data`**: Calldata * **`value`**: Native currency amount * **`skipRevert`**: Flag to skip reverting if this particular call fails * **`callbackHash`**: Specifies the hash used for controlling reentrancy callbacks 2. **Adapters** all inherit from [`CoreAdapter`](https://github.com/morpho-org/bundler3/blob/main/src/adapters/CoreAdapter.sol) , which provides access to the **initiator** (the original caller) via transient storage. This mechanism allows adapters to enforce strict permission checks (e.g. only acting on behalf of the initiator). 3. **Chain-specific adapters**, such as [`EthereumGeneralAdapter1`](https://github.com/morpho-org/bundler3/blob/main/src/adapters/EthereumGeneralAdapter1.sol) , extend the base [`GeneralAdapter1`](https://github.com/morpho-org/bundler3/blob/main/src/adapters/GeneralAdapter1.sol) to support network-specific features (e.g. stETH on Ethereum). 4. **Specialized adapters** target specific integrations: * [`ParaswapAdapter`](https://github.com/morpho-org/bundler3/blob/main/src/adapters/ParaswapAdapter.sol) for DEX aggregation (buy/sell/swaps) * **Migration adapters** for moving user positions between protocols (Aave, Compound, Morpho, etc.) * * * Bundler2 Structure[](https://docs.morpho.org/get-started/resources/contracts/bundlers/#bundler2-structure) ------------------------------------------------------------------------------------------------------------- ![blue-bundlers plot](https://docs.morpho.org/img/bundlers/blue-bundlers.svg) 1. All bundlers inherit from [`BaseBundler`](https://github.com/morpho-org/morpho-blue-bundlers/blob/main/src/BaseBundler.sol) that enables bundling multiple function calls into a single `multicall(bytes[] calldata data)` call to the end bundler contract. 2. Each chain-specific bundler is available under its chain-specific folder (e.g. [`ethereum`](https://github.com/morpho-org/morpho-blue-bundlers/tree/main/src/ethereum) ). 3. Some chain-specific domains are also scoped to the chain-specific folder because they are not expected to be used on any other chain (e.g. DAI and its specific `permit` function is only available on Ethereum - see [`EthereumPermitBundler`](https://github.com/morpho-org/morpho-blue-bundlers/blob/main/src/ethereum/EthereumPermitBundler.sol) . 4. User-end bundlers are provided in each chain-specific folder, instantiating all the intermediary domain-specific bundlers and associated parameters (such as chain-specific protocol addresses, e.g. [`EthereumBundler`](https://github.com/morpho-org/morpho-blue-bundlers/blob/main/src/ethereum/EthereumBundler.sol) ). In November 2022, Uniswap Labs introduced [Permit2](https://blog.uniswap.org/permit2-and-universal-router) , a robust token approval contract designed to standardize and secure token approvals across various smart contracts. By enabling signature-based approvals and efficient management of token allowances, Permit2 significantly enhances the user experience. It reduces transaction costs and bolsters smart contract security by mitigating risks associated with traditional approval methods. The integration of Permit2 is set to benefit the entire DeFi ecosystem. Specifically, the Bundlers, operating within the Morpho V0, V1 and V2 frameworks, leverage Permit2's features to streamline transactions. This integration ensures more secure, cost-effective, and user-friendly operations across these platforms. Discover the full potential of Permit2 and how it revolutionizes token approvals in the [integration guide](https://blog.uniswap.org/permit2-integration-guide) . --- # Manage Vault Roles – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v1/roles/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Manage Vault Roles On this page Chevron Right This tutorial guides you through the process of setting up and managing roles for your Morpho vault. Proper role assignment is crucial for vault operations, governance, and security. Using the Curator App[](https://docs.morpho.org/curate/tutorials-v1/roles/#using-the-curator-app) ---------------------------------------------------------------------------------------------------- To manage your vault's roles, navigate using the left-hand side menu to the Roles section. ![Vault roles management interface](https://docs.morpho.org/img/curators/navigation/roles-1.png) ### Owner Transfer[](https://docs.morpho.org/curate/tutorials-v1/roles/#owner-transfer) The vault owner can transfer ownership to a new address. Click the Transfer button next to the current owner address. The new owner must accept the transfer to complete the process. ### Setting Up Core Roles[](https://docs.morpho.org/curate/tutorials-v1/roles/#setting-up-core-roles) The following roles can be configured through the interface or directly via contract calls. Using Contract Calls[](https://docs.morpho.org/curate/tutorials-v1/roles/#using-contract-calls) -------------------------------------------------------------------------------------------------- ### Set Curator[](https://docs.morpho.org/curate/tutorials-v1/roles/#set-curator) The curator manages market configurations and can submit caps and market removals. Execute `setCurator(0xNewCurator)` * **Parameters:** * `newCurator`: Address of the new curator * **Permissions:** Only owner can execute * **Effect:** Immediate - no timelock required ### Add Allocators[](https://docs.morpho.org/curate/tutorials-v1/roles/#add-allocators) Allocators can reallocate liquidity between markets and manage supply/withdraw queues. Execute `setIsAllocator(0xNewAllocator, true)` * **Parameters:** * `newAllocator`: Address to grant allocator permissions * `isAllocator`: `true` to grant, `false` to revoke * **Permissions:** Only owner can execute * **Effect:** Immediate - can have multiple allocators ### Set Guardian[](https://docs.morpho.org/curate/tutorials-v1/roles/#set-guardian) The guardian can revoke pending operations and provides additional security oversight. Execute `submitGuardian(0xNewGuardian)` * **Parameters:** * `newGuardian`: Address of the new guardian * **Permissions:** Only owner can execute * **Timelock:** If no guardian exists, sets immediately. Otherwise, requires timelock period * **Acceptance:** New guardian must call `acceptGuardian()` after timelock expires ### Configure Fee Structure[](https://docs.morpho.org/curate/tutorials-v1/roles/#configure-fee-structure) Performance fees are collected when vault performance exceeds benchmarks. **Step 1: Set Fee Recipient** Execute `setFeeRecipient(0xFeeRecipient)` **Step 2: Set Fee Rate** Execute `setFee(10000000000000000)` // 1% fee (18 decimal precision) * **Parameters:** * `feeRecipient`: Address to receive performance fees * `fee`: Fee rate in 18-decimal format (1% = 10^16) * **Limits:** Maximum fee is 50% (0.5e18) * **Requirements:** Fee recipient must be set before setting non-zero fee ### Set Skim Recipient[](https://docs.morpho.org/curate/tutorials-v1/roles/#set-skim-recipient) The skim recipient receives rewards and excess tokens allocated to the vault. Execute `setSkimRecipient(0xSkimRecipient)` * **Parameters:** * `skimRecipient`: Address to receive skimmed tokens * **Purpose:** Collects rewards from market participation * **Usage:** Call `skim(tokenAddress)` to transfer accumulated tokens Role Management via Curator App[](https://docs.morpho.org/curate/tutorials-v1/roles/#role-management-via-curator-app) ------------------------------------------------------------------------------------------------------------------------ ![Detailed roles management interface](https://docs.morpho.org/img/curators/navigation/roles-2.png) ### Guardian Changes[](https://docs.morpho.org/curate/tutorials-v1/roles/#guardian-changes) Guardian changes require timelock approval for security: 1. Click **Change** next to the current guardian 2. Enter the new guardian address 3. Submit the transaction - this starts the timelock period 4. Wait for the timelock to expire 5. New guardian must click **Accept** to complete the change ### Curator Management[](https://docs.morpho.org/curate/tutorials-v1/roles/#curator-management) Curator changes are immediate and don't require timelock: 1. Click **Change** next to the current curator 2. Enter the new curator address 3. Submit the transaction - change takes effect immediately ### Allocator Management[](https://docs.morpho.org/curate/tutorials-v1/roles/#allocator-management) **Adding Allocators:** * Click **Add Allocator** in the top right * Enter the allocator address in the popup * Submit the transaction **Adding Public Allocator:** * Click **Add Public Allocator** for one-click integration * This adds the Morpho Public Allocator to your vault **Removing Allocators:** * Click **Remove** on the relevant allocator row * Confirm the transaction Best Practices[](https://docs.morpho.org/curate/tutorials-v1/roles/#best-practices) -------------------------------------------------------------------------------------- * **Owner:** Use a secure multisig wallet for the owner role * **Curator:** Choose experienced DeFi professionals familiar with Morpho markets * **Guardian:** Select a trusted party different from the curator for oversight * **Fee Recipient:** Can be the same as owner or a separate treasury address * **Allocators:** Add the Public Allocator for automated optimizations, plus any custom allocators --- # Manage Allocations (Vaults V1) – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Manage Allocations (Vaults V1) On this page Chevron Right Managing allocations is the core responsibility of the `Allocator` role. It involves strategically moving capital between the vault's enabled markets to optimize for yield, maintain liquidity, and adhere to the risk parameters set by the `Curator`. This guide covers how to manage allocations using two methods: 1. **The Curator App**: An intuitive interface for rebalancing the vault's portfolio. 2. **Direct Contract Calls**: For advanced users and scripted interactions with the powerful `reallocate` function. Method 1: Managing Allocations with the Curator App[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#method-1-managing-allocations-with-the-curator-app) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The Curator App provides a visual and interactive way to rebalance your vault's assets. Navigate to the **Allocation** tab to get started. ### Viewing and Planning Allocations[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#viewing-and-planning-allocations) The main table on this page displays the vault's current, live allocation across all its enabled markets, including the Idle Market. You can customize the table with additional columns to see real-time data like supply caps, utilization, and interest rates. ![Vault allocations interface in the Curator App](https://docs.morpho.org/img/curators/navigation/allocations-1.png) ### Performing a Reallocation[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#performing-a-reallocation) #### Enter Edit Mode[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#enter-edit-mode) Click the **Reallocate** button to make the "New Allocation" column editable. This also reveals several helpful tools at the top right of the table: * **Reset**: Reverts your pending changes back to the vault's live state. * **Simulate**: Analyzes the impact of your proposed reallocation on the vault's overall APY. * **Undo/Redo**: Steps back and forth through your recent changes. ![Entering reallocation edit mode](https://docs.morpho.org/img/curators/navigation/allocations-22.png) #### Define the New Allocation[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#define-the-new-allocation) You can now input your desired allocation for each market. Use the toggle at the top of the column to switch between entering values as percentages (%) or as absolute asset amounts. As you edit, the "Delta" column will show you how much capital will be moved for each market. ![Editing allocations by percentage or absolute amount](https://docs.morpho.org/img/curators/navigation/allocations-2.png) #### Save and Execute[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#save-and-execute) Once you are satisfied with your new allocation strategy, click the **Save** button to initiate the transaction. The app will generate the necessary `reallocate` call for you to confirm in your wallet. If your new allocation doesn't account for 100% of the vault's assets, a popup will prompt you to allocate the small remaining amount to a market of your choice (typically the Idle Market) to ensure no funds are left unallocated. Method 2: Reallocating via Direct Contract Calls[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#method-2-reallocating-via-direct-contract-calls) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- For advanced control and scripting, you can call the `reallocate` function directly on the vault contract. This function is extremely powerful, as it can simultaneously withdraw from some markets and supply to others in a single, gas-efficient transaction. ### Understanding the `reallocate` Function[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#understanding-the-reallocate-function) The function signature is: `reallocate(MarketAllocation[] calldata allocations)` It takes a single argument: an array of `MarketAllocation` structs. Each struct tells the vault how much of the underlying `asset` it should aim to have in a specific market **after** the reallocation is complete. Copy `struct MarketAllocation { MarketParams marketParams; // The full parameters of the target market uint256 assets; // The desired final amount of assets in this market }` ### How `reallocate` Works[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#how-reallocate-works) 1. **Calculates Net Flow**: The function first determines the total amount of assets that need to be withdrawn from markets where the target allocation is _less_ than the current allocation. 2. **Withdraws First**: It performs all necessary withdrawals from the designated markets. 3. **Supplies Second**: It then uses the pool of withdrawn assets to supply to markets where the target allocation is _greater_ than the current allocation. 4. **Balance Check**: The transaction will revert if the total amount supplied does not exactly match the total amount withdrawn. ### Practical Example: Shifting Funds[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#practical-example-shifting-funds) Imagine a vault with 100 WETH, currently allocated as: * Market A: 70 WETH * Idle Market: 30 WETH The Allocator wants to move 20 WETH from Market A to a new, higher-yielding Market B. **The `allocations` array would look like this:** Copy `[ { "marketParams": { ...Market A params... }, "assets": "50000000000000000000" // Target: 50 WETH }, { "marketParams": { ...Market B params... }, "assets": "20000000000000000000" // Target: 20 WETH } ]` **What happens when this is executed?** 1. The vault sees it needs to withdraw `70 - 50 = 20 WETH` from Market A. 2. It withdraws 20 WETH from Market A. 3. It sees it needs to supply `20 - 0 = 20 WETH` to Market B. 4. It supplies the 20 WETH to Market B. 5. The total withdrawn (20) equals the total supplied (20), so the transaction succeeds. The Idle Market was not included, so its balance of 30 WETH remains untouched. ### Best Practice: The "Max" Catcher[](https://docs.morpho.org/curate/tutorials-v1/manage-allocations/#best-practice-the-max-catcher) To ensure that the total supplied always matches the total withdrawn and to avoid failed transactions due to rounding or accrued interest, it is a **critical best practice** to make the last item in your `allocations` array a "catcher." This is typically your Idle Market, with its `assets` parameter set to the maximum possible `uint256` value (`115792089237316195423570985008687907853269984665640564039457584007913129639935`). **Example: Safely shifting 20 WETH from Market A to Market B** Copy `[ { "marketParams": { ...Market A params... }, "assets": "50000000000000000000" // Target: 50 WETH }, { "marketParams": { ...Market B params... }, "assets": "20000000000000000000" // Target: 20 WETH }, { "marketParams": { ...Idle Market params... }, "assets": "115792089237316195423570985008687907853269984665640564039457584007913129639935" // MAX_UINT256 } ]` In this case, the Idle Market will automatically absorb any remaining assets from the withdrawn pool, guaranteeing the transaction succeeds. This is especially useful for fully delisting a market by setting its target `assets` to `0`. --- # Manage Adapters (Vaults V2) – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Manage Adapters (Vaults V2) On this page Chevron Right 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 external yield protocol. As a `Curator`, enabling and managing adapters is how you define your vault's investment universe. This guide will walk you through the process of deploying, listing, and managing adapters, with a focus on two key adapters: 1. **`MorphoVaultV1Adapter`**: Connects your Vault V2 to a Morpho Vault V1. 2. **`MorphoMarketV1Adapter`**: Connects your Vault V2 directly to Morpho V1 markets. Setting Up Your First Adapter: The `MorphoVaultV1Adapter`[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#setting-up-your-first-adapter-the-morphovaultv1adapter) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ A common and powerful strategy is to use a Vault V2 as a "wrapper" around an existing Morpho Vault V1. This is automatically handled by the deployment script. ### Method 1: Setting an Adapter via Script (Recommended)[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#method-1-setting-an-adapter-via-script-recommended) The official deployment repository handles adapter setup automatically: **[https://github.com/morpho-org/vault-v2-deployment](https://github.com/morpho-org/vault-v2-deployment) ** The `DeployVaultV2.s.sol` script includes: Copy `// Deploy MorphoVaultV1Adapter address morphoVaultV1Adapter = address(new MorphoVaultV1Adapter(address(vaultV2), address(vaultV1))); // Submit and execute adapter enablement bytes memory idData = abi.encode("this", morphoVaultV1Adapter); vaultV2.submit(abi.encodeCall(vaultV2.addAdapter, morphoVaultV1Adapter)); vaultV2.addAdapter(morphoVaultV1Adapter); // Set caps for the adapter vaultV2.submit(abi.encodeCall(vaultV2.increaseAbsoluteCap, (idData, type(uint128).max))); vaultV2.submit(abi.encodeCall(vaultV2.increaseRelativeCap, (idData, 1e18))); vaultV2.increaseAbsoluteCap(idData, type(uint128).max); vaultV2.increaseRelativeCap(idData, 1e18); // Set as liquidity adapter vaultV2.setLiquidityAdapterAndData(morphoVaultV1Adapter, bytes(""));` For adding adapters after deployment: **`script/AddAdapter.s.sol`** Copy `pragma solidity 0.8.28; import {Script, console} from "forge-std/Script.sol"; import {IVaultV2} from "vault-v2/interfaces/IVaultV2.sol"; import {MorphoVaultV1Adapter} from "vault-v2/adapters/MorphoVaultV1Adapter.sol"; import {MorphoMarketV1Adapter} from "vault-v2/adapters/MorphoMarketV1Adapter.sol"; contract AddAdapter is Script { function run() external { address vaultAddress = vm.envAddress("VAULT_V2_ADDRESS"); address targetVaultV1 = vm.envAddress("TARGET_VAULT_V1"); IVaultV2 vault = IVaultV2(vaultAddress); vm.startBroadcast(); // Deploy new adapter address newAdapter = address(new MorphoVaultV1Adapter(vaultAddress, targetVaultV1)); // Submit enablement proposal bytes memory enableData = abi.encodeCall(IVaultV2.addAdapter, newAdapter); vault.submit(enableData); // Submit cap increases bytes memory idData = abi.encode("this", newAdapter); vault.submit(abi.encodeCall(IVaultV2.increaseAbsoluteCap, (idData, type(uint128).max))); vault.submit(abi.encodeCall(IVaultV2.increaseRelativeCap, (idData, 1e18))); vm.stopBroadcast(); console.log("Adapter deployed at:", newAdapter); console.log("Proposals submitted. Execute after timelock."); } }` ### Method 2: Setting an Adapter via Etherscan[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#method-2-setting-an-adapter-via-etherscan) #### 1\. Deploy the Adapter[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#1-deploy-the-adapter) For `MorphoVaultV1Adapter`: 1. Deploy the contract with constructor parameters: * `_parentVault`: Your Vault V2 address * `_morphoVaultV1`: Target Vault V1 address For `MorphoMarketV1Adapter`: 1. Deploy with: * `_parentVault`: Your Vault V2 address * `_morpho`: Morpho V1 contract address #### 2\. Enable the Adapter[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#2-enable-the-adapter) 1. As Curator, encode: `abi.encodeCall(IVaultV2.addAdapter, (adapterAddress))`. 2. Call `submit(bytes)` with the encoded data. 3. After timelock, call `addAdapter(adapterAddress)`. #### 3\. Set Risk Caps[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#3-set-risk-caps) The adapter's ID is computed as: Copy `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%) #### 4\. Set as Liquidity Adapter (if needed)[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#4-set-as-liquidity-adapter-if-needed) As Allocator, call: Copy `setLiquidityAdapterAndData(adapterAddress, bytes(""))` Working with MorphoMarketV1Adapter[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#working-with-morphomarketv1adapter) ----------------------------------------------------------------------------------------------------------------------------------------- When allocating to Morpho V1 markets directly: Copy `// Prepare market parameters MarketParams memory marketParams = MarketParams({ loanToken: loanTokenAddress, collateralToken: collateralTokenAddress, oracle: oracleAddress, irm: irmAddress, lltv: lltv }); // Allocate as Allocator bytes memory data = abi.encode(marketParams); vault.allocate(morphoMarketV1Adapter, data, amount);` Managing Adapter Caps[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#managing-adapter-caps) --------------------------------------------------------------------------------------------------------------- Each adapter has associated IDs for risk management: * **MorphoVaultV1Adapter**: Single ID based on `keccak256(abi.encode("this", adapterAddress))` * **MorphoMarketV1Adapter**: Three IDs: * Adapter ID: `keccak256(abi.encode("this", adapterAddress))` * Collateral ID: `keccak256(abi.encode("collateralToken", collateralAddress))` * Market ID: `keccak256(abi.encode("this/marketParams", adapterAddress, marketParams))` Sentinels can decrease caps immediately: Copy `vault.decreaseAbsoluteCap(idData, newLowerCap); vault.decreaseRelativeCap(idData, newLowerRelativeCap);` Delisting an Adapter[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#delisting-an-adapter) ------------------------------------------------------------------------------------------------------------- To delist: 1. **Deallocate All Funds**: Copy `vault.deallocate(adapterAddress, data, totalAllocated);` 2. **Submit Delisting Proposal** (as Curator): Copy `bytes memory data = abi.encodeCall(IVaultV2.removeAdapter, (adapterAddress)); vault.submit(data);` 3. **Execute After Timelock**: Copy `vault.removeAdapter(adapterAddress);` Setting Force Deallocate Penalty[](https://docs.morpho.org/curate/tutorials-v2/listing-adapters/#setting-force-deallocate-penalty) ------------------------------------------------------------------------------------------------------------------------------------- To enable emergency withdrawals with a penalty: Copy `// 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% penalty` --- # Manage Markets & Liquidity (Vaults V1) – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Manage Markets & Liquidity (Vaults V1) On this page Chevron Right As a curator for a Morpho Vault V1, your primary responsibilities are to manage which markets the vault can supply to, set risk limits via supply caps, and organize the flow of capital using supply and withdraw queues. This guide provides a comprehensive overview of how to perform these actions using two methods: 1. **The Curator App**: A user-friendly interface for most management tasks. 2. **Direct Contract Calls**: For advanced users or scripted interactions via Etherscan. Managing Supply Caps[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#managing-supply-caps) ----------------------------------------------------------------------------------------------------------- Supply caps are the primary tool for controlling a vault's risk exposure to any single Morpho Market. ### Using the Curator App[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#using-the-curator-app) Navigate to the **Caps** tab in the Curator App to view and manage all active and pending market caps. ![Morpho Vault V1 supply caps interface](https://docs.morpho.org/img/curators/navigation/caps-1.png) #### Modifying or Adding a New Cap[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#modifying-or-adding-a-new-cap) ##### Click "+ New" Button[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#click--new-button) Click the "+ New" button in the top right to open the market selection modal. ![Select a market to set a cap](https://docs.morpho.org/img/curators/navigation/caps-2.png) ##### Select a Market and Set the Cap[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#select-a-market-and-set-the-cap) Choose the market you want to enable or modify. Set the desired **Supply Cap** value and click `Submit New Cap`. Setting a non-zero cap for the first time will enable the market in your vault. ![Submitting a new supply cap](https://docs.morpho.org/img/curators/navigation/caps-5.png) ##### Wait for the Timelock and Accept[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#wait-for-the-timelock-and-accept) Increasing a cap is a timelocked action. After submitting, the proposal will appear in the **Pending** tab. Once the timelock expires (shown under "Estimated Valid At"), you must click **Accept** to finalize the change. Decreasing a cap is instant. ![Accepting a pending cap change](https://docs.morpho.org/img/curators/navigation/caps-6.png) ### Using Direct Contract Calls[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#using-direct-contract-calls) #### 1\. Submit the Cap (`submitCap`)[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#1-submit-the-cap-submitcap) Execute `submitCap` with the market's parameters and the desired cap amount. The `newSupplyCap` should be in the native decimals of the loan token. ![Etherscan interface for submitCap](https://docs.morpho.org/img/metamorpho/submit-cap.png) Submitting a cap via Etherscan. #### 2\. Accept the Cap (`acceptCap`)[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#2-accept-the-cap-acceptcap) After the timelock period expires, anyone can call `acceptCap` with the same market parameters to finalize the change. ![Etherscan interface for acceptCap](https://docs.morpho.org/img/metamorpho/accept-cap.png) Accepting a cap via Etherscan. Managing Queues[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#managing-queues) ------------------------------------------------------------------------------------------------- The Supply and Withdraw Queues dictate the logic for capital allocation. The `Allocator` role is responsible for their management. ### Using the Curator App[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#using-the-curator-app-1) Navigate to the **Queues** section to view and manage your vault's queues. ![Morpho Vault V1 queues interface](https://docs.morpho.org/img/curators/navigation/queue-1.png) #### Reordering a Queue[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#reordering-a-queue) 1. Click the **Edit** button for the queue you wish to modify. 2. **Drag and drop** the market cards into your desired order. 3. Click **Save** and confirm the transaction. ![Reordering a queue by dragging and dropping markets](https://docs.morpho.org/img/curators/navigation/queue-3.png) ### Using Direct Contract Calls[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#using-direct-contract-calls-1) #### Setting the Supply Queue (`setSupplyQueue`)[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#setting-the-supply-queue-setsupplyqueue) To set the supply queue, call `setSupplyQueue` with an array of market `Id`s in the desired order. Copy `# Example input for setSupplyQueue [0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41, 0x_MARKET_ID_2, ...]` #### Updating the Withdraw Queue (`updateWithdrawQueue`)[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#updating-the-withdraw-queue-updatewithdrawqueue) To reorder the withdraw queue, call `updateWithdrawQueue` with an array of numbers representing the **original indexes** of the markets in their **new desired order**. For example, if the original queue was `[MarketA, MarketB, MarketC]` (indexes `[0, 1, 2]`) and you want the new order to be `[MarketC, MarketA, MarketB]`, you would call `updateWithdrawQueue([2, 0, 1])`. Delisting a Market[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#delisting-a-market) ------------------------------------------------------------------------------------------------------- Delisting a market is a multi-step process to ensure funds are safely migrated. ### Standard Delisting Process[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#standard-delisting-process) This process safely removes a market without losing funds. #### 1\. Set Market Cap to Zero[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#1-set-market-cap-to-zero) Instantly set the market's supply cap to `0` using `submitCap`. This prevents new allocations to the market. #### 2\. Reallocate All Liquidity[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#2-reallocate-all-liquidity) Use `reallocate` to move all of the vault's assets out of the target market and into other active markets. Ensure the market to be delisted is **not** included in the `reallocate` call. #### 3\. Update the Withdraw Queue[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#3-update-the-withdraw-queue) Once the market's cap and the vault's allocation are both zero, call `updateWithdrawQueue` with a new index array that omits the delisted market. ### Dust Shares Removal[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#dust-shares-removal) There is an edge case to consider when removing a market. A small amount of dust supply shares could accumulate through usual allocation processes. Reallocating out of these markets via reallocate is not possible because the reallocation is denominated in assets, while the removal of a market from the withdraw queue requires supply shares to be zero. When you have some dust shares on a market that you are trying to remove, **you are forced to supply one unit of an asset on behalf of your vault** to then be able to reallocate and withdraw. For example for USDC it would be 0.000001$ (6 decimals). **Warning**: You must not force remove a market if this edge case occurs: * in V1.0 force-removing it makes share price goes down instantly and will go up instantly if you re-enable the market. * in V1.1, force-removing it creates a bad debt in the vault instantly and will not go away if you re-enable it (instead, the share price will go up, but the same hole will be present). #### Remove dust shares via the Curator App V1 (Ethereum mainnet and Base only)[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#remove-dust-shares-via-the-curator-app-v1-ethereum-mainnet-and-base-only) #### 1\. Head to the Emergency page[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#1-head-to-the-emergency-page) Click on the "Dust Shares Removal" `start` button. ![Reordering a queue by dragging and dropping markets](https://docs.morpho.org/img/curators/tutorials/dust-shares-removal-app-1.png) #### 2\. Choose the targeted market[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#2-choose-the-targeted-market) ![Reordering a queue by dragging and dropping markets](https://docs.morpho.org/img/curators/tutorials/dust-shares-removal-app-2.png) #### 3\. Follow the app[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#3-follow-the-app) The flow will require to: * Approve the Bundler V2 * Donate 1 unit of the asset on behalf of the vault * Remove dust by reallocating ![Reordering a queue by dragging and dropping markets](https://docs.morpho.org/img/curators/tutorials/dust-shares-removal-app-3.png) #### Remove dust shares using direct contract calls[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#remove-dust-shares-using-direct-contract-calls) For other chains than Ethereum and Base, you will have to follow the same steps as described above but interactign at contract directly (via script or explorer). #### 1\. Approve the [Morpho contract](https://docs.morpho.org/get-started/resources/addresses#morpho-v1-contracts) and supply 1 unit of asset in the market on behalf of the vault.[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#1-approve-the-morpho-contract-and-supply-1-unit-of-asset-in-the-market-on-behalf-of-the-vault) See contract spec of the `supply` function [here](https://docs.morpho.org/get-started/resources/contracts/morpho#supply) . #### 2\. You can then `reallocate` liquidity out of the market[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#2-you-can-then-reallocate-liquidity-out-of-the-market) See how to interact at contract level [here](https://docs.morpho.org/curate/tutorials-v1/manage-allocations#method-2-reallocating-via-direct-contract-calls) ### Emergency Market Removal[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#emergency-market-removal) This process should only be used if a market is malfunctioning and funds cannot be safely reallocated. #### 1\. Submit Market for Removal[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#1-submit-market-for-removal) As the `Curator`, call `submitMarketRemoval` with the parameters of the market to be force-removed. #### 2\. Wait for the Timelock[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#2-wait-for-the-timelock) A timelock period begins, allowing users to react. #### 3\. Update the Withdraw Queue[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#3-update-the-withdraw-queue-1) After the timelock expires, the `Allocator` can call `updateWithdrawQueue` to remove the market, even if it still contains vault assets. ### Delisting Process Summary[](https://docs.morpho.org/curate/tutorials-v1/manage-markets/#delisting-process-summary) For safe market delisting: 1. Remove the market from the supply queue 2. Reduce the market cap to zero 3. Reallocate all funds from the market to other markets 4. Remove the market from the withdraw queue For emergency situations: 1. Submit market removal 2. Wait for timelock to elapse 3. Update the withdraw queue Always prioritize the safety of depositor funds and provide clear communication throughout the delisting process. --- # Set the Rate at Target – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-market-v1/setting-rate/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Set the Rate at Target On this page Chevron Right This tutorial guides you through the process of setting and managing interest rates for your new markets: ![Setting Rates](https://docs.morpho.org/img/curators/setting-rates.png) Understanding Rate Mechanics[](https://docs.morpho.org/curate/tutorials-market-v1/setting-rate/#understanding-rate-mechanics) -------------------------------------------------------------------------------------------------------------------------------- The Interest Rate Model (IRM) follows specific rules that market creators should understand: | Category | Condition | Rate Change | | --- | --- | --- | | **Instantaneous Changes** | 90% → 0% Utilization | Rate ÷4 | | | 0% → 90% Utilization | Rate ×4 | | | 90% → 100% Utilization | Rate ×4 | | | 100% → 90% Utilization | Rate ÷4 | | **Time-Based Changes** | At 0% Utilization | Rate halves every 5 days | | | At 100% Utilization | Rate doubles every 5 days | | | At 90% Utilization | Rate remains constant | | **Market Creation** | Initial State | 4% APR at 90% utilization | | | Without Activity | Starts at 0% utilization | Best Practices for Rate Setting[](https://docs.morpho.org/curate/tutorials-market-v1/setting-rate/#best-practices-for-rate-setting) -------------------------------------------------------------------------------------------------------------------------------------- ### Initial Market Setup[](https://docs.morpho.org/curate/tutorials-market-v1/setting-rate/#initial-market-setup) * The market starts with 0% utilization despite having a target rate of 4% APR at 90% utilization * Without activity, rates will continuously decrease (halving every 5 days) * To prevent this, seed the market immediately after creation ### Targeting Specific Rates[](https://docs.morpho.org/curate/tutorials-market-v1/setting-rate/#targeting-specific-rates) * To increase rates: Set utilization above 90% * To decrease rates: Set utilization below 90% * Avoid 100% utilization as rates will double every 5 days * Plan rate adjustments in advance due to the time-based mechanics ### Avoiding Liquidity Traps[](https://docs.morpho.org/curate/tutorials-market-v1/setting-rate/#avoiding-liquidity-traps) * Low rates can create liquidity traps where: * Lenders are discouraged from depositing * Borrowers can't access liquidity due to insufficient deposits * Maintain healthy rates from market launch to ensure proper market function For more details: * IRM Documentation: [Concept IRM Doc](https://docs.morpho.org/learn/concepts/irm) * Implementation: [Morpho V1 IRM on GitHub](https://github.com/morpho-org/morpho-blue-irm) --- # Gates in Morpho Vaults – Morpho Docs [Skip to content](https://docs.morpho.org/curate/concepts/gates/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Gates in Morpho Vaults On this page Chevron Right Morpho Vaults (V1 and V2) support different mechanisms to restrict access to deposits, withdrawals, and transfers. Vault V2 introduces **first-class gates** as external contracts with timelock and abdication guarantees, while Vault V1.1 achieves gating operationally by manipulating the `supplyQueue` and market caps. High-Level Comparison[](https://docs.morpho.org/curate/concepts/gates/#high-level-comparison) ------------------------------------------------------------------------------------------------ | Aspect | Vault V1.1 | Vault V2 | | --- | --- | --- | | **Native Gates** | ❌ None (must use supplyQueue + caps) | ✅ Four explicit gates (receive/send shares, receive/send assets) | | **Granularity** | Coarse: deposits only (via `supplyQueue`) | Fine: deposits, withdrawals, transfers, fee accrual | | **Timelock** | Caps increases are timelocked (24h–2w) | All gate changes timelocked (configurable, e.g. up to 3 weeks) | | **Abdication** | ❌ Not supported | ✅ Supported (permanent permissionless or permanently gated) | | **Atomic batching** | ✅ `multicall` allows open–deposit–close | ✅ `multicall` supported but rarely needed for gates | | **Intended use cases** | Simple whitelisting of suppliers | Compliance, allowlists, permissioned transfers | Gates in Vault V2[](https://docs.morpho.org/curate/concepts/gates/#gates-in-vault-v2) ---------------------------------------------------------------------------------------- ### Executive Summary[](https://docs.morpho.org/curate/concepts/gates/#executive-summary) Gates in Vault V2 are external smart contracts that provide **access control and compliance mechanisms** for vault operations. They enable selective permissions for share transfers, asset deposits, and asset withdrawals while making it possible to maintain the vault's non-custodial guarantees. Gates are **optional** (if not set, operations are unrestricted) and can be **timelocked** for security. ### Core Architecture[](https://docs.morpho.org/curate/concepts/gates/#core-architecture) #### Four Gate Types[](https://docs.morpho.org/curate/concepts/gates/#four-gate-types) ![Gates in Vault V2](https://docs.morpho.org/img/curators/gates/gates-vaults-v2.png) Vault V2 implements a **four-gate system** addressing different operational vectors: #### 1\. **Receive Shares Gate** (`receiveSharesGate`)[](https://docs.morpho.org/curate/concepts/gates/#1-receive-shares-gate-receivesharesgate) * **Interface**: `IReceiveSharesGate` with `canReceiveShares(address)` (TODO: redirect to the code) * **Controls**: Who can receive vault shares * **Operations**: * `deposit()`, `mint()` → checks `canReceiveShares(onBehalf)` * `transfer()`, `transferFrom()` → checks `canReceiveShares(to)` * Performance/management fee accrual → checks `canReceiveShares(feeRecipient)` * **⚠️ Critical Risk**: Can prevent depositors from getting back shares deposited on other contracts. Note that if the gate **reverts** instead of returning `false`, it can cause a **denial of service (DoS)** across core vault operations. #### 2\. **Send Shares Gate** (`sendSharesGate`)[](https://docs.morpho.org/curate/concepts/gates/#2-send-shares-gate-sendsharesgate) * **Interface**: `ISendSharesGate` with `canSendShares(address)` * **Controls**: Who can send vault shares * **Operations**: * `withdraw()`, `redeem()` → checks `canSendShares(onBehalf)` * `transfer()`, `transferFrom()` → checks `canSendShares(from)` * **⚠️ Critical Risk**: Can lock users out of exiting the vault or prevent depositors from getting back shares deposited on other contracts #### 3\. **Receive Assets Gate** (`receiveAssetsGate`)[](https://docs.morpho.org/curate/concepts/gates/#3-receive-assets-gate-receiveassetsgate) * **Interface**: `IReceiveAssetsGate` with `canReceiveAssets(address)` * **Controls**: Who can receive underlying assets from the vault * **Operations**: * `withdraw()`, `redeem()` → checks `canReceiveAssets(receiver)` * **Special Rule**: Vault itself (`address(this)`) always bypasses this gate * **⚠️ Critical Risk**: Can prevent people from receiving their assets upon withdrawals #### 4\. **Send Assets Gate** (`sendAssetsGate`)[](https://docs.morpho.org/curate/concepts/gates/#4-send-assets-gate-sendassetsgate) * **Interface**: `ISendAssetsGate` with `canSendAssets(address)` * **Controls**: Who can deposit underlying assets into the vault * **Operations**: * `deposit()`, `mint()` → checks `canSendAssets(msg.sender)` * **Non-critical**: Cannot block users' funds, while still being able to gate supplies ### Technical Implementation Deep Dive[](https://docs.morpho.org/curate/concepts/gates/#technical-implementation-deep-dive) #### Gate Checking Logic[](https://docs.morpho.org/curate/concepts/gates/#gate-checking-logic) Copy `// From VaultV2.sol - Gate validation functions function canReceiveShares(address account) public view returns (bool) { return receiveSharesGate == address(0) || IReceiveSharesGate(receiveSharesGate).canReceiveShares(account); } function canSendShares(address account) public view returns (bool) { return sendSharesGate == address(0) || ISendSharesGate(sendSharesGate).canSendShares(account); } function canReceiveAssets(address account) public view returns (bool) { return account == address(this) || receiveAssetsGate == address(0) || IReceiveAssetsGate(receiveAssetsGate).canReceiveAssets(account); } function canSendAssets(address account) public view returns (bool) { return sendAssetsGate == address(0) || ISendAssetsGate(sendAssetsGate).canSendAssets(account); }` #### Critical Implementation Requirements[](https://docs.morpho.org/curate/concepts/gates/#critical-implementation-requirements) Gates MUST be designed knowing it should never revert, returning always boolean values. Also gates should not use a malicious amount of gas (like something close to the block size). ### Governance and Security Model[](https://docs.morpho.org/curate/concepts/gates/#governance-and-security-model) #### Timelock Protection[](https://docs.morpho.org/curate/concepts/gates/#timelock-protection) Gates follow the vault's timelock system: Copy `// Curator functions for gate management (timelockable) function setReceiveSharesGate(address newReceiveSharesGate) external { timelocked(); receiveSharesGate = newReceiveSharesGate; emit EventsLib.SetReceiveSharesGate(newReceiveSharesGate); } function setSendSharesGate(address newSendSharesGate) external { timelocked(); sendSharesGate = newSendSharesGate; emit EventsLib.SetSendSharesGate(newSendSharesGate); } function setReceiveAssetsGate(address newReceiveAssetsGate) external { timelocked(); receiveAssetsGate = newReceiveAssetsGate; emit EventsLib.SetReceiveAssetsGate(newReceiveAssetsGate); } function setSendAssetsGate(address newSendAssetsGate) external { timelocked(); sendAssetsGate = newSendAssetsGate; emit EventsLib.SetSendAssetsGate(newSendAssetsGate); }` #### The Two Types of Permanent Guarantees with Gate Abdication[](https://docs.morpho.org/curate/concepts/gates/#the-two-types-of-permanent-guarantees-with-gate-abdication) Copy `// Example: Permanently disable receive shares gate changes vault.abdicateSubmit(IVaultV2.setReceiveSharesGate.selector);` The `abdicateSubmit()` function allows a curator to make an irreversible commitment regarding a vault's configuration, providing users with permanent guarantees. When applied to gates, this creates two distinct and powerful outcomes: ensuring a vault is either permanently permissionless or permanently governed by a fixed set of rules: #### Type 1. The Permanently Ungated Vault (Abdicating to Zero)[](https://docs.morpho.org/curate/concepts/gates/#type-1-the-permanently-ungated-vault-abdicating-to-zero) This strategy provides the strongest guarantee of permissionless access. * **Goal:** To ensure a vault can never have a specific type of gate imposed on it. * **How it Works:** The curator first ensures the target gate address is set to address(0) (disabling it). They then call abdicateSubmit on that gate's setter function (e.g., setReceiveSharesGate). * **Result:** This action permanently locks the gate address to address(0). No one can ever set a gate contract for that function in the future. This is a powerful tool for creating truly decentralized vaults where users are assured that access rules will never be introduced. #### Type 2. The Permanently Gated Vault (Abdicating to a Non-Zero Gate)[](https://docs.morpho.org/curate/concepts/gates/#type-2-the-permanently-gated-vault-abdicating-to-a-non-zero-gate) This strategy is designed for vaults that must adhere to a fixed, unchangeable set of compliance rules. * **Goal:** To lock a vault into a specific, non-modifiable access control policy. * **How it Works:** The curator sets the gate to the address of a deployed gate contract and then calls abdicateSubmit on the setter function. * **Result:** The vault becomes permanently bound to that gate contract. The rules defined within that contract can never be altered by changing the gate address. **Crucial Security Consideration:** This guarantee is only meaningful if the gate contract itself has **immutable behavior**. If the gate contract contains administrative functions that allow an owner to modify its rules (e.g., change a whitelist), then abdicating simply transfers the power to control access from the vault's curator to the gate's administrator. For a true permanent guarantee, the gate contract must be designed without such administrative controls, or its ownership must be renounced. ### Bundler Example **Integration**[](https://docs.morpho.org/curate/concepts/gates/#bundler-example-integration) Ref: [https://github.com/morpho-org/vault-v2/blob/main/test/examples/GateExample.sol](https://github.com/morpho-org/vault-v2/blob/main/test/examples/GateExample.sol) (unaudited example) Copy `// From GateExample.sol - Handles Bundler3 operations contract GateExample is IReceiveSharesGate, ISendSharesGate, IReceiveAssetsGate, ISendAssetsGate { ... mapping(address => bool) public isBundlerAdapter; mapping(address => bool) public whitelisted; ... function whitelistedOrHandlingOnBehalf(address account) internal view returns (bool) { return whitelisted[account] || (isBundlerAdapter[account] && whitelisted[IBundlerAdapter(account).BUNDLER3().initiator()]); } function canSendShares(address account) external view returns (bool) { return whitelistedOrHandlingOnBehalf(account); } function canReceiveShares(address account) external view returns (bool) { return whitelistedOrHandlingOnBehalf(account); } function canReceiveAssets(address account) external view returns (bool) { return whitelistedOrHandlingOnBehalf(account); } function canSendAssets(address account) external view returns (bool) { return whitelistedOrHandlingOnBehalf(account); } ... }` ### Special Cases and Edge Conditions[](https://docs.morpho.org/curate/concepts/gates/#special-cases-and-edge-conditions) #### Vault Self-Operations[](https://docs.morpho.org/curate/concepts/gates/#vault-self-operations) The vault itself (`address(this)`) is **always allowed** to receive assets, regardless of the `receiveAssetsGate` configuration. This prevents the vault from blocking its own internal operations: Copy `function canReceiveAssets(address account) public view returns (bool) { return account == address(this) || // Vault always bypasses receiveAssetsGate == address(0) || IReceiveAssetsGate(receiveAssetsGate).canReceiveAssets(account); }` #### Fee Recipient Gate Checks[](https://docs.morpho.org/curate/concepts/gates/#fee-recipient-gate-checks) **Important**: If a gate is set and reverts for fee recipients when fees are non-zero, interest accrual will revert. This makes proper gate configuration critical for vault operation. ### Impact on Non-Custodial Guarantees[](https://docs.morpho.org/curate/concepts/gates/#impact-on-non-custodial-guarantees) #### Force Deallocate Mechanism[](https://docs.morpho.org/curate/concepts/gates/#force-deallocate-mechanism) Copy `function forceDeallocate(address adapter, bytes memory data, uint256 assets, address onBehalf) external returns (uint256)` This function allows users to perform in-kind redemptions by: 1. Flashloaning liquidity 2. Supplying to an adapter's market 3. Withdrawing liquidity through `forceDeallocate` 4. Repaying the flashloan More details are provided [here](https://docs.morpho.org/learn/concepts/vault-v2#are-morpho-vaults-v2-non-custodial) . ### Testing Considerations[](https://docs.morpho.org/curate/concepts/gates/#testing-considerations) The codebase includes comprehensive gate testing: * `GateExampleTest.sol` - Tests the reference implementation (Disclaimer: this should not be used in production as is). * `GatingTest.sol` - Tests all gate integration points * Tests verify proper error handling for each gate type * Tests confirm vault self-operations bypass receive assets gate Gates in Vault V1[](https://docs.morpho.org/curate/concepts/gates/#gates-in-vault-v1) ---------------------------------------------------------------------------------------- Vault V1.1 does not include first-class gates. Instead, access control can be emulated by **playing with the `supplyQueue` and market caps**, combined with `multicall`. This provides a practical gating mechanism for suppliers. ### Key Mechanics[](https://docs.morpho.org/curate/concepts/gates/#key-mechanics) * **Deposits only work if the `supplyQueue` is non-empty**. If empty, `deposit` reverts and the vault is effectively closed. * **Allocator role** can update the queue at any time (no timelock). * A market must have a **non-zero cap** to appear in the queue. * **Cap increases** are timelocked (24h–2w), but **cap decreases** are instant. * The vault supports **`multicall`**, allowing atomic open–deposit–close flows to prevent front-running. ### Tutorial[](https://docs.morpho.org/curate/concepts/gates/#tutorial) #### One-Time Setup[](https://docs.morpho.org/curate/concepts/gates/#one-time-setup) 1. **Deploy** the V1.1 vault (`MetaMorphoV1_1`). 2. **Assign roles**: * Owner → multisig * Curator → multisig (or another trusted address) * Allocator → hot wallet / automation bot that will run the batch transaction 3. **Prepare the market**: ensure cap > 0 (requires timelock if raising). #### Keep the Vault Closed by Default[](https://docs.morpho.org/curate/concepts/gates/#keep-the-vault-closed-by-default) Copy `// Curator or Allocator vault.setSupplyQueue(new MarketParams); // []` No one can deposit, as the queue is empty. #### Open Deposit Window (Privileged Supplier)[](https://docs.morpho.org/curate/concepts/gates/#open-deposit-window-privileged-supplier) Perform an **atomic batch** via `multicall`: 1. Open queue (add target market). 2. Deposit assets. 3. Close queue (reset to empty). #### Example in viem[](https://docs.morpho.org/curate/concepts/gates/#example-in-viem) Copy ``import { createPublicClient, createWalletClient, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { mainnet } from "viem/chains"; import { morphoVaultAbi } from "./abi"; const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const client = createWalletClient({ account, chain: mainnet, transport: http(RPC_URL), }); const VAULT_ADDRESS = "0x..."; const TARGET_MARKET = "0x..."; // market id const AMOUNT = 1_000n * 10n ** 18n; const openQueueCall = { abi: morphoVaultAbi, functionName: "setSupplyQueue", args: [[TARGET_MARKET]], }; const depositCall = { abi: morphoVaultAbi, functionName: "deposit", args: [AMOUNT, account.address], }; const closeQueueCall = { abi: morphoVaultAbi, functionName: "setSupplyQueue", args: [[]], }; await client.writeContract({ address: VAULT_ADDRESS, abi: morphoVaultAbi, functionName: "multicall", args: [[ client.encodeFunctionData(openQueueCall), client.encodeFunctionData(depositCall), client.encodeFunctionData(closeQueueCall), ]], });`` #### Operational Caveats[](https://docs.morpho.org/curate/concepts/gates/#operational-caveats) * **Always batch** open–deposit–close; otherwise, others may front-run deposits. * Keep caps at **0 by default** and raise only when scheduling controlled deposits. * This mechanism gates **suppliers only**; withdrawals remain unaffected. #### Final notes on Vault V1 Gating operation:[](https://docs.morpho.org/curate/concepts/gates/#final-notes-on-vault-v1-gating-operation) * The **supplier must sign the batch** and be the allocator itself. * If you use a Gnosis Safe, craft a Multisend with those three calls and have the Safe execute it. --- # Create a Vault – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v1/vault-creation/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Create a Vault On this page Chevron Right This tutorial guides you through the process of creating and configuring a new vault in the Morpho ecosystem. Morpho Vaults can be created directly via etherscan (or any other explorer) or using scripts or using apps. Using the Curator App[](https://docs.morpho.org/curate/tutorials-v1/vault-creation/#using-the-curator-app) ------------------------------------------------------------------------------------------------------------- To create a new Vault navigate using the left-hand side menu to the Create Vault section. ![Morpho rewards claim interface](https://docs.morpho.org/img/curators/navigation/create-vault.png) By default, the owner of the Vault will be the address connected and submitting the transaction. You can create the Vault with any address and set the ownership to another, overriding the default by simply entering a different address. By default, the Timelock value is set to 1 Day, however Curators can set it to 0 to facilitate the initial setup (ie. adding markets to the vault without waiting for the Timelock.) The Timelock can be increased after the creation of the vault, but it cannot be set to 0 again after creation. The rest of the fields are: * **Asset:** The address of the Vault’s deposit asset - cannot be modified after creation * **Name:** The display name of the Vault, which can be modified after creation * **Symbol:** The ticker of the vault’s receipt token - cannot be modified after creation * **Salt** (optional): A unique value to deterministically generate the Vault’s address (in conjunction with the other parameters) Once the vault is configured with the desired parameters, click on Create Vault to submit the transaction. Using Etherscan[](https://docs.morpho.org/curate/tutorials-v1/vault-creation/#using-etherscan) ------------------------------------------------------------------------------------------------- ### Factory Address[](https://docs.morpho.org/curate/tutorials-v1/vault-creation/#factory-address) Jump into the factory contract. You can find factory addresses on [the Addresses section here](https://docs.morpho.org/get-started/resources/addresses) . ### Fill attributes[](https://docs.morpho.org/curate/tutorials-v1/vault-creation/#fill-attributes) One will have to fill the following attributes: * `initialOwner`: The initial owner of the vault. This address will have the authority to manage the vault's settings and parameters after creation. * `initialTimelock`: The initial duration, in seconds, during which any critical operations (e.g. changing the curator or guardian roles, updating market parameters) are delayed for security reasons. Starting from V1.1, the initial timelock can be set to 0 during vault creation to facilitate the initial configuration. After setup, the timelock must be set within bounds (minimum = 1 day = 86,400 seconds and maximum = 2 weeks = 1,209,600 seconds). * `asset`: The address of the underlying asset (ERC20 token) for which the vault is being created. The vault will manage deposits and withdrawals of this asset. * `name`: The human-readable name of the vault. It is used primarily for display and identification purposes. * `symbol`: The abbreviation or ticker symbol of the vault. This symbol is a shorter way to represent the vault, typically used in interfaces and listings. * `salt`: A unique value used in conjunction with the vault's other parameters to deterministically generate its address through the CREATE2 opcode. This ensures the uniqueness of the vault's address even if other parameters are identical. ![](https://docs.morpho.org/img/metamorpho/vault-creation.png) Vault Creation ### Approve[](https://docs.morpho.org/curate/tutorials-v1/vault-creation/#approve) Approve the transaction, and retrieve the address of your vault. --- # Handling Permissioned Tokens in the Morpho App – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-market-v1/permissioned-assets/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Handling Permissioned Tokens in the Morpho App On this page Chevron Right Some loan assets and collaterals supported by the Morpho protocol are permissioned tokens. These tokens require specific contract whitelisting to function properly in the Morpho app (frontend & SDKs). Indeed, Morpho’s Bundler3 system uses adapters to handle token operations and the main Morpho app and SDK require the general adapter to simulate and execute transactions involving permissioned tokens. If the general adapter is not whitelisted, the bundler flow breaks and users cannot interact with permissioned tokens through the app. Issuer whitelisting requirements[](https://docs.morpho.org/curate/tutorials-market-v1/permissioned-assets/#issuer-whitelisting-requirements) ----------------------------------------------------------------------------------------------------------------------------------------------- To enable a permissioned token to work in the Morpho app, the token issuer must whitelist at token level the following contracts: * `Morpho` — core lending protocol * `GeneralAdapter1` (`EthereumGeneralAdapter1` for Ethereum mainnet)— required for the frontend and SDK to handle permissioned tokens All contracts deployments addresses are available in [the addresses page](https://docs.morpho.org/get-started/resources/addresses) . Without the general adapter whitelisted, the Morpho app cannot simulate or execute user transactions with permissioned tokens. When listing a permissioned token, curators must review and confirm with the asset issuer that the contracts whitelisting is properly implemented. --- # Managing Bad Debt: How-to Guide – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Managing Bad Debt: How-to Guide On this page Chevron Right Overview[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#overview) ----------------------------------------------------------------------------- This guide is designed for Morpho Vaults curators and aims to provide a methodical approach to identifying, processing, and resolving bad debt within the Morpho ecosystem. It clarifies the concepts of unrealized and realized bad debt and outlines the technical and operational steps required for effective remediation. ### Bad Debt Overview[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#bad-debt-overview) As a reminder, the health of a borrower's position can be divided into three main categories, with LTV being Loan-To-Value, LLTV being the Liquidation Loan-To-Value (one of the market parameters) and LIF the Liquidation Incentive Factor: 1. If LTV < LLTV, the position is healthy, and the borrower cannot be liquidated. 2. If LLTV < LTV ≤ 1/LIF, a liquidator can repay part or all of the user's debt and seize part of its collateral. 3. If 1/LIF < LTV, a liquidator can seize all the collateral by repaying only a share of the debt. There is no incentive for the liquidator or borrower to repay the remaining debt. The latter is commonly referred to as bad debt. Under situation 3, bad debt can be categorized into two types: 1. **Unrealized** when the liquidation has not occurred yet, 2. **Realized** when the liquidation has occurred, and the entire collateral position is seized. How Vaults are handling bad debt[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#how-vaults-are-handling-bad-debt) ----------------------------------------------------------------------------------------------------------------------------- In practice, the remaining debt of the liquidated user, at the market level, affects all existing suppliers of the market. Vault V1.0 and V1.1 are part of them, and handle bad debt in different ways. ### Vault V1.0[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#vault-v10) Morpho Vault V1.0 automatically realizes the loss on all existing depositors at the moment of the bad-debt liquidation event. The share price of the vault will instantaneously decrease. Vaults are from a Morpho Market point of view simple users. Their supply shares value post liquidation incurring bad debt in a market they allocated liquidity are worth a bit less than before the liquidation. The entire vault and depositors respectively are impacted proportionally to the proportion of the share the vault has in the market. ### Vault V1.1[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#vault-v11) Morpho Vault V1.1 do not automatically realize the loss on all existing depositors at the moment of the bad-debt liquidation event. The share price will not decrease. The last depositors will face the bad debt unless action is taken. How to cover the bad debt[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#how-to-cover-the-bad-debt) --------------------------------------------------------------------------------------------------------------- Anyone (e.g., a curator or a lender) can decide to cover those bad debt events that have been realized, and this is feasible in different ways depending on the version of the vault. One can call the action to put back some liquidity "Asset injection", which involves supplying methodically sufficient loan tokens to cover the loss in order to: 1. for vault V1.0: restore the vault's share price 2. for vault V1.1: allow any lenders to never get stuck if there was some liquidity shortage. ### Vault V1.0[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#vault-v10-1) #### How to compute the loan token asset lost?[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#how-to-compute-the-loan-token-asset-lost) The `amountLost` is retrievable easily thanks to the liquidation event emitted. After liquidation with bad debt realization, the entire Morpho Market suffered a reduction on `totalSupplyAsset` up to the `badDebtAssets` (in loan token units), retrievable at the `liquidate` event level. Copy `emit EventsLib.Liquidate( id, msg.sender, borrower, repaidAssets, repaidShares, seizedAssets, badDebtAssets, badDebtShares );` Then, one needs to compute in this Morpho Market what was the proportion % (called `proportionPercentage`) of the vault position as the vault is probably not the only supplier into the market. amountLost\=proportionPercentage×badDebtAssetsamountLost = proportionPercentage \\times badDebtAssets amountLost\=proportionPercentage×badDebtAssets #### Which action to execute?[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#which-action-to-execute) The following 3 solutions could be performed: 1. For vault V1.0, one could think about depositing the loan token asset lost (called `AMOUNT_LOST`) by the vault straight into the market, by calling the `supply()` function, and deposit on behalf of the vault address: Copy `// On the Morpho contract function supply( MarketParams, assets=AMOUNT_LOST, shares=0, onBehalf=0x_VAULT_ADDRESS, 0x, )` However, if any new depositor comes between the time the vault suffered from bad debt, and the new loan token provider triggers the supply, this would indeed favor the new user(s) while they should not have been benefiting from this. 2. Deposit on behalf of each user, coming with more gas consumption. 3. Create an airdrop solution favoring the impacted users. ### Vault V1.1[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#vault-v11-1) For vault V1.1, and as stated in the contract, as the bad debt is not realized at the vault level, anyone can compute the amount lost by using the value of lostAssets. #### How to compute the loan token asset lost?[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#how-to-compute-the-loan-token-asset-lost-1) The added loss is `lostAssets_after` - `lostAssets_before`. These values are taken by retrieving the onchain `lostAssets` value before and after the liquidation event. #### Which action to execute?[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#which-action-to-execute-1) It is suggested to supply on behalf of address(1) on the vault. The loan token provider will thus lose the asset, but this will cover the bad debt event and no lenders will ultimately be stuck if they were to withdraw their funds. Copy `// Call the deposit function on the Vault contract like this: function deposit(assets,0x000..0001)` Alternative Approach: Third-Party Insurance Solutions[](https://docs.morpho.org/curate/tutorials-v1/bad-debt/#alternative-approach-third-party-insurance-solutions) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Another alternative for users is to subscribe to third-party insurance solutions (e.g., Nexus Mutual) that could provide coverage against bad debt events. This approach offers a proactive risk curation strategy rather than reactive remediation after bad debt has occurred. This insurance-based approach could potentially replace or complement the manual bad debt coverage methods described above, providing automated protection for vault participants. --- # Emergency Procedures – Morpho Docs [Skip to content](https://docs.morpho.org/curate/emergency/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Emergency Procedures On this page Chevron Right This document outlines procedures for handling emergency situations related to Morpho Vaults, from dealing with unsafe markets to responding to a compromised role. These actions should be executed with extreme care, as they can have significant consequences for the vault and its depositors. Please read the [README](https://github.com/morpho-org/metamorpho/blob/main/README.md) section from the Morpho Vaults repository. Unsafe Market: Soft Deprecation[](https://docs.morpho.org/curate/emergency/#unsafe-market-soft-deprecation) -------------------------------------------------------------------------------------------------------------- This procedure is used when a market is deemed too risky for continued new allocations, but is still functioning correctly, allowing for a graceful exit. ### The Goal[](https://docs.morpho.org/curate/emergency/#the-goal) Safely withdraw all vault funds from the market without incurring losses, and prevent any new capital from being allocated to it. ### Procedure via Direct Contract Calls[](https://docs.morpho.org/curate/emergency/#procedure-via-direct-contract-calls) 1. **Revoke Pending Caps**: If there is a pending cap increase for the market, the `Guardian`, `Curator`, or `Owner` should call `revokePendingCap` to prevent it from being accepted. 2. **Set Cap to Zero**: The `Curator` or `Owner` must immediately call `submitCap` with a `newSupplyCap` of `0`. This is an instant action and prevents new funds from flowing into the market. * **Pro Tip**: To avoid front-running issues, it's best to batch the `revokePendingCap` and `submitCap` calls in a single transaction using a `multicall` function for instance. 3. **Reallocate Liquidity**: The `Allocator` should call `reallocate` to withdraw all available liquidity from the market. If the market is illiquid, this may need to be done in stages as liquidity becomes available. 4. **Update Withdraw Queue**: The `Allocator` should move the market to the beginning of the `withdrawQueue` to ensure any newly available liquidity is captured first. 5. **Complete Delisting**: Once all funds have been withdrawn, the `Allocator` can remove the market entirely from the `withdrawQueue` by calling `updateWithdrawQueue`. ### Procedure via the Curator App[](https://docs.morpho.org/curate/emergency/#procedure-via-the-curator-app) The Curator App streamlines this process with a dedicated "Unsafe Market" emergency flow. ![Morpho Vaults emergency actions interface](https://docs.morpho.org/img/curators/navigation/emergency-1.png) Executing this flow in a single transaction will: 1. Revoke any pending cap changes for the target market. 2. Set the market's supply cap to `0`. 3. Reallocate all _currently available_ liquidity to the vault's designated Idle Market. 4. Move the market to the first position in the `withdrawQueue`. Market Reverts: Forced Removal[](https://docs.morpho.org/curate/emergency/#market-reverts-forced-removal) ------------------------------------------------------------------------------------------------------------ This procedure is for critical situations where a market is malfunctioning (e.g., its functions consistently revert), making it impossible to withdraw funds normally. This action involves accepting the loss of any capital stuck in the market. ### The Goal[](https://docs.morpho.org/curate/emergency/#the-goal-1) Remove a broken market from the vault's accounting to restore normal vault operations, even if it means losing the funds allocated to it. ### Procedure via Direct Contract Calls[](https://docs.morpho.org/curate/emergency/#procedure-via-direct-contract-calls-1) 1. **Set Cap to Zero**: As with a soft deprecation, the `Curator` must first set the market's cap to `0`. 2. **Submit for Removal**: The `Curator` or `Owner` must call `submitMarketRemoval`. This action is **timelocked**. 3. **Wait for Timelock**: The mandatory waiting period must elapse. 4. **Update Withdraw Queue**: After the timelock, the `Allocator` can call `updateWithdrawQueue` to permanently remove the market from the vault's configuration. ### Procedure via the Curator App[](https://docs.morpho.org/curate/emergency/#procedure-via-the-curator-app-1) The "Market Reverts" flow in the Curator App is designed for this scenario. ![Morpho Vaults emergency actions interface](https://docs.morpho.org/img/curators/navigation/emergency-1.png) In a single transaction, this flow will: 1. Revoke any pending cap changes for the market. 2. Set the market's supply cap to `0`. 3. Call `submitMarketRemoval` to begin the timelocked process of forced deprecation. After the timelock expires, the `Allocator` must still manually call `updateWithdrawQueue` to complete the removal. Role Compromise Scenarios[](https://docs.morpho.org/curate/emergency/#role-compromise-scenarios) --------------------------------------------------------------------------------------------------- ### Curator Takeover[](https://docs.morpho.org/curate/emergency/#curator-takeover) If a `Curator` begins acting maliciously (e.g., submitting caps for unsafe markets), the `Owner` must intervene. 1. **Set a New Curator**: The `Owner` should immediately call `setCurator` to transfer control to a new, trusted address. 2. **Revoke Pending Actions**: The new `Curator`, `Owner`, or `Guardian` must call `revokePendingCap` on any malicious proposals submitted by the old curator. 3. **Remediate Accepted Actions**: If a malicious cap was accepted before it could be revoked, the new `Curator` must follow the "Unsafe Market" procedure to safely exit the position. ### Allocator Takeover[](https://docs.morpho.org/curate/emergency/#allocator-takeover) If an `Allocator` acts against the vault's strategy (e.g., by setting improper queues or reallocating funds incoherently), the `Owner` should: 1. **Revoke Allocator Privileges**: Call `setIsAllocator` with the malicious address and `false`. 2. **Correct Queues**: The `Owner` or a trusted `Allocator` must call `setSupplyQueue` and `updateWithdrawQueue` to restore the correct order. 3. **Reallocate Funds**: Call `reallocate` to move funds back into alignment with the vault's intended strategy. --- # Vaults & ERC4626 Mechanics – Morpho Docs [Skip to content](https://docs.morpho.org/build/earn/concepts/vault-mechanics#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Concepts On this page Chevron Right **Morpho Vaults V1.x** and **Morpho Vaults V2** expose the standard [ERC‑4626](https://eips.ethereum.org/EIPS/eip-4626) interface for tokenized vaults. Understanding these mechanics is essential for building robust Earn integrations. ERC4626 Standard[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#erc4626-standard) --------------------------------------------------------------------------------------------------- The ERC‑4626 standard defines four core functions for deposits and withdrawals. ### Core Functions[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#core-functions) #### Deposit[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#deposit) Copy `// Deposit a specific amount of underlying assets. // Example: deposit 10 USDC and receive N vault shares. function deposit(uint256 assets, address receiver) external returns (uint256 shares); // Mint a specific amount of shares. // Example: mint N shares; the corresponding assets are pulled from the user. function mint(uint256 shares, address receiver) external returns (uint256 assets);` #### Withdraw[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#withdraw) Copy `// Withdraw a specific amount of assets. // Example: withdraw 10 USDC; N shares are burned. function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); // Redeem a specific amount of shares for assets. function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);` Assets vs. Shares[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#assets-vs-shares) ---------------------------------------------------------------------------------------------------- **Assets** are the underlying token (e.g., USDC, WETH). **Shares** represent proportional ownership of the vault and typically appreciate as yield accrues. ### Conversions[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#conversions) Copy `// Convert assets to shares (pre‑deposit expectation). const shares = await vault.previewDeposit(assetAmount); // Convert shares to assets at the current rate. const assets = await vault.convertToAssets(shareAmount); // Estimate shares needed to withdraw a target asset amount. const sharesNeeded = await vault.previewWithdraw(assetAmount); // Estimate assets received when redeeming shares. const assetsReceived = await vault.previewRedeem(shareAmount);` Share Price Appreciation[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#share-price-appreciation) ------------------------------------------------------------------------------------------------------------------- Vault performance is reflected in the share price: Copy `// 1 vault share = 1e18 const sharePrice = await vault.convertToAssets(10n ** 18n); // Example: totalAssets grows from 1.0M to 1.1M with 1.0M shares // -> price from $1.00/share to $1.10/share (≈10%)` Inflation Attack Protection[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#inflation-attack-protection) ------------------------------------------------------------------------------------------------------------------------- ERC4626 vaults are susceptible to [share inflation attacks](https://docs.openzeppelin.com/contracts/5.x/erc4626) , where an attacker manipulates the share price to cause rounding losses for subsequent depositors. This affects all ERC4626-compliant implementations. ### The Protection Mechanism[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#the-protection-mechanism) Before interacting with a vault, verify that a **dead deposit** has been made to address `0x000000000000000000000000000000000000dEaD`. This initial deposit establishes a baseline share supply that makes inflation attacks economically unfeasible. **The Check:** Copy `// Verify the vault has adequate dead deposit protection const deadAddress = "0x000000000000000000000000000000000000dEaD"; const deadShares = await vault.balanceOf(deadAddress); // Minimum threshold: 1e9 shares (~$10 equivalent for most assets) if (deadShares < 1_000_000_000n) { throw new Error("Vault lacks adequate inflation protection"); }` **Why 1e9 shares?** This threshold ensures that the cost to manipulate the share price exceeds any potential gain from the attack. The specific value (1e9 shares) is a conservative standard that works across different asset decimals and price points. **Implementation Notes:** * The dead deposit does not need to be made atomically with your interaction * Once established, it cannot be withdrawn (by design) * Both Morpho Vault V1 and V2 should have this protection in place * Curators and vault deployers are responsible for ensuring this protection exists Additional Considerations: Slippage[](https://docs.morpho.org/build/earn/concepts/vault-mechanics#additional-considerations-slippage) ---------------------------------------------------------------------------------------------------------------------------------------- **When to consider slippage protection:** * Share price may shift due to interest accrual or other vault activity between simulation and inclusion * User-facing applications benefit from showing expected vs. actual amounts received **Implementation options:** * **Recommended:** Use **Bundlers** for app integrations—slippage checks are handled automatically * **Alternative:** Implement min-received checks around ERC4626 operations for direct integrations See the [Assets Flow tutorial](https://docs.morpho.org/build/earn/tutorials/assets-flow) for integration examples. --- # Rewards: Developer Resources – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/resources/all#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Resources On this page Chevron Right This page is your central hub for all the tools, links, and data sources you need to integrate Morpho rewards (both Merkl and Legacy URD) into your application. APIs[](https://docs.morpho.org/build/rewards/resources/all#apis) ------------------------------------------------------------------- ### Morpho API (Recommended for Vault/Market Rewards)[](https://docs.morpho.org/build/rewards/resources/all#morpho-api-recommended-for-vaultmarket-rewards) The Morpho API provides integrated rewards data alongside vault and market information. * **GraphQL Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql) * **Documentation**: [Morpho API Docs](https://docs.morpho.org/tools/offchain/api/morpho) * **Rewards Queries**: * [Morpho Markets Rewards](https://docs.morpho.org/tools/offchain/api/rewards#morpho-markets-rewards) * [Morpho Vaults Rewards](https://docs.morpho.org/tools/offchain/api/rewards#morpho-vaults-rewards) **Use Cases:** * Fetch vault APY + rewards APR * Get market reward rates (supply, borrow, collateral) * Combine base yield and rewards in one query * Historical data and time-series queries ### Merkl API (Primary for User Rewards)[](https://docs.morpho.org/build/rewards/resources/all#merkl-api-primary-for-user-rewards) Merkl's REST API for current reward programs and user claimable amounts. * **Base URL**: `https://api.merkl.xyz/v4/` * **Documentation**: [docs.merkl.xyz/integrate-merkl/app](https://docs.merkl.xyz/integrate-merkl/app) * **Key Endpoints**: * User Rewards: `GET /userRewards?user={address}&chainId={chainId}` * Claim Data: `GET /claim?user={address}&chainId={chainId}` **Use Cases:** * Fetch user claimable rewards (current programs) * Get Merkle proofs for claiming * Real-time reward accrual (updates every 8 hours) ### Morpho Rewards API (Legacy URD Programs)[](https://docs.morpho.org/build/rewards/resources/all#morpho-rewards-api-legacy-urd-programs) The Rewards API for historical Morpho URD rewards. * **Base URL**: `https://rewards.morpho.org/v1/` * **API Docs**: [rewards.morpho.org/docs](https://rewards.morpho.org/docs) * **Key Endpoints**: * User Rewards: `GET /users/{address}/rewards` * User Distributions: `GET /users/{address}/distributions` * All Programs: `GET /programs` * Stats: `GET /rewards/stats` **Use Cases:** * Fetch historical/legacy rewards * Get URD claim data (Merkle proofs) * Query past reward programs Smart Contracts[](https://docs.morpho.org/build/rewards/resources/all#smart-contracts) ----------------------------------------------------------------------------------------- ### Merkl Distributor Contracts[](https://docs.morpho.org/build/rewards/resources/all#merkl-distributor-contracts) **Mainnet (Ethereum):** * Address: `0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae` **Other Chains:** * See [Merkl's documentation](https://docs.merkl.xyz/) for all chain deployments **Key Functions:** * `claim(address user, address[] tokens, uint256[] amounts, bytes32[][] proofs)` - Claim rewards ### Morpho URD Contracts[](https://docs.morpho.org/build/rewards/resources/all#morpho-urd-contracts) **Mainnet (Ethereum):** * URD Address: `0x330eefa8a787552DC5cAd3C3cA644844B1E61Ddb` **Other Chains:** * See [Rewards Addresses](https://docs.morpho.org/get-started/resources/addresses#rewards) for all deployments **Key Functions:** * `claim(address account, address reward, uint256 claimable, bytes32[] proof)` - Claim rewards * `claimed(address account, address reward) view returns (uint256)` - Check claimed amount **Repository:** * GitHub: [morpho-org/universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor) ### Contract ABIs[](https://docs.morpho.org/build/rewards/resources/all#contract-abis) **Merkl Distributor ABI:** Copy `[ { "inputs": [ { "name": "user", "type": "address" }, { "name": "tokens", "type": "address[]" }, { "name": "amounts", "type": "uint256[]" }, { "name": "proofs", "type": "bytes32[][]" } ], "name": "claim", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ]` **URD ABI (Claim):** Copy `[ { "inputs": [ { "name": "account", "type": "address" }, { "name": "reward", "type": "address" }, { "name": "claimable", "type": "uint256" }, { "name": "proof", "type": "bytes32[]" } ], "name": "claim", "outputs": [{ "name": "amount", "type": "uint256" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "name": "account", "type": "address" }, { "name": "reward", "type": "address" } ], "name": "claimed", "outputs": [{ "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" } ]` Code Examples & Repositories[](https://docs.morpho.org/build/rewards/resources/all#code-examples--repositories) ------------------------------------------------------------------------------------------------------------------ ### Official Examples[](https://docs.morpho.org/build/rewards/resources/all#official-examples) * **Merkl + Morpho Recipe** (Recommended): * GitHub: [morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe) * A complete Next.js demo showing: * Vault metrics with rewards * User claimable rewards (Merkl + URD) * Claim implementations * TypeScript best practices ### Community Examples[](https://docs.morpho.org/build/rewards/resources/all#community-examples) * **Morpho Lite App**: [morpho-org/morpho-lite-apps](https://github.com/morpho-org/morpho-lite-apps/tree/main/apps/lite) * **Fallback App**: [morpho-org/morpho-blue-offchain-public](https://github.com/morpho-org/morpho-blue-offchain-public/tree/main/apps/fallback) SDKs & Tools[](https://docs.morpho.org/build/rewards/resources/all#sdks--tools) ---------------------------------------------------------------------------------- ### Morpho SDKs[](https://docs.morpho.org/build/rewards/resources/all#morpho-sdks) While there's no dedicated rewards SDK, you can use Morpho's core SDKs for related functionality: * **`@morpho-org/blue-sdk`**: Core SDK for vaults and markets * **`@morpho-org/blue-sdk-viem`**: Viem-based fetchers * **`@morpho-org/simulation-sdk`**: Simulate transactions * **`@morpho-org/bundler-sdk-viem`**: Bundle multiple actions (including claims) **Learn More**: [Morpho SDKs Documentation](https://docs.morpho.org/tools/offchain/sdks/get-started) ### GraphQL Clients[](https://docs.morpho.org/build/rewards/resources/all#graphql-clients) For querying the Morpho API: * **[graphql-request](https://github.com/jasonkuhrt/graphql-request) **: Lightweight GraphQL client * **[Apollo Client](https://www.apollographql.com/docs/react/) **: Full-featured GraphQL client * **[urql](https://formidable.com/open-source/urql/) **: Flexible GraphQL client ### Web3 Libraries[](https://docs.morpho.org/build/rewards/resources/all#web3-libraries) For claiming rewards onchain: * **[viem](https://viem.sh/) **: Modern TypeScript web3 library (recommended) * **[ethers.js](https://docs.ethers.org/) **: Popular web3 library * **[web3.js](https://web3js.readthedocs.io/) **: Classic web3 library External Documentation[](https://docs.morpho.org/build/rewards/resources/all#external-documentation) ------------------------------------------------------------------------------------------------------- ### Merkl[](https://docs.morpho.org/build/rewards/resources/all#merkl) * **Official Docs**: [docs.merkl.xyz](https://docs.merkl.xyz/) * **Integration Guide**: [docs.merkl.xyz/integrate-merkl/app](https://docs.merkl.xyz/integrate-merkl/app) ### Morpho[](https://docs.morpho.org/build/rewards/resources/all#morpho) * **Developer Hub**: [/tools/](https://docs.morpho.org/tools) * **API Documentation**: [/tools/offchain/api/rewards/](https://docs.morpho.org/tools/offchain/api/rewards) Onchain Data Sources[](https://docs.morpho.org/build/rewards/resources/all#onchain-data-sources) --------------------------------------------------------------------------------------------------- * **Morpho Subgraphs**: [/tools/offchain/subgraphs/](https://docs.morpho.org/tools/offchain/subgraphs) * **Merkl Subgraphs**: See [Merkl docs](https://docs.merkl.xyz/) Tutorials & Guides[](https://docs.morpho.org/build/rewards/resources/all#tutorials--guides) ---------------------------------------------------------------------------------------------- ### Getting Started[](https://docs.morpho.org/build/rewards/resources/all#getting-started) * [Rewards Integration Overview](https://docs.morpho.org/build/rewards/get-started) * [Understanding Reward Programs](https://docs.morpho.org/build/rewards/concepts/reward-campaigns) * [Distribution Systems (Merkl vs URD)](https://docs.morpho.org/build/rewards/concepts/distribution-system) ### Step-by-Step Tutorials[](https://docs.morpho.org/build/rewards/resources/all#step-by-step-tutorials) * [Create a Rewards Program](https://docs.morpho.org/build/rewards/tutorials/create-program) * [Fetch Rewards Data](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data) * [Claim Rewards](https://docs.morpho.org/build/rewards/tutorials/claim-rewards) * [Integrate Rewards Display](https://docs.morpho.org/build/rewards/tutorials/integrate-display) ### Advanced[](https://docs.morpho.org/build/rewards/resources/all#advanced) * [Complete Integration Example](https://docs.morpho.org/build/rewards/guides/complete-integration) * [URD Technical Details](https://docs.morpho.org/get-started/resources/contracts/rewards) Support Channels[](https://docs.morpho.org/build/rewards/resources/all#support-channels) ------------------------------------------------------------------------------------------- ### For Integrators[](https://docs.morpho.org/build/rewards/resources/all#for-integrators) * **Technical Questions**: [help.morpho.org](https://help.morpho.org/) ### For Reward Issuers[](https://docs.morpho.org/build/rewards/resources/all#for-reward-issuers) * **Program Creation Help**: [Merkl Docs](https://docs.merkl.xyz/) Monitoring & Analytics[](https://docs.morpho.org/build/rewards/resources/all#monitoring--analytics) ------------------------------------------------------------------------------------------------------ ### Dashboards[](https://docs.morpho.org/build/rewards/resources/all#dashboards) * **Merkl Dashboard**: [merkl.xyz](https://merkl.xyz/) - View active campaigns * **Morpho App**: [app.morpho.org](https://app.morpho.org/) - See rewards on vaults/markets ### Analytics Tools[](https://docs.morpho.org/build/rewards/resources/all#analytics-tools) * **Dune Analytics**: [Morpho Dashboards](https://docs.morpho.org/tools/offchain/dune) * **DefiLlama**: Track TVL and yields across Morpho Governance & Updates[](https://docs.morpho.org/build/rewards/resources/all#governance--updates) -------------------------------------------------------------------------------------------------- ### Morpho Governance[](https://docs.morpho.org/build/rewards/resources/all#morpho-governance) * **Snapshot**: [snapshot.box/#/s\ \ .eth](https://snapshot.box/#/s:morpho.eth) ### Migration Information[](https://docs.morpho.org/build/rewards/resources/all#migration-information) * **MIP 111**: [Snapshot Proposal](https://snapshot.box/#/s:morpho.eth/proposal/0xadf3862d97cf4e8bb84a4b3d5117abe1a9db774e92ad97c65bde22214c0b76c9) - Migration to Merkl Quick Reference[](https://docs.morpho.org/build/rewards/resources/all#quick-reference) ----------------------------------------------------------------------------------------- | Resource | Link | | --- | --- | | **Morpho API** | [api.morpho.org/graphql](https://api.morpho.org/graphql) | | **Merkl API** | [api.merkl.xyz/v4](https://api.merkl.xyz/v4/) | | **Rewards API** | [rewards.morpho.org](https://rewards.morpho.org/) | | **Example Code** | [github.com/morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe) | | **Merkl Docs** | [docs.merkl.xyz](https://docs.merkl.xyz/) | | **URD Contracts** | [github.com/morpho-org/universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor) | Need Help?[](https://docs.morpho.org/build/rewards/resources/all#need-help) ------------------------------------------------------------------------------ If you can't find what you're looking for, reach out via: * **Chat**: [help.morpho.org](https://help.morpho.org/) --- # Set Up Public Allocator – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Set Up Public Allocator On this page Chevron Right Overview[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#overview) ------------------------------------------------------------------------------------- As the vault curator of a Morpho Vault, you can designate the `PublicAllocator` address as an allocator of the vault. This will allow borrowers or Morpho's interface to trigger reallocations, amplifying the available liquidity for end users while limiting the flow of tokens that can be supplied or withdrawn from a market listed in the vault. This provides power for the curator to: * Enable interface/advanced borrowers to trigger reallocations * Amplifies available liquidity * Controls token flow limits Prerequisites[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#prerequisites) ----------------------------------------------------------------------------------------------- * You must be a curator of a Morpho Vault * Access to the Morpho Vault contract Setup Steps[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#setup-steps) ------------------------------------------------------------------------------------------- ### Enable the Public Allocator[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#enable-the-public-allocator) As a `curator` of your own vault, provide the [`allocator`](https://docs.morpho.org/curate/concepts/roles) role to the `PublicAllocator` [contract address](https://docs.morpho.org/get-started/resources/addresses) as described in [this section](https://docs.morpho.org/curate/tutorials-v2/roles) , via the `setIsAllocator` function (0xNewAllocator, true). ![](https://docs.morpho.org/img/public-allocator/setIsAllocator.png) Providing the `allocator` role to the `PublicAllocator` contract on the Morpho Vault contract ### Configure Basic Settings[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#configure-basic-settings) #### A. Set Admin (Optional)[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#a-set-admin-optional) By default, only the owner of the vault can configure the `PublicAllocator` for a given vault. However, the owner can appoint an additional admin by triggering the `setAdmin` function. #### B. Set Fee (Optional)[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#b-set-fee-optional) The `PublicAllocator` can set a fee to charge on every reallocation. The fee is paid in ETH and can be changed at any time by the owner of the vault or the admin by triggering the `setFee` function. This fee prevents griefing attacks and helps the vault curators to cover the gas costs reallocations in the case the reallocation through the `PublicAllocator` has created an imbalance. ### Configure Flow Caps[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#configure-flow-caps) Flow caps determine the maximum amount of tokens that can be supplied or withdrawn from a market listed in the vault. The flow caps can be set by the owner of the vault or the admin for a specific market by triggering the `setFlowCap` function. A flow cap is composed of the `maxIn` and `maxOut` in this order. The `maxIn` is the maximum amount of tokens that can be supplied to a market and the `maxOut` is the maximum amount of tokens that can be withdrawn from a market. For example, if amount `x` is withdrawn from a market during reallocation, the market's `maxIn` increases by `x`, while `maxOut` decreases by `x`. Conversely, if `x` is supplied to the market, `maxIn` decreases by `x` and `maxOut` increases by `x`. This mechanism helps maintain balance and limits excessive token flows in and out of the market. Example Configuration[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#example-configuration) --------------------------------------------------------------------------------------------------------------- Security Considerations[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#security-considerations) ------------------------------------------------------------------------------------------------------------------- * Flow cap limits protect against excessive token movements * Fees prevent griefing attacks * Admin controls provide flexibility while maintaining security Next Steps[](https://docs.morpho.org/curate/tutorials-v1/public-allocator/#next-steps) ----------------------------------------------------------------------------------------- * Monitor your flow caps * Adjust settings as needed * Consider market conditions when setting limits --- # Create a Morpho Vault V2 – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Create a Morpho Vault V2 On this page Chevron Right Deploying a Morpho Vault V2 is a permissionless process that anyone can initiate. This guide covers three methods for deploying your vault, ranging from the simplest user-friendly interface to more advanced technical approaches. This guide covers three methods for deploying your vault: 1. **Using the Curator App (Recommended)**: The easiest and most user-friendly method with a graphical interface for vault creation and configuration. 2. **Using a Deployment Script**: A powerful and efficient method for developers, allowing you to create, configure, and assign roles for your vault in a single, automated process. 3. **Using Etherscan**: A manual approach suitable for those who prefer interacting directly with contracts on a block explorer. Method 1: Create a Vault via the Curator App[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#method-1-create-a-vault-via-the-curator-app) ---------------------------------------------------------------------------------------------------------------------------------------------------------- The Curator App provides the easiest and most user-friendly way to deploy a Morpho Vault V2. This web-based interface guides you through the entire vault creation process without requiring any coding or command-line experience. **Curator App**: [**https://curator.morpho.org/vaults**](https://curator.morpho.org/vaults) ### Why Use the Curator App?[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#why-use-the-curator-app) * **No Technical Knowledge Required**: User-friendly graphical interface suitable for all experience levels. * **Guided Setup**: Step-by-step wizard walks you through every configuration option. * **Instant Deployment**: Deploy your vault directly from your browser using your connected wallet. * **Built-in Validation**: Automatic validation of parameters to prevent common configuration mistakes. * **Visual Configuration**: Easily configure roles, adapters, and risk parameters through intuitive forms. ### Getting Started with the Curator App[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#getting-started-with-the-curator-app) #### 1\. Connect Your Wallet[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#1-connect-your-wallet) Navigate to [https://curator.morpho.org/vaults](https://curator.morpho.org/vaults) and connect your Ethereum wallet (e.g., MetaMask, WalletConnect). #### 2\. Select Network[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#2-select-network) Choose the network where you want to deploy your vault. Morpho Vault V2 is available on multiple networks including Ethereum mainnet, Base, and other supported chains. #### 3\. Configure Vault Parameters[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#3-configure-vault-parameters) You will first be asked to set the main vault's parameters: * **Asset**: Select the ERC-20 token your vault will use (e.g., USDC, WETH). * **Owner**: Set the initial owner address (ideally a multisig for security). Once the vault created, set and abdicate the [Morpho registry](https://docs.morpho.org/curate/concepts/adapter-registry#the-morpho-registry) . You can then set the other Vault's parameters: * **Vault Symbol**: Choose a token symbol for your vault. * **Vault Name**: Choose a descriptive name for your vault. * **Curator**: Assign the curator role for managing vault parameters. * **Allocator**: Set the allocator address for managing fund allocations. * **Sentinel** (Optional): Optionally assign a sentinel for emergency actions. * **MaxRate**: The maximum rate earn by vault's suppliers. MaxRate must be set for suppliers to earn yield (more [here](https://docs.morpho.org/curate/concepts/yield#interest-rate-controls) ). #### 4\. Configure Adapters and Risk Parameters[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#4-configure-adapters-and-risk-parameters) * Select which Morpho Vault V1 instances you want to use as underlying liquidity markets. * Set initial risk caps (absolute and relative) for each adapter. * Configure the liquidity adapter for managing fund flows. #### 5\. Set Timelock (Optional)[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#5-set-timelock-optional) Configure timelock durations for critical functions to add an additional security layer for production vaults. #### 6\. Review and Deploy[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#6-review-and-deploy) Review all your configuration settings, then click "Deploy Vault". Your wallet will prompt you to confirm the transaction. Once deployed, you can continue managing your vault through the Curator App or use the advanced methods described below for programmatic management. Method 2: Create and Configure a Vault via Script[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#method-2-create-and-configure-a-vault-via-script) -------------------------------------------------------------------------------------------------------------------------------------------------------------------- For developers who prefer a code-based approach, you can use the official Morpho Vaults V2 deployment repository. This method allows you to bundle multiple setup actions into a single, automated script. **Repository**: [**https://github.com/morpho-org/vault-v2-deployment**](https://github.com/morpho-org/vault-v2-deployment) ### The Power of Scripted Deployment[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#the-power-of-scripted-deployment) The key advantage of using the deployment repository is automation and efficiency. The `DeployVaultV2.s.sol` script performs the entire initial configuration in one go, leveraging the fact that new vaults have a zero-second timelock by default. The deployment script performs the following actions: 1. **Vault Creation**: Deploys a new `VaultV2` instance using the VaultV2Factory. 2. **Adapter Deployment**: Deploys a `MorphoVaultV1Adapter` for the specified Vault V1. 3. **Role Assignment**: Configures temporary permissions during deployment, then assigns final `Owner`, `Curator`, `Allocator`, and optionally `Sentinel` roles. 4. **Core Configuration**: * Submits and executes timelocked configuration changes. * Enables the adapter on the vault. * Sets the adapter registry. * Configures the adapter as the `liquidityAdapter`. * Sets initial risk caps (absolute and relative). 5. **Timelock Hardening**: Optionally sets timelocks on critical functions to secure the vault for production use. 6. **Dead Deposit**: Optionally seeds the vault with initial liquidity to prevent inflation attacks. ### Prerequisites[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#prerequisites) Before deploying, ensure you have: * [Foundry](https://getfoundry.sh/) installed * Git installed * An Ethereum wallet with sufficient funds for deployment * RPC URL for your target network ### Running the Deployment Script[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#running-the-deployment-script) #### 1\. Clone the Repository and Install Dependencies[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#1-clone-the-repository-and-install-dependencies) Copy `git clone https://github.com/morpho-org/vault-v2-deployment cd vault-v2-deployment git submodule update --init --recursive` #### 2\. Configure Environment Variables[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#2-configure-environment-variables) Create a `.env` file with your deployment configuration: Copy `# Role addresses (replace with your actual addresses) OWNER=0x... # Final owner of the vault (ideally a multisig) CURATOR=0x... # Curator address (ideally a multisig) ALLOCATOR=0x... # Allocator address SENTINEL=0x... # Sentinel address (optional) # Timelock duration (in seconds) - set to 0 for immediate execution TIMELOCK_DURATION=1814400 # 21 days (optional, leave empty for 0) # Deployed contract addresses (network-specific) # See https://docs.morpho.org/get-started/resources/addresses/ for addresses ADAPTER_REGISTRY=0x... # Adapter Registry address VAULT_V2_FACTORY=0x... # VaultV2 Factory address MORPHO_VAULT_V1_ADAPTER_FACTORY=0x... # MorphoVaultV1 Adapter Factory address # Target Vault V1 VAULT_V1=0x... # The Morpho Vault V1 address to use as liquidity market # RPC and deployment settings RPC_URL=https://... # Your RPC endpoint PRIVATE_KEY=0x... # Your private key (keep secure!) # Optional: For contract verification ETHERSCAN_API_KEY=... # Your Etherscan API key DEAD_DEPOSIT_AMOUNT=... # Optional initial deposit to prevent inflation attacks` **Security Note**: Never commit your `.env` file to version control. It contains sensitive information like private keys. #### 3\. Deploy the Vault[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#3-deploy-the-vault) Run the deployment script: Copy `# Without block explorer verification forge script script/DeployVaultV2.s.sol \ --rpc-url $RPC_URL \ --private-key $PRIVATE_KEY \ --broadcast` Or with verification on Etherscan: Copy `# With verification on Etherscan forge script script/DeployVaultV2.s.sol \ --rpc-url $RPC_URL \ --private-key $PRIVATE_KEY \ --broadcast \ --etherscan-api-key $ETHERSCAN_API_KEY \ --verify` The script will output the addresses of all deployed contracts and confirm each configuration step. ### Testing Before Mainnet Deployment[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#testing-before-mainnet-deployment) The repository includes testing tools to help you validate your deployment: Copy `# Run all tests forge test # Test deployment on local Anvil network ./deploy_anvil.sh` **Important**: Always test your deployment configuration on a testnet before deploying to mainnet. ### Understanding the Deployment Steps[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#understanding-the-deployment-steps) The `DeployVaultV2.s.sol` script orchestrates a comprehensive deployment process. Here's what happens internally: #### Phase 1: Deploy VaultV2 Instance[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#phase-1-deploy-vaultv2-instance) Copy `// Deploy VaultV2 using the factory for deterministic addresses bytes32 uniqueSalt = keccak256(abi.encodePacked(block.timestamp + gasleft())); VaultV2 deployedVaultV2 = VaultV2( VaultV2Factory(factoryAddress).createVaultV2( temporaryOwner, underlyingAsset, uniqueSalt ) );` #### Phase 2: Configure Temporary Permissions[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#phase-2-configure-temporary-permissions) Copy `// Set broadcaster as temporary curator for configuration vault.setCurator(temporaryCurator);` #### Phase 3: Deploy and Configure Morpho Adapter[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#phase-3-deploy-and-configure-morpho-adapter) Copy `// Deploy MorphoVaultV1Adapter using the adapter factory address morphoAdapter = MorphoVaultV1AdapterFactory(factoryAddress) .createMorphoVaultV1Adapter(vaultV2Address, vaultV1Address);` #### Phase 4: Submit Timelocked Configuration Changes[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#phase-4-submit-timelocked-configuration-changes) Copy `// Submit all configuration changes that will be timelocked vault.submit(abi.encodeCall(vault.setIsAllocator, (allocator, true))); vault.submit(abi.encodeCall(vault.setAdapterRegistry, (registry))); vault.submit(abi.encodeCall(vault.setLiquidityAdapterAndData, (adapter, bytes("")))); bytes memory adapterIdData = abi.encode("this", adapter); vault.submit(abi.encodeCall(vault.addAdapter, (adapter))); vault.submit(abi.encodeCall(vault.increaseAbsoluteCap, (adapterIdData, type(uint128).max))); vault.submit(abi.encodeCall(vault.increaseRelativeCap, (adapterIdData, 1e18)));` #### Phase 5: Execute Immediate Configuration Changes[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#phase-5-execute-immediate-configuration-changes) Copy `// Since timelock is 0 initially, execute configurations immediately vault.setAdapterRegistry(registry); vault.setIsAllocator(allocator, true); vault.addAdapter(adapter); vault.setLiquidityAdapterAndData(adapter, bytes("")); bytes memory adapterIdData = abi.encode("this", adapter); vault.increaseAbsoluteCap(adapterIdData, type(uint128).max); vault.increaseRelativeCap(adapterIdData, 1e18); // Abdicate setAdapterRegistry function to prevent future changes vault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setAdapterRegistry.selector))); vault.abdicate(IVaultV2.setAdapterRegistry.selector);` #### Phase 6: Configure Timelock Settings (Optional)[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#phase-6-configure-timelock-settings-optional) Copy `// Define critical functions that should be timelocked bytes4[] memory timelockedSelectors = new bytes4[](10); timelockedSelectors[0] = IVaultV2.setReceiveSharesGate.selector; timelockedSelectors[1] = IVaultV2.setSendSharesGate.selector; timelockedSelectors[2] = IVaultV2.setReceiveAssetsGate.selector; // ... more critical functions // Submit and execute timelock increases for (uint256 i = 0; i < timelockedSelectors.length; i++) { vault.submit(abi.encodeCall(vault.increaseTimelock, (timelockedSelectors[i], timelockDuration))); vault.increaseTimelock(timelockedSelectors[i], timelockDuration); }` #### Phase 7: Set Final Role Assignments[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#phase-7-set-final-role-assignments) Copy `// Assign final roles to production addresses vault.setCurator(vaultCurator); if (vaultSentinel != address(0)) { vault.setIsSentinel(vaultSentinel, true); } vault.setOwner(vaultOwner);` #### Phase 8: Execute Dead Deposit (Optional)[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#phase-8-execute-dead-deposit-optional) Copy `// Seed vault with initial liquidity to prevent inflation attacks if (depositAmount > 0) { IERC20(vault.asset()).approve(address(vault), depositAmount); vault.deposit(depositAmount, address(0xdead)); // Burned shares }` For a detailed explanation of how to build your own deployment script, see the [repository documentation](https://github.com/morpho-org/vault-v2-deployment/blob/main/docs/build_own_script.md) . Method 3: Create a Vault Manually via Etherscan[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#method-3-create-a-vault-manually-via-etherscan) ---------------------------------------------------------------------------------------------------------------------------------------------------------------- If you prefer a manual approach without using the Curator App or deployment scripts, you can deploy a vault directly by interacting with the contracts on a block explorer like Etherscan. ### Prerequisites[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#prerequisites-1) * An Ethereum wallet (e.g., MetaMask) connected to the desired network. * The address of the ERC-20 token the vault will use as its `asset`. * The address you want to designate as the initial `owner`. ### Step-by-Step Guide[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#step-by-step-guide) #### 1\. Deploy a New VaultV2 Contract[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#1-deploy-a-new-vaultv2-contract) Since Vault V2 doesn't use a factory pattern, you'll need to deploy the contract directly. This typically requires using a development environment like Remix or Foundry. For Remix: 1. Copy the `VaultV2.sol` contract and its dependencies. 2. Compile with Solidity 0.8.28. 3. Deploy with constructor parameters: * `_owner`: The initial owner address (ideally your multisig). * `_asset`: The ERC-20 token address (e.g., USDC, WETH). #### 2\. Verify the Contract[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#2-verify-the-contract) After deployment, verify the contract on Etherscan to enable the `Write Contract` interface. #### 3\. Configure the Vault[](https://docs.morpho.org/curate/tutorials-v2/vault-creation/#3-configure-the-vault) Once deployed and verified, you'll need to: 1. Set up roles (see [Manage Vault V2 Roles](https://docs.morpho.org/curate/tutorials-v2/roles) ). 2. Deploy and configure adapters (see [(De)List Adapters](https://docs.morpho.org/curate/tutorials-v2/listing-adapters) ). **Congratulations!** Your vault is now deployed. For a production-ready setup, we strongly recommend using the deployment script method as it ensures all components are properly configured. --- # Create a Market – Morpho Docs [Skip to content](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Curate Chevron Down Menu Create a Market On this page Chevron Right This tutorial guides you through the process of creating and configuring a market in your Morpho vault. Deploying a Market via Etherscan[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#deploying-a-market-via-etherscan) ------------------------------------------------------------------------------------------------------------------------------------------- ### Jump on the Morpho contract[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#jump-on-the-morpho-contract) See the [address section](https://docs.morpho.org/get-started/resources/addresses) . E.g: Ethereum mainnet address is [0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb](https://etherscan.io/address/0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb#writeContract) ### Fill all attributes[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#fill-all-attributes) Jump on the `createMarket` function * `loanToken`: paste the address of the loan token, * `collateralToken`: paste the address of the collateral token, * `oracle`: paste the oracle address, * `irm`: paste the Interest Rate Model address, * `lltv`: the LLTV is defined with 18 decimals. 1e18 represents an LLTV of 100% (which is not enabled) and 945000000000000000 thus represents 94.5%. ![Market Creation Etherscan guide](https://docs.morpho.org/img/morpho-blue/market-creation.png) ### Sign the transaction[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#sign-the-transaction) You are done. Important Note[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#important-note) ------------------------------------------------------------------------------------------------------- ### Market Id Retrieval[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#market-id-retrieval) When creating a market, a `CreateMarket` event is emitted with the market `id`: ![CreateMarket event showing the market ID](https://docs.morpho.org/img/morpho-blue/createMarketEvent.png) To retrieve the market parameters from this `id`: #### Navigate to the Morpho contract on Etherscan[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#navigate-to-the-morpho-contract-on-etherscan) #### Go to the "Read Contract" tab[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#go-to-the-read-contract-tab) #### Find the `idToMarketParams` function[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#find-the-idtomarketparams-function) #### Paste the `id` into the input field and execute[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#paste-the-id-into-the-input-field-and-execute) Example: Using the `id`: `0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc` ![idToMarketParams function call example](https://docs.morpho.org/img/morpho-blue/idToMarketParams.png) Resource: Market ID Generator[](https://docs.morpho.org/curate/tutorials-market-v1/creating-market/#resource-market-id-generator) ------------------------------------------------------------------------------------------------------------------------------------ Use this tool to generate the unique market ID from your market parameters: Loan Token Address Collateral Token Address Oracle Address IRM Address LLTV (in wei, e.g., 915000000000000000 for 91.5%) Reset --- # Supply Collateral, Borrow, Repay & Withdraw Collateral – Morpho Docs [Skip to content](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Tutorials On this page Chevron Right This tutorial provides a comprehensive guide for developers on how to integrate the core functionalities of Morpho Markets: supplying collateral, borrowing, repaying debt, and withdrawing collateral. Unlike ERC4626 vaults, Morpho Markets have a unique interface defined by the core `Morpho` contract. Understanding these functions is essential for building any application with borrowing capabilities. We will cover three primary methods of interaction: 1. **Direct Smart Contract Integration** using Solidity. 2. **Offchain Integration** using the Morpho SDK with TypeScript and Viem. 3. **Advanced Integration** using Morpho Bundlers for atomic, multi-step actions. Key Concepts: Assets vs. Shares[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#key-concepts-assets-vs-shares) ------------------------------------------------------------------------------------------------------------------------------- The core accounting system in Morpho Markets revolves around the concepts of `assets` and `shares`. This applies to the `borrow` positions (the loanable asset), but **not** to the collateral. | Concept | Functions Affected | Description | | --- | --- | --- | | **Assets** | `borrow`, `repay` | The actual underlying token (e.g., USDC, WETH) that a user wants to lend or borrow. | | **Shares** | `borrow`, `repay` | Internal accounting units representing a proportional claim on the market's total supply or debt. | **Best Practice:** * For `borrow`, using the `assets` parameter is the most common and intuitive approach for users. * For **full repayments**, using the `shares` parameter is highly recommended. Repaying a user's exact `borrowShares` balance ensures the debt is fully cleared, avoiding "dust" amounts left over from rounding. * Collateral (`supplyCollateral` and `withdrawCollateral`) is always handled in `assets`. Prerequisites[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#prerequisites) --------------------------------------------------------------------------------------------- Before you begin, you will need: * The `MarketParams` for the market you want to interact with. You can find active markets using the [Morpho API](https://docs.morpho.org/build/borrow/tutorials/get-data#markets-parameters) . * An account with a balance of the collateral asset (e.g., wstETH) and the loan asset (e.g., WETH for repayments). Method 1: Smart Contract Integration (Solidity)[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#method-1-smart-contract-integration-solidity) -------------------------------------------------------------------------------------------------------------------------------------------------------------- This method is for developers building smart contracts that interact directly with Morpho Markets. The typical flow is: supply collateral, borrow, repay, and then withdraw collateral. ### Step 1: Supply Collateral[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#step-1-supply-collateral) First, the user must supply a collateral asset to the market. This requires approving the Morpho contract to spend the collateral token. Copy `import { IMorpho, MarketParams } from "morpho-blue/src/interfaces/IMorpho.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; // Within your contract IMorpho morpho = IMorpho(0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb); MarketParams memory marketParams = ...; // The parameters for the chosen market uint256 collateralAmount = 1 ether; // 1. Approve Morpho to spend the collateral token IERC20(marketParams.collateralToken).approve(address(morpho), collateralAmount); // 2. Supply the collateral morpho.supplyCollateral(marketParams, collateralAmount, msg.sender, "");` ### Step 2: Borrow Assets[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#step-2-borrow-assets) Once collateral is supplied, the user can borrow the loan asset against it. Copy `// Borrowing a specific amount of the loan token (asset-first approach) uint256 borrowAmount = 1000 * 10**18; // Example: 1000 WETH // The final two arguments are onBehalf and receiver (uint256 assetsBorrowed, ) = morpho.borrow(marketParams, borrowAmount, 0, msg.sender, msg.sender);` ### Step 3: Repay Debt[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#step-3-repay-debt) To repay the loan, the user must approve the Morpho contract to spend the loan token. Partial RepayFull Repay Partial Repay Copy `// Asset-first approach: Repay a specific amount of the loan token. uint256 repayAmount = 500 * 10**18; IERC20(marketParams.loanToken).approve(address(morpho), repayAmount); morpho.repay(marketParams, repayAmount, 0, msg.sender, "");` ### Step 4: Withdraw Collateral[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#step-4-withdraw-collateral) After the debt is fully or partially repaid, the user can withdraw their collateral, provided their position remains healthy. Copy `uint256 amountToWithdraw = 0.5 ether; // The final two arguments are onBehalf and receiver morpho.withdrawCollateral(marketParams, amountToWithdraw, msg.sender, msg.sender);` Full Example: Solidity Snippet[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#full-example-solidity-snippet) ------------------------------------------------------------------------------------------------------------------------------ Here is a complete example contract demonstrating the full borrow-repay cycle. Copy `// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IMorpho, MarketParams, Market, Position } from "morpho-blue/src/interfaces/IMorpho.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { MorphoBalancesLib } from "morpho-blue/src/libraries/periphery/MorphoBalancesLib.sol"; import { MarketParamsLib } from "morpho-blue/src/libraries/MarketParamsLib.sol"; contract MorphoMarketInteraction { using MarketParamsLib for MarketParams; using MorphoBalancesLib for IMorpho; IMorpho public immutable morpho; MarketParams public immutable marketParams; constructor(IMorpho _morpho, MarketParams memory _marketParams) { morpho = _morpho; marketParams = _marketParams; } function supplyCollateralAndBorrow(uint256 collateralAmount, uint256 borrowAmount) external { IERC20(marketParams.collateralToken).approve(address(morpho), collateralAmount); morpho.supplyCollateral(marketParams, collateralAmount, msg.sender, ""); morpho.borrow(marketParams, borrowAmount, 0, msg.sender, msg.sender); } function repayAllAndWithdraw(uint256 collateralAmount) external { uint256 debt = morpho.expectedBorrowAssets(marketParams, msg.sender); IERC20(marketParams.loanToken).approve(address(morpho), debt); (, uint128 borrowShares, ) = morpho.position(marketParams.id(), msg.sender); morpho.repay(marketParams, 0, borrowShares, msg.sender, ""); morpho.withdrawCollateral(marketParams, collateralAmount, msg.sender, msg.sender); } }` Method 2: Offchain Integration (TypeScript SDK)[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#method-2-offchain-integration-typescript-sdk) -------------------------------------------------------------------------------------------------------------------------------------------------------------- This method is ideal for dApp frontends or backend services. We'll use TypeScript with **Viem**. ### Step 1: Setup[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#step-1-setup) Install dependencies and set up your Viem client. Copy `npm install viem @morpho-org/blue-sdk @morpho-org/morpho-ts` Copy `import { createWalletClient, http, publicActions, parseUnits } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { mainnet } from "viem/chains"; import { IMorpho_ABI } from "@morpho-org/morpho-ts"; const morphoAddress = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"; const marketParams = { ... }; // Your target market's parameters const account = privateKeyToAccount("0x..."); const client = createWalletClient({ account, chain: mainnet, transport: http(process.env.RPC_URL_MAINNET), }).extend(publicActions);` ### Step 2: Supply Collateral & Borrow[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#step-2-supply-collateral--borrow) This example combines supplying collateral and borrowing. In a real app, these would likely be separate user actions. Copy `const collateralAmount = parseUnits("1.0", 18); // 1 wstETH const borrowAmount = parseUnits("2000", 18); // 2000 WETH // 1. Approve collateral await client.writeContract({ address: marketParams.collateralToken, abi: IERC20_ABI, // A standard ERC20 ABI functionName: "approve", args: [morphoAddress, collateralAmount], }); // 2. Supply collateral await client.writeContract({ address: morphoAddress, abi: IMorpho_ABI, functionName: "supplyCollateral", args: [marketParams, collateralAmount, account.address, "0x"], }); // 3. Borrow await client.writeContract({ address: morphoAddress, abi: IMorpho_ABI, functionName: "borrow", args: [marketParams, borrowAmount, 0, account.address, account.address], });` ### Step 3: Repay & Withdraw[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#step-3-repay--withdraw) This example shows a full repayment using the `shares` parameter. Copy `// 1. Get user's borrow shares const { borrowShares } = await client.readContract({ address: morphoAddress, abi: IMorpho_ABI, functionName: "position", args: [marketId, account.address], }); if (borrowShares > 0) { // 2. Approve repayment (for the full debt amount in assets) // The Morpho SDK can help calculate the expected asset amount for the shares. const expectedDebtAssets = ...; await client.writeContract({ address: marketParams.loanToken, abi: IERC20_ABI, functionName: "approve", args: [morphoAddress, expectedDebtAssets], }); // 3. Repay full debt using shares await client.writeContract({ address: morphoAddress, abi: IMorpho_ABI, functionName: "repay", args: [marketParams, 0, borrowShares, account.address, "0x"], }); // 4. Withdraw collateral const collateralToWithdraw = parseUnits("1.0", 18); await client.writeContract({ address: morphoAddress, abi: IMorpho_ABI, functionName: "withdrawCollateral", args: [marketParams, collateralToWithdraw, account.address, account.address], }); }` * * * Method 3: Advanced Integration with Bundlers[](https://docs.morpho.org/build/borrow/tutorials/assets-flow/#method-3-advanced-integration-with-bundlers) ---------------------------------------------------------------------------------------------------------------------------------------------------------- For the best user experience, especially for actions that require multiple steps (like supply and borrow), **Morpho Bundlers** are the recommended solution. The bundler abstracts away the complexity. You define your intent, and it creates a single, atomic transaction. For example, to supply collateral and borrow in one click: Copy ``import { type InputBundlerOperation } from "@morpho-org/bundler-sdk-viem"; const supplyCollateralOp: InputBundlerOperation = { type: "Blue_SupplyCollateral", args: { /* ... */ }, }; const borrowOp: InputBundlerOperation = { type: "Blue_Borrow", args: { /* ... */ }, }; // The bundler SDK would take [supplyCollateralOp, borrowOp] and create one transaction // that automatically includes the necessary `approve` call.`` --- # Depositing & Withdrawing from Vaults – Morpho Docs [Skip to content](https://docs.morpho.org/build/earn/tutorials/assets-flow/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Tutorials On this page Chevron Right **Morpho Vaults V1** and **Morpho Vaults V2** are functionally identical for deposit and withdrawal operations. Both implement the standard [ERC‑4626](https://eips.ethereum.org/EIPS/eip-4626) interface, meaning `deposit()`, `withdraw()`, `mint()`, and `redeem()` work the same way across all vault versions. Your integration code remains unchanged regardless of which vault version your users interact with. This guide covers three integration methods for Morpho Vault deposits and withdrawals. Because all Morpho Vaults follow the ERC4626 standard, the patterns below apply universally—whether you're building a smart contract, dApp, or backend service. **Integration methods:** 1. **Direct Smart Contract Integration** using Solidity 2. **Offchain Integration** using TypeScript and Viem 3. **Advanced Integration** using Morpho Bundlers for atomic operations Key Concepts: Assets vs. Shares[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#key-concepts-assets-vs-shares) ----------------------------------------------------------------------------------------------------------------------------- When interacting with ERC4626 vaults, you have two approaches for deposits and withdrawals: an **asset-first** approach or a **shares-first** approach. Understanding the difference is key to a robust integration. | Approach | Deposit Function | Withdrawal Function | Description | | --- | --- | --- | --- | | **Asset-First** | `deposit(assets, ...)` | `withdraw(assets, ...)` | You specify the exact amount of the underlying token (e.g., USDC, WETH) you want to deposit or withdraw. | | **Shares-First** | `mint(shares, ...)` | `redeem(shares, ...)` | You specify the exact number of vault shares you want to mint or redeem. | **Best Practice:** * For **deposits**, `deposit()` is the most common and intuitive function. * For **full withdrawals**, `redeem()` is recommended. Redeeming all of a user's shares ensures their balance goes to zero and avoids leaving behind small, unusable amounts of "dust." * For **partial withdrawals** where a user needs a specific amount of the underlying asset, `withdraw()` is appropriate. Prerequisites[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#prerequisites) ------------------------------------------------------------------------------------------- Before you begin, you will need: * The address of the Morpho Vault you want to interact with. You can find active vaults using the [Morpho API](https://docs.morpho.org/build/earn/tutorials/get-data) . * An account with a balance of the vault's underlying asset (e.g., WETH for a WETH vault). Vault Safety: Inflation Attack Protection[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#vault-safety-inflation-attack-protection) -------------------------------------------------------------------------------------------------------------------------------------------------- All ERC4626-compliant vaults, including Morpho Vaults, require a **dead deposit** to protect against share inflation attacks. This protection must be verified before your first interaction with a vault. **Verification Check:** Copy `// Check that the vault has adequate protection const deadAddress = "0x000000000000000000000000000000000000dEaD"; const deadShares = await vault.balanceOf(deadAddress); if (deadShares < 1_000_000_000n) { throw new Error("Vault lacks required inflation protection"); }` **Key Points:** * The dead deposit must be at least **1e9 shares** (approximately $10 equivalent) * This check should be performed during vault integration/whitelisting, not on every transaction * Properly protected vaults make inflation attacks economically unfeasible * Both Morpho Vault V1 and V2 should have this protection established by curators For a detailed explanation of how this protection works, see [Vault Mechanics: Inflation Attack Protection](https://docs.morpho.org/build/earn/concepts/vault-mechanics#inflation-attack-protection) . Method 1: Smart Contract Integration (Solidity)[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#method-1-smart-contract-integration-solidity) ------------------------------------------------------------------------------------------------------------------------------------------------------------ This method is for developers building smart contracts that need to deposit into or withdraw from a Morpho Vault onchain. ### Step 1: Approve the Vault[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#step-1-approve-the-vault) Before your contract can deposit tokens into a vault, it must first approve the vault contract to spend its tokens. Copy `import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; // Within your contract address vaultAddress = 0x...; // Address of the Morpho Vault address assetAddress = 0x...; // Address of the underlying asset (e.g., WETH) uint256 depositAmount = 1 ether; // Approve the vault to spend the asset IERC20(assetAddress).approve(vaultAddress, depositAmount);` ### Step 2: Deposit or Mint Assets[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#step-2-deposit-or-mint-assets) Choose the function that best fits your needs. deposit (V2)mint (V2)deposit (V1)mint (V1) deposit (V2) Copy `import { IVaultV2 } from "@morpho-org/vault-v2/src/interfaces/IVaultV2.sol"; // Asset-first approach: Deposit a specific amount of the underlying token. // The contract will calculate and mint the corresponding number of shares. uint256 sharesMinted = IVaultV2(vaultAddress).deposit(depositAmount, address(this));` ### Step 3: Withdraw or Redeem Assets[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#step-3-withdraw-or-redeem-assets) Similarly, you can withdraw by specifying either the asset amount or the share amount. withdraw (V2)redeem (V2)withdraw (V1)redeem (V1) withdraw (V2) Copy `import { IVaultV2 } from "@morpho-org/vault-v2/src/interfaces/IVaultV2.sol"; // Asset-first approach: Withdraw a specific amount of the underlying token. uint256 assetsToWithdraw = 1 ether; uint256 sharesBurned = IVaultV2(vaultAddress).withdraw(assetsToWithdraw, address(this), address(this));` ### Full Example: Solidity Snippets[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#full-example-solidity-snippets) Here are some example contracts demonstrating these interactions for both vault versions. Morpho Vault V2Morpho Vault V1 Morpho Vault V2 Copy `// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IVaultV2 } from "@morpho-org/vault-v2/src/interfaces/IVaultV2.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract VaultV2Interaction { IVaultV2 public immutable vault; IERC20 public immutable asset; constructor(address _vault) { vault = IVaultV2(_vault); asset = IERC20(vault.asset()); } /// @notice Deposits a specified amount of assets into the vault. /// @param amount The amount of underlying assets to deposit. function deposit(uint256 amount) external { asset.approve(address(vault), amount); vault.deposit(amount, msg.sender); } /// @notice Withdraws all assets from the vault for the caller. function withdrawAll() external { uint256 shares = vault.balanceOf(msg.sender); if (shares > 0) { vault.redeem(shares, msg.sender, msg.sender); } } }` Method 2: Offchain Integration (TypeScript SDK)[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#method-2-offchain-integration-typescript-sdk) ------------------------------------------------------------------------------------------------------------------------------------------------------------ This method is ideal for dApp frontends or backend services that trigger transactions on behalf of users. We'll use TypeScript with **Viem** and the **Morpho SDKs**. ### Step 1: Setup[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#step-1-setup) First, install the necessary packages and set up your Viem client. Copy `npm install viem @morpho-org/blue-sdk @morpho-org/blue-sdk-viem @morpho-org/morpho-ts` Copy `import { createWalletClient, http, publicActions, parseUnits } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { mainnet } from "viem/chains"; import { metaMorphoAbi } from "@morpho-org/blue-sdk-viem"; const vaultAddress = "0x..."; // The vault address const assetAddress = "0x..."; // The vault's underlying asset address const account = privateKeyToAccount("0x..."); // The user's account const client = createWalletClient({ account, chain: mainnet, transport: http(process.env.RPC_URL_MAINNET), }).extend(publicActions);` ### Step 2: Approve the Vault[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#step-2-approve-the-vault) Before depositing, check the current allowance and approve if necessary. Copy `// 1. Check current allowance const allowance = await client.readContract({ address: assetAddress, abi: IERC20_ABI, // A standard ERC20 ABI functionName: "allowance", args: [account.address, vaultAddress], }); const amountToDeposit = parseUnits("1.0", 18); // Example: 1 WETH // 2. Approve if allowance is insufficient if (allowance < amountToDeposit) { const { request } = await client.simulateContract({ address: assetAddress, abi: IERC20_ABI, functionName: "approve", args: [vaultAddress, amountToDeposit], }); await client.writeContract(request); }` ### Step 3: Deposit Assets[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#step-3-deposit-assets) Call the `deposit` function to add funds to the vault. Copy `const { request: depositRequest } = await client.simulateContract({ address: vaultAddress, abi: metaMorphoAbi, functionName: "deposit", args: [amountToDeposit, account.address], // (assets, receiver) }); const depositTxHash = await client.writeContract(depositRequest); console.log("Deposit successful:", depositTxHash);` ### Step 4: Withdraw Assets[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#step-4-withdraw-assets) To withdraw the full balance, first fetch the user's share balance, then call `redeem`. Copy `// 1. Get the user's share balance const userShares = await client.readContract({ address: vaultAddress, abi: metaMorphoAbi, functionName: "balanceOf", args: [account.address], }); // 2. Redeem the shares for the underlying asset if (userShares > 0n) { const { request: redeemRequest } = await client.simulateContract({ address: vaultAddress, abi: metaMorphoAbi, functionName: "redeem", args: [userShares, account.address, account.address], // (shares, receiver, owner) }); const redeemTxHash = await client.writeContract(redeemRequest); console.log("Withdrawal successful:", redeemTxHash); }` Method 3: Advanced Integration with Bundlers[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#method-3-advanced-integration-with-bundlers) -------------------------------------------------------------------------------------------------------------------------------------------------------- For complex operations, such as depositing into a vault and performing another action in the same transaction, **Morpho Bundlers** are the recommended tool. Bundlers abstract away the low-level details like approvals and transfers. You simply define your high-level intent, and the bundler constructs the atomic transaction for you. For example, to deposit into a vault, you would define an input operation like this: Copy `import { type InputBundlerOperation } from "@morpho-org/bundler-sdk-viem"; const vaultAddress = "0x..."; const userAddress = "0x..."; const depositAmount = 1000000000000000000n; // 1 WETH const depositOperation: InputBundlerOperation = { type: "MetaMorpho_Deposit", sender: userAddress, address: vaultAddress, args: { assets: depositAmount, receiver: userAddress, }, };` The bundler SDK would then automatically handle the `approve` call before executing the `deposit`. Additional Considerations[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#additional-considerations) ------------------------------------------------------------------------------------------------------------------- ### Slippage for User Experience[](https://docs.morpho.org/build/earn/tutorials/assets-flow/#slippage-for-user-experience) While not a security requirement when proper dead deposit protection is in place, implementing slippage tolerance can improve user experience in your application. **For production applications**, we recommend using [Bundlers](https://docs.morpho.org/build/earn/tutorials/bundlers) , which automatically handle slippage checks for you. **For direct integrations**, here's an educational example of how to implement a basic slippage check (1% tolerance): Vault V2 with slippage checkVault V1 with slippage check Vault V2 with slippage check Copy `// Educational example: Deposit with 1% slippage protection import { IVaultV2 } from "@morpho-org/vault-v2/src/interfaces/IVaultV2.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract VaultV2DepositWithSlippage { function depositWithSlippage( address vaultAddress, uint256 depositAmount ) external returns (uint256) { IVaultV2 vault = IVaultV2(vaultAddress); IERC20 asset = IERC20(vault.asset()); // 1. Preview expected shares uint256 expectedShares = vault.previewDeposit(depositAmount); // 2. Calculate minimum acceptable shares (1% slippage = 99% of expected) uint256 minShares = expectedShares * 99 / 100; // 3. Approve and execute deposit asset.approve(vaultAddress, depositAmount); uint256 sharesMinted = vault.deposit(depositAmount, msg.sender); // 4. Verify slippage tolerance require(sharesMinted >= minShares, "Slippage tolerance exceeded"); return sharesMinted; } }` --- # Morpho SDKs – Morpho Docs [Skip to content](https://docs.morpho.org/tools/offchain/sdks/get-started/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Developers Hub Chevron Down Menu Morpho SDKs On this page Chevron Right The Morpho Software Development Kits (SDKs) are a comprehensive suite of TypeScript packages designed to streamline development on the Morpho protocol. Whether you're building a full-featured DeFi application, a liquidation bot, or a simple data dashboard, these SDKs provide the tools you need to interact with Morpho's onchain and offchain ecosystems efficiently. The SDKs are built with a modular, framework-agnostic core and offer powerful integrations for modern tools like **Viem** and **Wagmi**. The SDK Stack[](https://docs.morpho.org/tools/offchain/sdks/get-started/#the-sdk-stack) ------------------------------------------------------------------------------------------ The SDKs are organized into logical layers, allowing you to pick and choose the packages that best fit your needs. Core Packages[](https://docs.morpho.org/tools/offchain/sdks/get-started/#core-packages) ------------------------------------------------------------------------------------------ These framework-agnostic packages form the foundation of the Morpho SDK ecosystem. * **`@morpho-org/blue-sdk`**: The heart of the stack. Defines core entity classes like `Market`, `Vault`, and `Position`, and handles essential offchain computations. * **`@morpho-org/simulation-sdk`**: A powerful engine for simulating user interactions like supplying, borrowing, or depositing into vaults before executing them onchain. * **`@morpho-org/blue-api-sdk`**: A GraphQL client for fetching data directly from the [Morpho API](https://docs.morpho.org/tools/offchain/api/get-started) , complete with types and an Apollo cache controller. Viem Integration Packages[](https://docs.morpho.org/tools/offchain/sdks/get-started/#viem-integration-packages) ------------------------------------------------------------------------------------------------------------------ These packages augment the core SDKs with Viem-based fetchers for seamless onchain interaction. * **`@morpho-org/blue-sdk-viem`**: Extends `@morpho-org/blue-sdk` with methods to fetch live market and position data from the blockchain using Viem. * **`@morpho-org/bundler-sdk-viem`**: The key to building powerful, one-click user experiences. It transforms simple actions into atomic, gas-efficient transactions. * **`@morpho-org/liquidity-sdk-viem`**: Simplifies calculations for available liquidity, including funds accessible via the Public Allocator. * **`@morpho-org/liquidation-sdk-viem`**: Provides utilities to build robust, Viem-based liquidation bots. Wagmi (React) Integration Packages[](https://docs.morpho.org/tools/offchain/sdks/get-started/#wagmi-react-integration-packages) ---------------------------------------------------------------------------------------------------------------------------------- Designed for frontend developers, these packages provide React hooks for fetching Morpho data in your application. * **`@morpho-org/blue-sdk-wagmi`**: A set of Wagmi hooks for fetching Morpho-related entities. * **`@morpho-org/simulation-sdk-wagmi`**: Wagmi hooks for fetching and managing simulation states in a React environment. Featured Use Case: Building One-Click Actions with the Bundler SDK[](https://docs.morpho.org/tools/offchain/sdks/get-started/#featured-use-case-building-one-click-actions-with-the-bundler-sdk) --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The Bundler SDK is the powerhouse for creating seamless user experiences. It allows you to abstract away the complexities of multi-step DeFi operations (like token approvals, wrapping, and supplying) into a single, atomic transaction. For example, a user can supply ETH as collateral and borrow USDC against it in one click, without needing to perform separate transactions for wrapping ETH to WETH, approving WETH, supplying collateral, and finally borrowing. To learn how to integrate the Bundler, follow this path: 1. **Understand the Concept**: Start with an overview of what Bundlers do in the [Get Started with Bundlers](https://docs.morpho.org/bundlers/get-started) guide. 2. **The Core Functionality**: See how multiple calls are batched in the [`multicall`](https://docs.morpho.org/bundlers/functions/multicall) function specification. 3. **How to Combine Actions**: Learn to encode and combine various protocol actions in the [Combine Actions Tutorial](https://docs.morpho.org/bundlers/tutorials/combine-actions) . 4. **Full Integration Guide**: Walk through a complete example of integrating the Bundler SDK into an application in the [App Integration Guide](https://docs.morpho.org/bundlers/tutorials/integrate) . Product-Specific Examples[](https://docs.morpho.org/tools/offchain/sdks/get-started/#product-specific-examples) ------------------------------------------------------------------------------------------------------------------ * **Integrate Bundlers for Earn**: [Earn with Bundlers Tutorial](https://docs.morpho.org/build/earn/tutorials/bundlers) * **Integrate Bundlers for Borrow**: [Borrow with Bundlers Tutorial](https://docs.morpho.org/build/borrow/tutorials/bundlers) Get Started[](https://docs.morpho.org/tools/offchain/sdks/get-started/#get-started) -------------------------------------------------------------------------------------- Ready to build? * **Explore the full list of SDKs** in our [SDKs Introduction](https://docs.morpho.org/tools/offchain/sdks/get-started) . * **Dive into the source code** on the [Morpho SDKs GitHub Repository](https://github.com/morpho-org/sdks) . * **Get in touch** via the chatbox on **[help.morpho.org](https://help.morpho.org/) **. --- # Market Mechanics – Morpho Docs [Skip to content](https://docs.morpho.org/build/borrow/concepts/market-mechanics#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Concepts On this page Chevron Right Interacting with Morpho Markets involves a set of core functions and concepts that govern how assets are supplied, borrowed, and tracked. Unlike ERC4626 vaults, which have a standardized interface, Morpho's market interactions are defined by its unique internal accounting system. This page explains the fundamental mechanics you need to understand to build a robust borrowing integration. Core Data Structures[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#core-data-structures) -------------------------------------------------------------------------------------------------------------- At the heart of Morpho are two key structs that define the state of every market and every user's position within it. ### `Market` Struct[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#market-struct) This struct tracks the overall state of a single, isolated market. Copy `struct Market { uint128 totalSupplyAssets; uint128 totalSupplyShares; uint128 totalBorrowAssets; uint128 totalBorrowShares; uint128 lastUpdate; uint128 fee; }` * `totalSupply/BorrowAssets`: The total amount of the underlying token supplied or borrowed. This value changes as interest accrues. * `totalSupply/BorrowShares`: The total number of internal accounting units (shares) held by suppliers or borrowers. This value only changes with user interactions. ### `Position` Struct[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#position-struct) This struct tracks an individual user's position within a specific market. Copy `struct Position { uint256 supplyShares; uint128 borrowShares; uint128 collateral; }` * `collateral`: The amount of collateral the user has supplied _to this specific market_. Assets vs. Shares: The Core Mechanic[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#assets-vs-shares-the-core-mechanic) -------------------------------------------------------------------------------------------------------------------------------------------- The most critical concept to grasp is the relationship between **Assets** and **Shares**. This dual-accounting system is how Morpho manages positions and accrues interest. ### Assets[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#assets) * **Definition**: The actual, underlying tokens (e.g., USDC, WETH) that users interact with. * **Use Case**: Ideal for user-facing interactions where a specific token amount is desired (e.g., "I want to borrow 1,000 USDC"). ### Shares[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#shares) * **Definition**: Internal, non-transferable accounting units that represent a user's proportional stake in the market's total supply or debt. * **How it works**: When you supply assets, you "buy" shares at the current exchange rate. As interest accrues in the market, the value of each share (its exchange rate back to assets) increases. * **Use Case**: Ideal for protocol-level interactions and for ensuring full repayment or withdrawal, as it avoids rounding errors ("dust"). ### The Relationship: Share Price[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#the-relationship-share-price) The "price" of a share is its exchange rate to the underlying asset. This price is dynamic and increases as interest accrues. Copy `// This is a conceptual calculation; the contract uses SharesMathLib for precision. sharePrice = totalAssets / totalShares;` * For **suppliers**, the value of their shares grows over time, representing their earned yield. * For **borrowers**, the asset value of their debt grows over time, representing the interest they owe. Core Functions & Their Dual Nature[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#core-functions--their-dual-nature) ----------------------------------------------------------------------------------------------------------------------------------------- Most core functions in Morpho allow you to specify an amount in either `assets` or `shares`. You must provide a value for one and zero for the other. ### `supply` and `borrow`[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#supply-and-borrow) Copy `function supply(uint256 assets, uint256 shares, ...); function borrow(uint256 assets, uint256 shares, ...);` * **Use `assets` > 0, `shares` = 0:** When a user wants to supply or borrow a precise amount of tokens. This is the most common use case for dApps. * **Use `assets` = 0, `shares` > 0:** For advanced use cases where you need to mint a precise number of shares. ### `repay` and `withdraw`[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#repay-and-withdraw) Copy `function repay(uint256 assets, uint256 shares, ...); function withdraw(uint256 assets, uint256 shares, ...);` * **Use `assets` > 0, `shares` = 0:** For partial repayments or withdrawals where a specific token amount is needed. * **Use `assets` = 0, `shares` > 0:** **Recommended for full repayments/withdrawals.** By specifying the user's exact share balance, you ensure their position is completely closed without leaving dust. Collateral and Health[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#collateral-and-health) ---------------------------------------------------------------------------------------------------------------- * **`supplyCollateral` & `withdrawCollateral`**: These functions are straightforward and only operate on `assets`. Collateral in Morpho does not earn yield and thus does not use a share-based system. * **Position Health**: A user's ability to borrow or withdraw collateral is determined by their Health Factor, which is a function of their collateral value, debt value, and the market's `lltv`. Practical Implementation Snippets[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#practical-implementation-snippets) ---------------------------------------------------------------------------------------------------------------------------------------- ### Supplying Collateral & Borrowing (Asset-First)[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#supplying-collateral--borrowing-asset-first) Copy `// Conceptual TypeScript using a web3 library like Viem // 1. Approve collateral tokens await client.writeContract({ functionName: 'approve', args: [morphoAddress, collateralAmount] }); // 2. Supply collateral await client.writeContract({ functionName: 'supplyCollateral', args: [marketParams, collateralAmount, userAddress] }); // 3. Borrow assets const { result } = await client.simulateContract({ functionName: 'borrow', args: [marketParams, borrowAmount, 0, userAddress, userAddress] // assets > 0, shares = 0 }); await client.writeContract(result.request);` ### Full Repayment (Shares-First)[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#full-repayment-shares-first) Copy `// 1. Fetch the user's current borrow shares const { borrowShares } = await client.readContract({ functionName: 'position', args: [marketId, userAddress] }); // 2. Approve the loan token for repayment // The amount to approve should be slightly more than the expected asset value of the shares // to account for interest accrued since the last block. const repayAmountAssets = await client.readContract({ functionName: 'toAssetsUp', // using a helper or SDK function args: [borrowShares, market.totalBorrowAssets, market.totalBorrowShares] }); await client.writeContract({ functionName: 'approve', args: [morphoAddress, repayAmountAssets] }); // 3. Repay the full debt by specifying the exact shares await client.writeContract({ functionName: 'repay', args: [marketParams, 0, borrowShares, userAddress] // assets = 0, shares > 0 });` Best Practices[](https://docs.morpho.org/build/borrow/concepts/market-mechanics#best-practices) -------------------------------------------------------------------------------------------------- * **For User-Facing Actions**: Use the `assets` parameter for `supply`, `borrow`, and partial `repay`/`withdraw` as it's more intuitive for users. * **For Closing Positions**: Use the `shares` parameter for full `repay` and `withdraw` operations to ensure the position is fully closed. * **Slippage**: When converting between assets and shares, be aware of potential slippage due to interest accrual between transaction simulation and execution. The Morpho SDKs and Bundlers handle this automatically. * **Interest Accrual**: Remember that `totalBorrowAssets` and `totalSupplyAssets` are only updated when an interaction triggers `_accrueInterest`. For the most up-to-date values, use a library like `MorphoBalancesLib` or the Morpho SDK. By understanding these core mechanics, you can build safe, efficient, and user-friendly applications on top of Morpho Markets. --- # Interest Rate Models – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/irm/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Interest Rate Models On this page Chevron Right [← Back to contracts](https://docs.morpho.org/get-started/resources/contracts) Code[](https://docs.morpho.org/get-started/resources/contracts/irm/#code) ---------------------------------------------------------------------------- [Interest Rate Model repository](https://github.com/morpho-org/morpho-blue-irm) Interest rate models are defined as a list of governance-approved contracts. Each contract implements the [IRM interface](https://github.com/morpho-org/morpho-blue/blob/main/src/interfaces/IIrm.sol) exposed below. Function[](https://docs.morpho.org/get-started/resources/contracts/irm/#function) ------------------------------------------------------------------------------------ ### borrowRate[](https://docs.morpho.org/get-started/resources/contracts/irm/#borrowrate) Copy `function borrowRate(MarketParams memory marketParams, Market memory market) external returns (uint256);` Returns the borrow rate of the market `marketParams`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/irm/#parameters) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho#marketparams-struct) | The MarketParams struct of the market. | | `market` | [Market](https://docs.morpho.org/get-started/resources/contracts/morpho#market-struct) | The Market struct of the market. | #### Return values:[](https://docs.morpho.org/get-started/resources/contracts/irm/#return-values) | Name | Type | Description | | --- | --- | --- | | `borrowRate` | uint256 | The borrow rate of the market. | View Function[](https://docs.morpho.org/get-started/resources/contracts/irm/#view-function) ---------------------------------------------------------------------------------------------- ### borrowRateView:[](https://docs.morpho.org/get-started/resources/contracts/irm/#borrowrateview) Copy `function borrowRateView(MarketParams memory marketParams, Market memory market) external view returns (uint256);` Returns the borrow rate of the market `marketParams` without modifying any storage. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/irm/#parameters-1) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho#marketparams-struct) | The MarketParams struct of the market. | | `market` | [Market](https://docs.morpho.org/get-started/resources/contracts/morpho#market-struct) | The Market struct of the market. | #### Return values:[](https://docs.morpho.org/get-started/resources/contracts/irm/#return-values-1) | Name | Type | Description | | --- | --- | --- | | `borrowRate` | uint256 | The borrow rate of the market. | Calculations[](https://docs.morpho.org/get-started/resources/contracts/irm/#calculations) -------------------------------------------------------------------------------------------- The Annual Percentage Yields (APY) for both borrowing and supplying are key indicators of the returns for lenders and the cost for borrowers. The APY takes into account the compounding interest to provide a standardized measure of yields over a one-year period. ### Borrow APY[](https://docs.morpho.org/get-started/resources/contracts/irm/#borrow-apy) The Borrow APY is calculated using the following formula: borrowAPY\=(e(borrowRate×secondsPerYear)−1)\\text{borrowAPY} = \\left(e^{\\left(\\text{borrowRate} \\times \\text{secondsPerYear}\\right)} - 1\\right) borrowAPY\=(e(borrowRate×secondsPerYear)−1) Where: * `borrowRate` is the borrow rate per second, as determined by the Interest Rate Model (IRM), * `secondsPerYear` represents the total number of seconds in a year (31,536,000). To obtain the `borrowRate` value, a simple call can be made to the `borrowRateView` or `borrowRate` functions defined in the upper sections. ### Supply APY[](https://docs.morpho.org/get-started/resources/contracts/irm/#supply-apy) The Supply APY is calculated considering the utilization and the fee. The formula is: The `fee` is the portion of the interest paid by borrowers that is retained by the protocol. For more details, see the [Curator Fee Section](https://docs.morpho.org/curate/concepts/fee) . supplyAPY\=borrowAPY×utilization×(1−fee)\\text{supplyAPY} = \\text{borrowAPY} \\times \\text{utilization} \\times (1 - \\text{fee}) supplyAPY\=borrowAPY×utilization×(1−fee) Where: * `fee` is the fee of the market, to be activated by the governance, on a per-market basis, * `utilization` is calculated as: utilization\=totalBorrowAssetstotalSupplyAssets\\text{utilization} = \\frac{\\text{totalBorrowAssets}}{\\text{totalSupplyAssets}} utilization\=totalSupplyAssetstotalBorrowAssets​ Here is a video that shows how the Adaptive Curve IRM works: Your browser does not support the video tag. Overview[](https://docs.morpho.org/get-started/resources/contracts/irm/#overview) ------------------------------------------------------------------------------------ In Morpho, the interest borrowers pay is defined by an external interest rate model (IRM) that can be chosen at market creation among a governance-defined collection. The AdaptiveCurveIRM is the first IRM that will be available for Morpho markets. It fundamentally differs from the ones used in traditional lending pools for two main reasons: * Unlike current lending pools' IRMs which can be updated, the AdaptiveCurveIRM is immutable. It must therefore adapt autonomously to market conditions, such as changes in interest rates on other venues. * In Morpho, the supply is not used as collateral. There is no need to keep markets very liquid to allow liquidations at any time. Removing this systemic risk enables more aggressive target utilization of the capital and lower penalties for illiquidity, enabling more efficient markets. The AdaptiveCurveIRM is designed to adjust utilization to the target utilization, which is set at 90%. There are two time horizons at play: In the short term, we don't want utilization to get too low, or too high and cause liquidity problems. In the medium and long term, we want the rate level to adapt to changing market dynamics. To achieve this, the AdaptiveCurveIRM adjusts user incentives through the action of two different mechanisms: * The Curve Mechanism * The Adaptive Mechanism The Curve Mechanism[](https://docs.morpho.org/get-started/resources/contracts/irm/#the-curve-mechanism) ---------------------------------------------------------------------------------------------------------- This mechanism is similar to the interest rate curve used in traditional lending pools. The curve is characterized by two parameters: r90% r\_{90\\%} r90%​ which is the target rate at utilization target u\_target\=0.9u\\\_{target}=0.9 u\_target\=0.9 and c\=4c=4 c\=4 a fixed parameter that determines the steepness of the curve above and below the utilization target. ![Curve Mechanism 1](https://docs.morpho.org/img/morpho-blue/curve-mechanism-01.png) At each interaction, utilization will change, resulting in a discontinuous change in the rate determined by the curve. For example: * if utilization is 90%, the rate is r\_90% r\\\_{90\\%} r\_90% * if utilization is 100%, the rate is 4∗r\_90%4\*r\\\_{90\\%} 4∗r\_90% (APR) The aim of the Curve Mechanism is to manage short-term utilization changes. The Adaptive Mechanism[](https://docs.morpho.org/get-started/resources/contracts/irm/#the-adaptive-mechanism) ---------------------------------------------------------------------------------------------------------------- This mechanism continuously shifts the curve to adjust to market conditions over time. Note that the rate follows the shift of the curve. This means that the rate is continuously evolving over time, even when there is no interaction. The shifting of the curve is done by continuously changing the value of r\_90%r\\\_{90\\%} r\_90% over time: * When the utilization is above the target utilization, r\_90% r\\\_{90\\%} r\_90% continuously shifts upwards. * When the utilization is below the target utilization, r90%r\_{90\\%} r90%​ continuously shifts downwards. ![Morpho Banner](https://docs.morpho.org/img/morpho-blue/curve-mechanism-02.png) The speed at which `math r_{90\%}` moves is updated at each interaction: the farther we are from the target, the faster r\_90%r\\\_{90\\%} r\_90% hence the curve, shifts. For example, if the utilization remains at 100% for 5 days, r\_90%r\\\_{90\\%} r\_90% will progressively double. This is the maximum speed at which r\_90%r\\\_{90\\%} r\_90% can move. Formal description[](https://docs.morpho.org/get-started/resources/contracts/irm/#formal-description) -------------------------------------------------------------------------------------------------------- We define: * Utilzation ( uu u ) u(t)u(t) u(t) is the ratio of total borrow over total supply at time tt t The utilization target is constant: u\_target\=0.9u\\\_{target}=0.9 u\_target\=0.9 * Error ( ee e ): ∀t,\\forall t, ∀t, e(u)\={u(t)−utarget1−utargetif u(t)\>utargetu(t)−utargetutargetif u(t)≤utargete(u)=\\begin{cases} \\frac{u(t)-u\_{target}}{1-u\_{target}}&\\text{if } u(t)>u\_{target} \\\\ \\frac{u(t)-u\_{target}}{u\_{target}}&\\text{if } u(t)\\le u\_{target} \\end{cases} e(u)\={1−utarget​u(t)−utarget​​utarget​u(t)−utarget​​​if u(t)\>utarget​if u(t)≤utarget​​ It can be seen as the difference between the utilization and the target, divided by a normalization factor. The normalization is here to make the distance between `math u_{target}` and `math u=1` equals to the distance between `math u_{target}` and u\=0u=0 u\=0 ![Morpho Banner](https://docs.morpho.org/img/morpho-blue/curve-mechanism-05.png) * Curve: curve(u)\={(1−1kd)∗e(u)+1if u≤utarget(kd−1)∗e(u)+1if u\>utarget\\text{curve}(u)= \\begin{cases} (1-\\frac{1}{k\_d})\*e(u)+1&\\text{if } u\\le u\_{target} \\\\ (k\_d-1)\*e(u)+1&\\text{if } u>u\_{target} \\end{cases} curve(u)\={(1−kd​1​)∗e(u)+1(kd​−1)∗e(u)+1​if u≤utarget​if u\>utarget​​ with kd\=4k\_d=4 kd​\=4 * History of interactions ( H\\mathcal{H} H ): Noting tit\_i ti​ the time at which the ithi^{th} ith interaction occurred, ∀t,\\forall t, ∀t, H(t)\={0}+{ti}ti0,rT(t)\=rT(last(t))∗speed(t)\\forall t >0, r\_T(t)=r\_{T}(\\text{last}(t))\*\\text{speed}(t) ∀t\>0,rT​(t)\=rT​(last(t))∗speed(t) At any time `math t` , the borrow rate rr r is given by the formula: r(t)\=rT(t)∗curve(u(t))r(t) = r\_{T}(t)\* \\text{curve}(u(t)) r(t)\=rT​(t)∗curve(u(t)) Implementation[](https://docs.morpho.org/get-started/resources/contracts/irm/#implementation) ------------------------------------------------------------------------------------------------ > [Adaptive Curve IRM Github repository](https://github.com/morpho-org/morpho-blue-irm) The contract implements the [Interest Rate Model interface](https://github.com/morpho-org/morpho-blue/blob/main/src/interfaces/IIrm.sol) to fit Morpho's specifications. Moreover, the implementation stores configuration variables and a market parameter updated at each `borrowRate` call for this market. Variables[](https://docs.morpho.org/get-started/resources/contracts/irm/#variables) -------------------------------------------------------------------------------------- ### Constants[](https://docs.morpho.org/get-started/resources/contracts/irm/#constants) The values of the following constants are hardcoded into the [code deployed on Ethereum](https://etherscan.io/address/0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC#code#F8#L27) * `CURVE_STEEPNESS`: Curve steepness (scaled by WAD), value = `4`. * `ADJUSTMENT_SPEED`: Adjustment speed per second (scaled by WAD), value = `50/nb of seconds per year`. * `TARGET_UTILIZATION`: Target utilization (scaled by WAD), value = `90%`. * `INITIAL_RATE_AT_TARGET`: Initial rate at target per second (scaled by WAD), value = `4%/nb of seconds per year`. * `MIN_RATE_AT_TARGET`: Minimum rate at target per second (scaled by WAD), value = `0.1%/nb of seconds per year`. * `MAX_RATE_AT_TARGET`: Maximum rate at target per second (scaled by WAD), value = `200%/nb of seconds per year`. Immutables[](https://docs.morpho.org/get-started/resources/contracts/irm/#immutables) ---------------------------------------------------------------------------------------- * `MORPHO`: Address of Morpho. Mappings[](https://docs.morpho.org/get-started/resources/contracts/irm/#mappings) ------------------------------------------------------------------------------------ ### Rate at target[](https://docs.morpho.org/get-started/resources/contracts/irm/#rate-at-target) Copy `mapping(Id => uint256) public rateAtTarget;` Rate at target utilization for each market. Tells the height of the curve. Events[](https://docs.morpho.org/get-started/resources/contracts/irm/#events) -------------------------------------------------------------------------------- ### BorrowRateUpdate[](https://docs.morpho.org/get-started/resources/contracts/irm/#borrowrateupdate) Copy `event BorrowRateUpdate(Id indexed id, uint256 avgBorrowRate, uint256 rateAtTarget);` Emitted when the borrow rate is updated (called by Morpho). #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/irm/#parameters-2) | Name | Type | Description | | --- | --- | --- | | `id` | Id | The id of the market. | | `avgBorrowRate` | uint256 | The average borrow rate of the market. | | `rateAtTarget` | uint256 | The stored rate at target of the market. | --- # Oracles – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/oracles/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Oracles On this page Chevron Right [← Back to contracts](https://docs.morpho.org/get-started/resources/contracts) Code[](https://docs.morpho.org/get-started/resources/contracts/oracles/#code) -------------------------------------------------------------------------------- [Morpho Chainlink Oracle V2](https://github.com/morpho-org/morpho-blue-oracles/tree/main/src/morpho-chainlink) Basics[](https://docs.morpho.org/get-started/resources/contracts/oracles/#basics) ------------------------------------------------------------------------------------ Oracles are contracts that can be used as oracles for markets on Morpho. The oracles implement the IOracle interface defined in [IOracle.sol](https://github.com/morpho-org/morpho-blue/blob/main/src/interfaces/IOracle.sol) . They return the price of 1 asset of collateral token quoted in 1 asset of loan token. price[](https://docs.morpho.org/get-started/resources/contracts/oracles/#price) ---------------------------------------------------------------------------------- Copy `function price() external view returns (uint256);` Returns the price of 1 asset of collateral token quoted in 1 asset of loan token, scaled by 1e36. * It corresponds to the price of 10\*\*(collateral token decimals) assets of collateral token quoted in 10 \*\*(loan token decimals) assets of loan token with `36 + loan token decimals - collateral token decimals` decimals of precision. ### Return values:[](https://docs.morpho.org/get-started/resources/contracts/oracles/#return-values) | Name | Type | Description | | --- | --- | --- | | `price` | uint256 | The price rate of 1 asset of collateral token quoted in 1 asset of loan token (scaled by 1e36). | MorphoChainlinkOracleV2[](https://docs.morpho.org/get-started/resources/contracts/oracles/#morphochainlinkoraclev2) ---------------------------------------------------------------------------------------------------------------------- This is an oracle that uses Chainlink-interface-compliant feeds to provide price data. This oracle handles the following cases among others (let's say that our pair is A/B): * A/B is a feed (typically, stETH/ETH). * B/A is a feed (typically, ETH/USDC). * A/C and B/C are feeds (typically, stETH/ETH and USDC/ETH). * A/C, C/D and B/D are feeds (typically, WBTC/BTC, BTC/USD, USDC/USD). * A/D, and B/C, C/D are feeds (typically, USDC/USD, WBTC/BTC, BTC/USD). * A/C, C/D and B/E, E/D are feeds. * A/C and C/B are feeds (typically, WBTC/BTC and BTC/ETH). * A'/C and B/C are feeds, and there is an exchange rate between A and A'. (typically A=sDAI and A'=DAI). WstETH/stETH Exchange Rate Adapter[](https://docs.morpho.org/get-started/resources/contracts/oracles/#wstethsteth-exchange-rate-adapter) ------------------------------------------------------------------------------------------------------------------------------------------- A specific implementation, the `WstEthStEthExchangeRateChainlinkAdapter`, provides the exchange rate between wstETH and stETH as a Chainlink-interface-compliant feed. This adapter is deployed on Ethereum Mainnet at the address [0x905b7dAbCD3Ce6B792D874e303D336424Cdb1421](https://etherscan.io/address/0x905b7dabcd3ce6b792d874e303d336424cdb1421#code) . MorphoChainlinkOracleV2Factory[](https://docs.morpho.org/get-started/resources/contracts/oracles/#morphochainlinkoraclev2factory) ------------------------------------------------------------------------------------------------------------------------------------ This factory deploys `MorphoChainlinkOracleV2` instances. The factory facilitates the creation and indexing of MorphoChainlinkOracleV2 oracles. This factory contract streamlines the process of deploying new oracles, catering to various market pairs without the need to deploy individual contracts manually for each pair. Implementation[](https://docs.morpho.org/get-started/resources/contracts/oracles/#implementation) ---------------------------------------------------------------------------------------------------- > [Morpho Chainlink Oracle V2 Github repository](https://github.com/morpho-org/morpho-blue-oracles/tree/main/src/morpho-chainlink) The contract implements the [Oracle interface](https://github.com/morpho-org/morpho-blue/blob/main/src/interfaces/IOracle.sol) to fit Morpho specifications: Immutables[](https://docs.morpho.org/get-started/resources/contracts/oracles/#immutables) -------------------------------------------------------------------------------------------- * `BASE_VAULT`: baseVault. Pass address zero to omit this parameter. * `BASE_VAULT_CONVERSION_SAMPLE`: Base vault conversion sample. * `BASE_FEED_1`: First base feed. Pass address zero if the price = 1. * `BASE_FEED_2`: Second base feed. Pass address zero if the price = 1. * `BASE_TOKEN_DECIMALS`: Base token decimals. * `QUOTE_VAULT`: Quote vault. Pass address zero to omit this parameter. * `QUOTE_VAULT_CONVERSION_SAMPLE`: The sample amount of quote vault shares used to convert to underlying. Pass 1 if the quote asset is not a vault. Should be chosen such that converting `quoteVaultConversionSample` to assets has enough precision. * `QUOTE_FEED_1`: First quote feed. Pass address zero if the price = 1. * `QUOTE_FEED_2`: Second quote feed. Pass address zero if the price = 1. * `QUOTE_TOKEN_DECIMALS`: Quote token decimals. Assumptions[](https://docs.morpho.org/get-started/resources/contracts/oracles/#assumptions) ---------------------------------------------------------------------------------------------- Here is the list of assumptions that guarantees the oracle behaves as expected: * The vaults, if set, are ERC4626-compliant. * The feeds, if set, are Chainlink-interface-compliant. * Decimals passed as argument are correct. * The base vaults's sample shares quoted as assets and the base feed prices don't overflow when multiplied. * The quote vault's sample shares quoted as assets and the quote feed prices don't overflow when multiplied. --- # Universal Rewards Distributors – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/rewards/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Universal Rewards Distributors On this page Chevron Right [← Back to contracts](https://docs.morpho.org/get-started/resources/contracts) Code[](https://docs.morpho.org/get-started/resources/contracts/rewards/#code) -------------------------------------------------------------------------------- [Universal Rewards Distributors repository](https://github.com/morpho-org/universal-rewards-distributor/tree/main) Contract Overview[](https://docs.morpho.org/get-started/resources/contracts/rewards/#contract-overview) ---------------------------------------------------------------------------------------------------------- The [`UniversalRewardsDistributor`](https://github.com/morpho-org/universal-rewards-distributor/tree/main) contract facilitates the distribution of various reward tokens to multiple accounts using different Merkle trees. It is designed to operate in a permissionless manner and is inspired by Morpho's current rewards distributor. The contract enables the dynamic update of distribution parameters, management of reward claims, and ensures the integrity of the distribution through the use of Merkle proofs. Functions[](https://docs.morpho.org/get-started/resources/contracts/rewards/#functions) ------------------------------------------------------------------------------------------ ### submitRoot[](https://docs.morpho.org/get-started/resources/contracts/rewards/#submitroot) Copy `function submitRoot(bytes32 newRoot, bytes32 newIpfsHash) external onlyUpdaterRole;` Submits a new merkle root for the distribution of rewards. * Can only be called by an address with updater role. * Emits a `PendingRootSet` event. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/rewards/#parameters) | Name | Type | Description | | --- | --- | --- | | `newRoot` | bytes32 | The new merkle root. | | `newIpfsHash` | bytes32 | The optional ipfs hash containing metadata about the root. | ### acceptRoot[](https://docs.morpho.org/get-started/resources/contracts/rewards/#acceptroot) Copy `function acceptRoot() external;` Accepts and sets the current pending merkle root after the timelock has expired. * Can be called by any address. * Reverts if no pending root is set or if the timelock has not expired. * Emits a `RootSet` event upon successful execution. ### revokePendingRoot[](https://docs.morpho.org/get-started/resources/contracts/rewards/#revokependingroot) Copy `function revokePendingRoot() external onlyUpdaterRole;` Revokes the current pending merkle root. * Can only be called by an address with updater role. * Reverts if no pending root is set. * Emits a `PendingRootRevoked` event. ### claim[](https://docs.morpho.org/get-started/resources/contracts/rewards/#claim) Copy `function claim(address account, address reward, uint256 claimable, bytes32[] calldata proof) external returns (uint256 amount);` Claims rewards for a specific account. * Reverts if the root is not set, if the proof is invalid, or if the claimable amount is less than the amount already claimed. * Emits a `Claimed` event upon successful execution. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/rewards/#parameters-1) | Name | Type | Description | | --- | --- | --- | | `account` | address | The address to claim rewards for. | | `reward` | address | The address of the reward token. | | `claimable` | uint256 | The overall claimable amount of token rewards. | | `proof` | bytes32\[\] | The merkle proof that validates this claim. | #### Return values:[](https://docs.morpho.org/get-started/resources/contracts/rewards/#return-values) | Name | Type | Description | | --- | --- | --- | | `amount` | uint256 | The amount of reward token claimed. | ### setRoot[](https://docs.morpho.org/get-started/resources/contracts/rewards/#setroot) Copy `function setRoot(bytes32 newRoot, bytes32 newIpfsHash) external onlyUpdaterRole;` Forces update of the distribution's merkle root, bypassing the timelock. * Can only be called by the owner of the distribution or by updaters if there is no timelock. * Reverts if the new root is the same as the current root and if the caller is unauthorized to change the root. * Emits a `RootSet` event upon successful execution. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/rewards/#parameters-2) | Name | Type | Description | | --- | --- | --- | | `newRoot` | bytes32 | The new merkle root. | | `newIpfsHash` | bytes32 | The optional ipfs hash containing metadata about the root. | ### setTimelock[](https://docs.morpho.org/get-started/resources/contracts/rewards/#settimelock) Copy `function setTimelock(uint256 newTimelock) external onlyOwner;` Sets a new timelock for the distribution. * Can only be called by the owner of the distribution. * Reverts if the new timelock is the same as the current timelock. * Emits a `TimelockSet` event upon successful execution. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/rewards/#parameters-3) | Name | Type | Description | | --- | --- | --- | | `newTimelock` | uint256 | The new timelock. | ### setRootUpdater[](https://docs.morpho.org/get-started/resources/contracts/rewards/#setrootupdater) Copy `function setRootUpdater(address updater, bool active) external onlyOwner;` Sets or unsets an address as a root updater. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/rewards/#parameters-4) | Name | Type | Description | | --- | --- | --- | | `updater` | address | The address of the root updater. | | `active` | bool | Whether the root updater should be active or not. | * Can only be called by the owner of the distribution. * Reverts if the updater status is already set as specified. * Emits a `RootUpdaterSet` event upon successful execution. ### setOwner[](https://docs.morpho.org/get-started/resources/contracts/rewards/#setowner) Copy `function setOwner(address newOwner) external onlyOwner;` Transfers ownership of the distribution to a new address. * Can only be called by the current owner. * Reverts if the new owner is the same as the current owner. * Emits an `OwnerSet` event upon successful execution. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/rewards/#parameters-5) | Name | Type | Description | | --- | --- | --- | | `newOwner` | address | The address of the new owner. | Events[](https://docs.morpho.org/get-started/resources/contracts/rewards/#events) ------------------------------------------------------------------------------------ The contract emits events to signify important actions and state changes. Here are the events associated with the `UniversalRewardsDistributor` contract: * `PendingRootSet`: Emitted when a new pending root is submitted. * `PendingRootRevoked`: Emitted when a pending root is revoked. * `RootSet`: Emitted when a new root is accepted and set. * `Claimed`: Emitted when rewards are successfully claimed. * `RootUpdaterSet`: Emitted when a root updater's status is changed. * `OwnerSet`: Emitted when a new owner is set for the distribution. * `TimelockSet`: Emitted when the timelock is updated. Roles[](https://docs.morpho.org/get-started/resources/contracts/rewards/#roles) ---------------------------------------------------------------------------------- There are only 2 roles: * **Owner**: owner of the contract that has access to the updater's functions and [`setTimelock`](https://docs.morpho.org/get-started/resources/contracts/rewards/#settimelock) , [`setRootUpdater`](https://docs.morpho.org/get-started/resources/contracts/rewards/#setrootupdater) , and [`setOwner`](https://docs.morpho.org/get-started/resources/contracts/rewards/#setowner) functions. * **Updater**: addresses that can trigger the [`submitRoot`](https://docs.morpho.org/get-started/resources/contracts/rewards/#submitroot) , [`setRoot`](https://docs.morpho.org/get-started/resources/contracts/rewards/#setroot) , and [`revokePendingRoot`](https://docs.morpho.org/get-started/resources/contracts/rewards/#revokependingroot) functions. --- # Morpho Vaults V2 – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Morpho Vaults V2 On this page Chevron Right [← Back to contracts](https://docs.morpho.org/get-started/resources/contracts) Code[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#code) ----------------------------------------------------------------------------------------- [v2.0 repository](https://github.com/morpho-org/vault-v2) Structs & Types[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#structs--types) -------------------------------------------------------------------------------------------------------------- ### Caps[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#caps) Copy `struct Caps { uint256 allocation; uint128 absoluteCap; uint128 relativeCap; }` | Name | Type | Description | | --- | --- | --- | | `allocation` | uint256 | The current amount of assets allocated to this `id`. | | `absoluteCap` | uint128 | The maximum amount of assets that can be allocated to this `id`. | | `relativeCap` | uint128 | The maximum percentage of total assets that can be allocated to this `id`, scaled by 1e18. | External Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#external-functions) --------------------------------------------------------------------------------------------------------------------- ### `deposit`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#deposit) Copy `function deposit(uint256 assets, address onBehalf) external returns (uint256)` Deposits `assets` of the underlying token to mint vault shares for `onBehalf`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of the underlying asset to deposit. | | `onBehalf` | address | The recipient of the minted vault shares. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of vault shares minted. | ### `mint`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#mint) Copy `function mint(uint256 shares, address onBehalf) external returns (uint256)` Mints exactly `shares` vault shares for `onBehalf` by depositing the required amount of the underlying token. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-1) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The exact amount of shares to mint. | | `onBehalf` | address | The recipient of the minted vault shares. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-1) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of the underlying asset deposited. | ### `withdraw`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#withdraw) Copy `function withdraw(uint256 assets, address receiver, address onBehalf) public returns (uint256)` Withdraws `assets` of the underlying token by burning shares from `onBehalf` and sends them to `receiver`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-2) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of the underlying asset to withdraw. | | `receiver` | address | The recipient of the withdrawn assets. | | `onBehalf` | address | The owner of the shares to be burned. `msg.sender` must be approved. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-2) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of vault shares burned. | ### `redeem`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#redeem) Copy `function redeem(uint256 shares, address receiver, address onBehalf) external returns (uint256)` Burns exactly `shares` vault shares from `onBehalf` and sends the corresponding amount of underlying assets to `receiver`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-3) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The exact amount of shares to burn. | | `receiver` | address | The recipient of the withdrawn assets. | | `onBehalf` | address | The owner of the shares to be burned. `msg.sender` must be approved. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-3) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of the underlying asset withdrawn. | ### `forceDeallocate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#forcedeallocate) Copy `function forceDeallocate(address adapter, bytes memory data, uint256 assets, address onBehalf) external returns (uint256)` Forcibly deallocates `assets` from a specific `adapter` to the vault's idle pool. A penalty is taken from `onBehalf`'s shares to disincentivize misuse. This function is permissionless and serves as an in-kind redemption mechanism. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-4) | Name | Type | Description | | --- | --- | --- | | `adapter` | address | The adapter to deallocate from. | | `data` | bytes | The protocol-specific data for the deallocation. | | `assets` | uint256 | The amount of assets to deallocate. | | `onBehalf` | address | The account from which the penalty shares will be burned. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-4) | Name | Type | Description | | --- | --- | --- | | `withdrawnShares` | uint256 | The amount of shares burned from `onBehalf` as a penalty. | ### `accrueInterest`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#accrueinterest) Copy `function accrueInterest() public` Accrues interest for the vault by querying adapters for their current assets and updating `totalAssets`. This function is called by most state-changing functions. ### `accrueInterestView`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#accrueinterestview) Copy `function accrueInterestView() public view returns (uint256, uint256, uint256)` Returns the view version of interest accrual without updating state. #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-5) | Name | Type | Description | | --- | --- | --- | | `newTotalAssets` | uint256 | The updated total assets after interest accrual. | | `performanceFeeShares` | uint256 | The amount of shares minted as performance fee. | | `managementFeeShares` | uint256 | The amount of shares minted as management fee. | ### `previewDeposit`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#previewdeposit) Copy `function previewDeposit(uint256 assets) public view returns (uint256)` Returns previewed minted shares for a given asset amount. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-5) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of assets to preview deposit for. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-6) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of shares that would be minted. | ### `previewMint`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#previewmint) Copy `function previewMint(uint256 shares) public view returns (uint256)` Returns previewed deposited assets for a given share amount. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-6) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of shares to preview mint for. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-7) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of assets that would be deposited. | ### `previewWithdraw`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#previewwithdraw) Copy `function previewWithdraw(uint256 assets) public view returns (uint256)` Returns previewed redeemed shares for a given asset amount. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-7) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of assets to preview withdrawal for. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-8) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of shares that would be burned. | ### `previewRedeem`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#previewredeem) Copy `function previewRedeem(uint256 shares) public view returns (uint256)` Returns previewed withdrawn assets for a given share amount. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-8) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of shares to preview redemption for. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-9) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of assets that would be withdrawn. | ### `convertToShares`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#converttoshares) Copy `function convertToShares(uint256 assets) external view returns (uint256)` Returns corresponding shares (rounded down) for a given asset amount. Takes into account performance and management fees. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-9) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of assets to convert. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-10) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The corresponding amount of shares. | ### `convertToAssets`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#converttoassets) Copy `function convertToAssets(uint256 shares) external view returns (uint256)` Returns corresponding assets (rounded down) for a given share amount. Takes into account performance and management fees. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-10) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of shares to convert. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-11) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The corresponding amount of assets. | ### `maxDeposit`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#maxdeposit) Copy `function maxDeposit(address) external pure returns (uint256)` Returns the maximum amount of assets that can be deposited. Always returns 0 due to gate complexity. ### `maxMint`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#maxmint) Copy `function maxMint(address) external pure returns (uint256)` Returns the maximum amount of shares that can be minted. Always returns 0 due to gate complexity. ### `maxWithdraw`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#maxwithdraw) Copy `function maxWithdraw(address) external pure returns (uint256)` Returns the maximum amount of assets that can be withdrawn. Always returns 0 due to gate complexity. ### `maxRedeem`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#maxredeem) Copy `function maxRedeem(address) external pure returns (uint256)` Returns the maximum amount of shares that can be redeemed. Always returns 0 due to gate complexity. ### `multicall`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#multicall) Copy `function multicall(bytes[] calldata data) external` Useful for EOAs to batch admin calls. Does not return anything, because accounts who would use the return data would be contracts, which can do the multicall themselves. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-11) | Name | Type | Description | | --- | --- | --- | | `data` | bytes\[\] | Array of encoded function calls to execute. | Owner Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#owner-functions) --------------------------------------------------------------------------------------------------------------- ### `setOwner`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setowner) Copy `function setOwner(address newOwner) external` Transfers ownership of the vault to `newOwner`. Only callable by the current `owner`. ### `setCurator`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setcurator) Copy `function setCurator(address newCurator) external` Sets the vault's `Curator`. Only callable by the `owner`. ### `setIsSentinel`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setissentinel) Copy `function setIsSentinel(address account, bool newIsSentinel) external` Grants or revokes the `Sentinel` role for an `account`. Only callable by the `owner`. ### `setName`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setname) Copy `function setName(string memory newName) external` Sets the vault's name. Only callable by the `owner`. ### `setSymbol`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setsymbol) Copy `function setSymbol(string memory newSymbol) external` Sets the vault's symbol. Only callable by the `owner`. Curator Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#curator-functions) ------------------------------------------------------------------------------------------------------------------- The following functions are only callable by the `Curator`. Some are subject to a **timelock** while others are **instant**. The timelock process is: 1. `Curator` calls `submit(bytes calldata data)` with the ABI-encoded function call. 2. After the timelock expires, anyone can execute the function directly. ### `abdicate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#abdicate) Copy `function abdicate(bytes4 selector) external` Irreversibly disables the ability to submit a specific type of action. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-12) | Name | Type | Description | | --- | --- | --- | | `selector` | bytes4 | The function selector to abdicate. | ### `addAdapter`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#addadapter) Copy `function addAdapter(address account) external` Adds a new adapter to the vault. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-13) | Name | Type | Description | | --- | --- | --- | | `account` | address | The adapter address to add. | ### `decreaseAbsoluteCap`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#decreaseabsolutecap) Copy `function decreaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external` Decreases the absolute cap for an `id`. **Instant Action** (also callable by a `Sentinel`) #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-14) | Name | Type | Description | | --- | --- | --- | | `idData` | bytes | The ID data to decrease cap for. | | `newAbsoluteCap` | uint256 | The new absolute cap value. | ### `decreaseRelativeCap`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#decreaserelativecap) Copy `function decreaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external` Decreases the relative cap for an `id`. **Instant Action** (also callable by a `Sentinel`) #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-15) | Name | Type | Description | | --- | --- | --- | | `idData` | bytes | The ID data to decrease cap for. | | `newRelativeCap` | uint256 | The new relative cap value (scaled by 1e18). | ### `decreaseTimelock`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#decreasetimelock) Copy `function decreaseTimelock(bytes4 selector, uint256 newDuration) external` Decreases a function's timelock duration (this action itself has a 3-week timelock). **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-16) | Name | Type | Description | | --- | --- | --- | | `selector` | bytes4 | The function selector. | | `newDuration` | uint256 | The new timelock duration. | ### `increaseAbsoluteCap`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#increaseabsolutecap) Copy `function increaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external` Increases the absolute cap for an `id`. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-17) | Name | Type | Description | | --- | --- | --- | | `idData` | bytes | The ID data to increase cap for. | | `newAbsoluteCap` | uint256 | The new absolute cap value. | ### `increaseRelativeCap`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#increaserelativecap) Copy `function increaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external` Increases the relative cap for an `id`. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-18) | Name | Type | Description | | --- | --- | --- | | `idData` | bytes | The ID data to increase cap for. | | `newRelativeCap` | uint256 | The new relative cap value (scaled by 1e18). | ### `increaseTimelock`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#increasetimelock) Copy `function increaseTimelock(bytes4 selector, uint256 newDuration) external` Increases a function's timelock duration. **Instant Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-19) | Name | Type | Description | | --- | --- | --- | | `selector` | bytes4 | The function selector. | | `newDuration` | uint256 | The new timelock duration. | ### `removeAdapter`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#removeadapter) Copy `function removeAdapter(address account) external` Removes an adapter from the vault. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-20) | Name | Type | Description | | --- | --- | --- | | `account` | address | The adapter address to remove. | ### `revoke`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#revoke) Copy `function revoke(bytes calldata data) external` Revokes a pending timelocked action. **Instant Action** (also callable by a `Sentinel`) #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-21) | Name | Type | Description | | --- | --- | --- | | `data` | bytes | The ABI-encoded function call data to revoke. | ### `setAdapterRegistry`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setadapterregistry) Copy `function setAdapterRegistry(address newAdapterRegistry) external` Sets the adapter registry contract. The no-op will revert if the registry now returns false for an already added adapter. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-22) | Name | Type | Description | | --- | --- | --- | | `newAdapterRegistry` | address | The new adapter registry contract. | ### `setForceDeallocatePenalty`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setforcedeallocatepenalty) Copy `function setForceDeallocatePenalty(address adapter, uint256 newForceDeallocatePenalty) external` Sets the penalty for using `forceDeallocate` on a specific adapter. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-23) | Name | Type | Description | | --- | --- | --- | | `adapter` | address | The adapter to set penalty for. | | `newForceDeallocatePenalty` | uint256 | The new penalty value (scaled by 1e18). | ### `setIsAllocator`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setisallocator) Copy `function setIsAllocator(address account, bool newIsAllocator) external` Grants or revokes the `Allocator` role for an account. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-24) | Name | Type | Description | | --- | --- | --- | | `account` | address | The account to modify. | | `newIsAllocator` | bool | Whether the account should be an allocator. | ### `setManagementFee`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setmanagementfee) Copy `function setManagementFee(uint256 newManagementFee) external` Sets the vault's management fee. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-25) | Name | Type | Description | | --- | --- | --- | | `newManagementFee` | uint256 | The new management fee (scaled by 1e18). | ### `setManagementFeeRecipient`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setmanagementfeerecipient) Copy `function setManagementFeeRecipient(address newManagementFeeRecipient) external` Sets the management fee recipient. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-26) | Name | Type | Description | | --- | --- | --- | | `newManagementFeeRecipient` | address | The new management fee recipient. | ### `setPerformanceFee`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setperformancefee) Copy `function setPerformanceFee(uint256 newPerformanceFee) external` Sets the vault's performance fee. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-27) | Name | Type | Description | | --- | --- | --- | | `newPerformanceFee` | uint256 | The new performance fee (scaled by 1e18). | ### `setPerformanceFeeRecipient`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setperformancefeerecipient) Copy `function setPerformanceFeeRecipient(address newPerformanceFeeRecipient) external` Sets the performance fee recipient. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-28) | Name | Type | Description | | --- | --- | --- | | `newPerformanceFeeRecipient` | address | The new performance fee recipient. | ### `setReceiveAssetsGate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setreceiveassetsgate) Copy `function setReceiveAssetsGate(address newReceiveAssetsGate) external` Sets the contract for gating asset receipts. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-29) | Name | Type | Description | | --- | --- | --- | | `newReceiveAssetsGate` | address | The new receive assets gate contract. | ### `setReceiveSharesGate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setreceivesharesgate) Copy `function setReceiveSharesGate(address newReceiveSharesGate) external` Sets the contract for gating share receipts. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-30) | Name | Type | Description | | --- | --- | --- | | `newReceiveSharesGate` | address | The new receive shares gate contract. | ### `setSendAssetsGate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setsendassetsgate) Copy `function setSendAssetsGate(address newSendAssetsGate) external` Sets the contract for gating asset sends. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-31) | Name | Type | Description | | --- | --- | --- | | `newSendAssetsGate` | address | The new send assets gate contract. | ### `setSendSharesGate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setsendsharesgate) Copy `function setSendSharesGate(address newSendSharesGate) external` Sets the contract for gating share sends. **Timelocked Action** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-32) | Name | Type | Description | | --- | --- | --- | | `newSendSharesGate` | address | The new send shares gate contract. | ### `submit`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#submit) Copy `function submit(bytes calldata data) external` Submits a timelocked action for execution after the timelock period expires. **Timelock Management Function** #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-33) | Name | Type | Description | | --- | --- | --- | | `data` | bytes | The ABI-encoded function call data. | Allocator Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#allocator-functions) ----------------------------------------------------------------------------------------------------------------------- ### `allocate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#allocate) Copy `function allocate(address adapter, bytes memory data, uint256 assets) external` Allocates `assets` from the vault's idle pool to a specific `adapter`. ### `deallocate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#deallocate) Copy `function deallocate(address adapter, bytes memory data, uint256 assets) external` Deallocates `assets` from an `adapter` back to the vault's idle pool. Also callable by a `Sentinel`. ### `setLiquidityAdapterAndData`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setliquidityadapteranddata) Copy `function setLiquidityAdapterAndData(address newLiquidityAdapter, bytes memory newLiquidityData) external` Sets the default adapter for handling user deposits and withdrawals. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-34) | Name | Type | Description | | --- | --- | --- | | `newLiquidityAdapter` | address | The new liquidity adapter address. | | `newLiquidityData` | bytes | The new liquidity data for the adapter. | ### `setMaxRate`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#setmaxrate) Copy `function setMaxRate(uint256 newMaxRate) external` Sets the maximum rate at which `totalAssets` can grow. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-35) | Name | Type | Description | | --- | --- | --- | | `newMaxRate` | uint256 | The new maximum rate (scaled by 1e18). | Gating Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#gating-functions) ----------------------------------------------------------------------------------------------------------------- ### `canReceiveShares`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#canreceiveshares) Copy `function canReceiveShares(address account) public view returns (bool)` Checks if an account can receive shares based on the receive shares gate. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-36) | Name | Type | Description | | --- | --- | --- | | `account` | address | The account to check. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-12) | Name | Type | Description | | --- | --- | --- | | `allowed` | bool | Whether the account can receive shares. | ### `canSendShares`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#cansendshares) Copy `function canSendShares(address account) public view returns (bool)` Checks if an account can send shares based on the send shares gate. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-37) | Name | Type | Description | | --- | --- | --- | | `account` | address | The account to check. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-13) | Name | Type | Description | | --- | --- | --- | | `allowed` | bool | Whether the account can send shares. | ### `canReceiveAssets`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#canreceiveassets) Copy `function canReceiveAssets(address account) public view returns (bool)` Checks if an account can receive assets based on the receive assets gate. The vault itself is always allowed. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-38) | Name | Type | Description | | --- | --- | --- | | `account` | address | The account to check. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-14) | Name | Type | Description | | --- | --- | --- | | `allowed` | bool | Whether the account can receive assets. | ### `canSendAssets`[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#cansendassets) Copy `function canSendAssets(address account) public view returns (bool)` Checks if an account can send assets based on the send assets gate. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#parameters-39) | Name | Type | Description | | --- | --- | --- | | `account` | address | The account to check. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/#return-values-15) | Name | Type | Description | | --- | --- | --- | | `allowed` | bool | Whether the account can send assets. | --- # Public Allocator – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Public Allocator On this page Chevron Right [← Back to contracts](https://docs.morpho.org/get-started/resources/contracts) Code[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#code) ----------------------------------------------------------------------------------------- [Public Allocator repository](https://github.com/morpho-org/public-allocator) Overview[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#overview) ------------------------------------------------------------------------------------------------- The `PublicAllocator` contract is a publicly callable allocator for Morpho Vaults. It allows for the efficient reallocation of assets within the vault, enabling borrowers or Morpho's interface to trigger reallocations and amplify the available liquidity for end users while ensuring the flow caps are respected. Constants[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#constants) --------------------------------------------------------------------------------------------------- ### MAX\_SETTABLE\_FLOW\_CAP[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#max_settable_flow_cap) The maximum settable flow cap, defined such that caps can always be stored on 128 bits. The actual max possible flow cap is `type(uint128).max / 2`, which equals `170141183460469231731687303715884105727`. Structs[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#structs) ----------------------------------------------------------------------------------------------- ### FlowCaps[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#flowcaps) The `FlowCaps` struct is defined as follows: Copy `struct FlowCaps { uint128 maxIn; uint128 maxOut; }` It contains the maximum allowed inflow and outflow for a market. ### FlowCapsConfig[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#flowcapsconfig) The `FlowCapsConfig` struct is defined as follows: Copy `struct FlowCapsConfig { Id id; FlowCaps caps; }` It is used to configure the flow caps for a market. ### Withdrawal[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#withdrawal) The `Withdrawal` struct is defined as follows: Copy `struct Withdrawal { MarketParams marketParams; uint128 amount; }` It specifies the market and the amount to withdraw. Functions[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#functions) --------------------------------------------------------------------------------------------------- ### setAdmin[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#setadmin) Copy `function setAdmin(address vault, address newAdmin) external;` Sets `newAdmin` as the admin for the specified vault. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#parameters) | Name | Type | Description | | --- | --- | --- | | `vault` | address | The address of the vault. | | `newAdmin` | address | The new admin address. | ### setFee[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#setfee) Copy `function setFee(address vault, uint256 newFee) external;` Sets the `newFee` for the specified vault. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#parameters-1) | Name | Type | Description | | --- | --- | --- | | `vault` | address | The address of the vault. | | `newFee` | uint256 | The new fee value. | ### setFlowCaps[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#setflowcaps) Copy `function setFlowCaps(address vault, FlowCapsConfig[] calldata config) external;` Sets the maximum inflow and outflow for the specified markets in the given vault. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#parameters-2) | Name | Type | Description | | --- | --- | --- | | `vault` | address | The address of the vault. | | `config` | FlowCapsConfig\[\] calldata | The flow caps configuration array. | ### transferFee[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#transferfee) Copy `function transferFee(address vault, address payable feeRecipient) external;` Transfers the accrued fee to the specified recipient for the given vault. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#parameters-3) | Name | Type | Description | | --- | --- | --- | | `vault` | address | The address of the vault. | | `feeRecipient` | address | The address of the recipient. | ### reallocateTo[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#reallocateto) Copy `function reallocateTo( address vault, Withdrawal[] calldata withdrawals, MarketParams calldata supplyMarketParams ) external payable;` Reallocates assets from a list of markets to one market in the specified vault. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#parameters-4) | Name | Type | Description | | --- | --- | --- | | `vault` | address | The address of the vault. | | `withdrawals` | Withdrawal\[\] calldata | The markets and amounts to withdraw. | | `supplyMarketParams` | MarketParams calldata | The market to which total withdrawn assets are supplied. | Events[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#events) --------------------------------------------------------------------------------------------- ### PublicWithdrawal[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#publicwithdrawal) Copy `event PublicWithdrawal(address indexed sender, address indexed vault, Id indexed id, uint256 withdrawnAssets);` Emitted during a public reallocation for each withdrawn-from market. ### PublicReallocateTo[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#publicreallocateto) Copy `event PublicReallocateTo(address indexed sender, address indexed vault, Id indexed supplyMarketId, uint256 suppliedAssets);` Emitted at the end of a public reallocation. ### SetAdmin[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#setadmin-1) Copy `event SetAdmin(address indexed sender, address indexed vault, address admin);` Emitted when the admin is set for a vault. ### SetFee[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#setfee-1) Copy `event SetFee(address indexed sender, address indexed vault, uint256 fee);` Emitted when the fee is set for a vault. ### TransferFee[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#transferfee-1) Copy `event TransferFee(address indexed sender, address indexed vault, uint256 amount, address indexed feeRecipient);` Emitted when the fee is transferred for a vault. ### SetFlowCaps[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#setflowcaps-1) Copy `event SetFlowCaps(address indexed sender, address indexed vault, FlowCapsConfig[] config);` Emitted when the flow caps are set for a vault. Error Handling[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#error-handling) ------------------------------------------------------------------------------------------------------------- ### ErrorsLib[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#errorslib) The `ErrorsLib` library defines various error messages used by the `PublicAllocator` contract. * `NotAdminNorVaultOwner()`: Thrown when the caller is not the admin nor the owner of the vault. * `IncorrectFee()`: Thrown when the reallocation fee given is wrong. * `AlreadySet()`: Thrown when the value is already set. * `EmptyWithdrawals()`: Thrown when `withdrawals` is empty. * `InconsistentWithdrawals()`: Thrown when `withdrawals` contains a duplicate or is not sorted. * `DepositMarketInWithdrawals()`: Thrown when the deposit market is in `withdrawals`. * `MarketNotEnabled(Id id)`: Thrown when attempting to reallocate or set flows to non-zero values for a non-enabled market. * `WithdrawZero(Id id)`: Thrown when attempting to withdraw zero of a market. * `MaxSettableFlowCapExceeded()`: Thrown when attempting to set max inflow/outflow above the `MAX_SETTABLE_FLOW_CAP`. * `NotEnoughSupply(Id id)`: Thrown when attempting to withdraw more than the available supply of a market. * `MaxOutflowExceeded(Id id)`: Thrown when attempting to withdraw more than the max outflow of a market. * `MaxInflowExceeded(Id id)`: Thrown when attempting to supply more than the max inflow of a market. Interfaces[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#interfaces) ----------------------------------------------------------------------------------------------------- ### IPublicAllocatorBase[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#ipublicallocatorbase) Defines the basic interface for the `PublicAllocator`. ### IPublicAllocatorStaticTyping[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#ipublicallocatorstatictyping) Inherits from `IPublicAllocatorBase` and includes a function to get flow caps. ### IPublicAllocator[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#ipublicallocator) The primary interface for the `PublicAllocator`. Conclusion[](https://docs.morpho.org/get-started/resources/contracts/public-allocator/#conclusion) ----------------------------------------------------------------------------------------------------- The `PublicAllocator` contract is a crucial component for managing asset reallocations within Morpho Vaults, ensuring efficient liquidity management while adhering to set flow caps. --- # Morpho Vaults – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Morpho Vaults On this page Chevron Right [← Back to contracts](https://docs.morpho.org/get-started/resources/contracts) Code[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#code) -------------------------------------------------------------------------------------- [V1.1 repository](https://github.com/morpho-org/metamorpho-v1.1) [V1.0 repository](https://github.com/morpho-org/metamorpho) Market[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#market) ------------------------------------------------------------------------------------------ Those following 3 elements are defined in the [Morpho related section](https://docs.morpho.org/get-started/resources/contracts/morpho#market-parameters) . * `MarketParams` struct, * `market` struct, * `Id` of markets. Also we have: Copy `struct MarketAllocation { MarketParams marketParams; uint256 assets; }` | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho#marketparams-struct) | The market to allocate funds to. | | `assets` | uint256 | The amount of assets to allocate. | External Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#external-functions) ------------------------------------------------------------------------------------------------------------------ ### deposit[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#deposit) Copy `function deposit(uint256 assets, address receiver) public override returns (uint256 shares) {}` Deposits `assets` of underlying token into the vault to mint vault shares to `receiver`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The quantity of asset to deposit. | | `receiver` | address | The address that will own the position on the vault. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#return-values) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of vault shares minted. | ### mint[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#mint) Copy `function mint(uint256 shares, address receiver) public override returns (uint256 assets) {}` Mints exactly `shares` vault shares to receiver by depositing underlying tokens into the vault. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-1) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The quantity of shares to mint. | | `receiver` | address | The address that will own the position on the vault. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#return-values-1) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of underlying token deposited. | ### withdraw[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#withdraw) Copy `function withdraw(uint256 assets, address receiver, address owner) public override returns (uint256 shares) {}` Withdraws `assets` of underlying token by burning vault shares of `owner`, and sends the withdrawn assets to `receiver`. `msg.sender` must be authorized to manage `owner`'s vault balance. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-2) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The quantity of asset to withdraw. | | `receiver` | address | The address that will receive the withdrawn assets. | | `owner` | address | The address that will see its position burnt of the amount of assets. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#return-values-2) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The amount of shares burned. | ### redeem[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#redeem) Copy `function redeem(uint256 shares, address receiver, address owner) public override returns (uint256 assets) {}` Burns exactly `shares` vault shares from `owner` and sends the withdrawn assets of underlying tokens to `receiver`. `msg.sender` must be authorized to manage `owner`'s vault balance. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-3) | Name | Type | Description | | --- | --- | --- | | `shares` | uint256 | The quantity of shares to burn. | | `receiver` | address | The address that will receive the minted shares. | | `owner` | address | The address that will see its position burnt of the amount of shares. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#return-values-3) | Name | Type | Description | | --- | --- | --- | | `assets` | uint256 | The amount of underlying token withdrawn. | ### acceptTimelock[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#accepttimelock) Copy `function acceptTimelock() external;` Accepts the pending timelock. This function is timelocked, which means `timelock` must have passed since the pending timelock submission for this function to be successfully called. ### acceptGuardian[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#acceptguardian) Copy `function acceptGuardian() external afterTimelock(pendingGuardian.validAt) {}` Accepts the pending guardian. This function is timelocked, which means `timelock` must have passed since the pending guardian submission for this function to be successfully called. ### acceptCap[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#acceptcap) Copy `function acceptCap(MarketParams memory marketParams) external;` Accepts the pending cap of the market defined by `marketParams`. This function is timelocked, which means `timelock` must have passed since the pending cap submission for this function to be successfully called. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-4) | Name | Type | Description | | --- | --- | --- | | `id` | [Id](https://docs.morpho.org/get-started/resources/contracts/morpho#market-id) | The id of the market to accept the cap. | ### skim[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#skim) Copy `function skim(address token) external {}` Skims the vault `token` balance to `skimRecipient`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-5) | Name | Type | Description | | --- | --- | --- | | `token` | address | The address of the token to skim the balance of. | The following functions are inheriting the [IERC4626 interface](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/interfaces/IERC4626.sol) OnlyOwner Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#onlyowner-functions) -------------------------------------------------------------------------------------------------------------------- ### setName (V1.1)[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#setname-v11) Copy `function setName(string memory newName) external onlyOwner {}` Sets the vault's name to `newName`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-6) | Name | Type | Description | | --- | --- | --- | | `newName` | string | The new name of the vault | ### setSymbol (V1.1)[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#setsymbol-v11) Copy `function setSymbol(string memory newSymbol) external onlyOwner {}` Sets the vault's symbol to `newSymbol`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-7) | Name | Type | Description | | --- | --- | --- | | `newSymbol` | string | The new symbol of the vault | ### setCurator[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#setcurator) Copy `function setCurator(address newCurator) external onlyOwner {};` Sets `curator` to `newCurator`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-8) | Name | Type | Description | | --- | --- | --- | | `newCurator` | address | The address of the new curator. | ### setIsAllocator[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#setisallocator) Copy `function setIsAllocator(address newAllocator, bool newIsAllocator) external onlyOwner {};` Sets `newAllocator` as an allocator or not (`newIsAllocator`). #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-9) | Name | Type | Description | | --- | --- | --- | | `newAllocator` | address | The address of the new allocator. | | `newIsAllocator` | bool | A boolean (true or false) indicating if the address is an allocator or not. | ### setSkimRecipient[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#setskimrecipient) Copy `function setSkimRecipient(address newSkimRecipient) external onlyOwner {};` Sets `skimRecipient` to `newSkimRecipient`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-10) | Name | Type | Description | | --- | --- | --- | | `newSkimRecipient` | address | The address of the new recipient parameters. | ### submitTimelock[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#submittimelock) Copy `function submitTimelock(uint256 newTimelock) external onlyOwner {};` Submits a `newTimelock`. * Warning: Reverts if a timelock is already pending. Revoke the pending timelock to overwrite it. * In case the new timelock is higher than the current one, the timelock is set immediately. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-11) | Name | Type | Description | | --- | --- | --- | | `newTimelock` | uint256 | The value of the new timelock (in seconds). | ### setFee[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#setfee) Copy `function setFee(uint256 newFee) external onlyOwner {};` Sets the `fee` to `newFee`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-12) | Name | Type | Description | | --- | --- | --- | | `newFee` | uint256 | The value of the new fee scaled in wad. | ### setFeeRecipient[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#setfeerecipient) Copy `function setFeeRecipient(address newFeeRecipient) external onlyOwner {};` Sets `feeRecipient` to `newFeeRecipient`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-13) | Name | Type | Description | | --- | --- | --- | | `newFeeRecipient` | address | The address of the new fee recipient. | ### submitGuardian[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#submitguardian) Copy `function submitGuardian(address newGuardian) external onlyOwner {};` Submits a `newGuardian`. * Warning: a malicious guardian could disrupt the vault's operation, and would have the power to revoke any pending guardian. * In case there is no guardian, the gardian is set immediately. * Warning: Submitting a gardian will overwrite the current pending gardian. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-14) | Name | Type | Description | | --- | --- | --- | | `newGuardian` | address | The address of the new guardian. | onlyCuratorRole Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#onlycuratorrole-functions) -------------------------------------------------------------------------------------------------------------------------------- Note that owner and curator has the `onlyCuratorRole`. ### submitCap[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#submitcap) Copy `function submitCap(MarketParams memory marketParams, uint256 newSupplyCap) external onlyCuratorRole {};` Submits a `newSupplyCap` for the market defined by `marketParams`. * Warning: Reverts if a cap is already pending. Revoke the pending cap to overwrite it. * Warning: Reverts if a market removal is pending. * In case the new cap is lower than the current one, the cap is set immediately. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-15) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho#marketparams-struct) | The market parameters. | | `newSupplyCap` | uint256 | The new supply cap in underlying units. | ### submitMarketRemoval[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#submitmarketremoval) Copy `function submitMarketRemoval(Id id) external onlyCuratorRole {};` Submits a forced market removal from the vault, eventually losing all funds supplied to the market. * Funds can be recovered by enabling this market again and withdrawing from it (using `reallocate`), but funds will be distributed pro-rata to the shares at the time of withdrawal, not at the time of removal. * This forced removal is expected to be used as an emergency process in case a market constantly reverts. To softly remove a sane market, the curator role is expected to bundle a reallocation that empties the market first (using `reallocate`), followed by the removal of the market (using `updateWithdrawQueue`). * Warning: Removing a market with non-zero supply will instantly impact the vault's price per share. * Warning: Reverts for non-zero cap or if there is a pending cap. Successfully submitting a zero cap will prevent such reverts. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-16) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho#marketparams-struct) | The market parameters. | onlyAllocatorRole Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#onlyallocatorrole-functions) ------------------------------------------------------------------------------------------------------------------------------------ Note that owner, curator and an address that has been set as an allocator has the `onlyAllocatorRole`. ### setSupplyQueue[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#setsupplyqueue) Copy `function setSupplyQueue(Id[] calldata newSupplyQueue) external onlyAllocatorRole {};` Sets `supplyQueue` to `newSupplyQueue`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-17) | Name | Type | Description | | --- | --- | --- | | `newSupplyQueue` | [Id](https://docs.morpho.org/get-started/resources/contracts/morpho#market-id)
\[ \] | newSupplyQueue is an array of enabled markets, and can contain duplicate markets, but it would only increase the cost of depositing to the vault. | ### updateWithdrawQueue[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#updatewithdrawqueue) Copy `function updateWithdrawQueue(uint256[] calldata indexes) external onlyAllocatorRole {};` Updates the withdraw queue. Some markets can be removed, but no market can be added. * Removing a market requires the vault to have 0 supply on it, or to have previously submitted a removal for this market (with the function `submitMarketRemoval`). * Warning: Anyone can supply on behalf of the vault so the call to `updateWithdrawQueue` that expects a market to be empty can be griefed by a front-run. To circumvent this, the allocator can simply bundle a reallocation that withdraws max from this market with a call to `updateWithdrawQueue`. * Warning: Removing a market with supply will decrease the fee accrued until one of the functions updating `lastTotalAssets` is triggered (deposit/mint/withdraw/redeem/setFee/setFeeRecipient). * Warning: `updateWithdrawQueue` is not idempotent. Submitting twice the same tx will change the queue twice. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-18) | Name | Type | Description | | --- | --- | --- | | `indexes` | uint256 \[ \] | The indexes of each market in the previous withdraw queue, in the new withdraw queue's order. | ### reallocate[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#reallocate) Copy `function reallocate(MarketAllocation[] calldata allocations) external onlyAllocatorRole {};` Reallocates the vault's liquidity so as to reach a given allocation of assets on each given market. * The allocator can withdraw from any market, even if it's not in the withdraw queue, as long as the loan token of the market is the same as the vault's asset. * The behavior of the reallocation can be altered by state changes, including: * Deposits on the vault that supplies to markets that are expected to be supplied to during reallocation. * Withdrawals from the vault that withdraws from markets that are expected to be withdrawn from during reallocation. * Donations to the vault on markets that are expected to be supplied to during reallocation. * Withdrawals from markets that are expected to be withdrawn from during reallocation. * Sender is expected to pass `assets = type(uint256).max` with the last MarketAllocation of `allocations` to supply all the remaining withdrawn liquidity, which would ensure that `totalWithdrawn` = `totalSupplied`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-19) | Name | Type | Description | | --- | --- | --- | | `allocations` | [MarketAllocation](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults#market) | The respective allocations in each market chosen. | onlyGuardianRole Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#onlyguardianrole-functions) ---------------------------------------------------------------------------------------------------------------------------------- Note that owner and guardian has the `onlyAllocatorRole`. ### revokePendingTimelock[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#revokependingtimelock) Copy `function revokePendingTimelock() external onlyGuardianRole {};` Revokes the pending timelock. * Does not revert if there is no pending timelock. ### revokePendingGuardian[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#revokependingguardian) Copy `function revokePendingGuardian() external onlyGuardianRole {};` Revokes the pending guardian. onlyCuratorOrGuardianRole Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#onlycuratororguardianrole-functions) ---------------------------------------------------------------------------------------------------------------------------------------------------- Note that owner, curator and guardian has the `onlyAllocatorRole`. ### revokePendingCap[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#revokependingcap) Copy `function revokePendingCap(Id id) external onlyCuratorOrGuardianRole {};` Revokes the pending cap of the market defined by `id`. * Does not revert if there is no pending cap. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-20) | Name | Type | Description | | --- | --- | --- | | `id` | [Id](https://docs.morpho.org/get-started/resources/contracts/morpho#market-id) | The id of the market to revoke the pending cap. | ### revokePendingMarketRemoval[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#revokependingmarketremoval) Copy `function revokePendingMarketRemoval(Id id) external onlyCuratorOrGuardianRole {};` Revokes the pending removal of the market defined by `id`. * Does not revert if there is no pending market removal. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/#parameters-21) | Name | Type | Description | | --- | --- | --- | | `id` | [Id](https://docs.morpho.org/get-started/resources/contracts/morpho#market-id) | The id of the market to revoke the pending removal. | Below is a list of the different **Errors** that can be thrown when executing transactions on Morpho Vaults. **E.g**: One can try to execute an action on Morpho Vaults' contracts, and get: Copy `reverted with an unrecognized custom error (return data: 0x46fedb57)` According to the following tables, this is an error that emitted the **AboveMaxTimelock()** function. | Custom Error | Error Signature (returned data) | | --- | --- | | `AboveMaxTimelock()` | 0x46fedb57 | | `AlreadyPending()` | 0x49b204ce | | `AlreadySet()` | 0xa741a045 | | `AllCapsReached()` | 0xded0652d | | `BelowMinTimelock()` | 0x342b27be | | `DuplicateMarket(Id id)` | 0x074e4d4b | | `InconsistentAsset(Id id)` | 0xf17887ec | | `InconsistentReallocation()` | 0x9e36b890 | | `InvalidMarketRemovalNonZeroCap(Id id)` | 0xd2575d1a | | `InvalidMarketRemovalNonZeroSupply(Id id)` | 0x6316104f | | `InvalidMarketRemovalTimelockNotElapsed(Id id)` | 0x813435c5 | | `MarketNotCreated()` | 0x96e13529 | | `MarketNotEnabled(Id id)` | 0x11b0e0ab | | `MaxFeeExceeded()` | 0xf4df6ae5 | | `MaxQueueLengthExceeded()` | 0x80f2f7ae | | `NonZeroCap()` | 0xc48e3172 | | `NoPendingValue()` | 0xe5f408a5 | | `NotAllocatorRole()` | 0xf7137c0f | | `NotCuratorNorGuardianRole()` | 0xd080fa31 | | `NotCuratorRole()` | 0xca899cec | | `NotEnoughLiquidity()` | 0x4323a555 | | `NotGuardianRole()` | 0xf9f2fc9a | | `PendingCap(Id id)` | 0x42288ef1 | | `PendingRemoval()` | 0x4bec0146 | | `SupplyCapExceeded(Id id)` | 0xd018394f | | `TimelockNotElapsed()` | 0x6677a596 | | `UnauthorizedMarket(Id id)` | 0x9cd14834 | | `ZeroAddress()` | 0x867915ab | | `ZeroFeeRecipient()` | 0xcff9f194 | --- # Morpho – Morpho Docs [Skip to content](https://docs.morpho.org/get-started/resources/contracts/morpho/#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Get Started Chevron Down Menu Morpho On this page Chevron Right [← Back to contracts](https://docs.morpho.org/get-started/resources/contracts) Code[](https://docs.morpho.org/get-started/resources/contracts/morpho/#code) ------------------------------------------------------------------------------- [Morpho repository](https://github.com/morpho-org/morpho-blue/tree/731e3f7ed97cf15f8fe00b86e4be5365eb3802ac) Market Parameters[](https://docs.morpho.org/get-started/resources/contracts/morpho/#market-parameters) --------------------------------------------------------------------------------------------------------- ### Market id[](https://docs.morpho.org/get-started/resources/contracts/morpho/#market-id) The market id is a `bytes32` keccak256 hash of the [5 parameters of a market](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) . It is used to identify a market in Morpho. Copy `type Id is bytes32;` To get the id from the parameters, a temporary solution is to execute [this gist](https://gist.github.com/tomrpl/3cfd34e04a01f9cbae2b16887f8026cf) , or retrieve the id at market creation. ### Market struct[](https://docs.morpho.org/get-started/resources/contracts/morpho/#market-struct) The market struct is defined as follows: Copy `struct Market { uint128 totalSupplyAssets; uint128 totalSupplyShares; uint128 totalBorrowAssets; uint128 totalBorrowShares; uint128 lastUpdate; uint128 fee; }` It contains the state of a market. `totalBorrowAssets` & `totalSupplyAssets` accrues the interest of the market only until last interest accrual, while `totalBorrowShares` & `totalSupplyShares` are representing the total shares distributed over lenders / borrowers. ### MarketParams struct[](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) The majority of the entrypoints accept a `MarketParams` struct as parameter. This struct is defined as follows: Copy `struct MarketParams { address loanToken; address collateralToken; address oracle; address irm; uint256 lltv; }` As an integrator, you need to recover these 5 parameters to interact with Morpho. You can also use the [idToMarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#idtomarketparams) view function to recover the parameters of a given market from the bytes32 id. Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho/#functions) ----------------------------------------------------------------------------------------- ### setOwner[](https://docs.morpho.org/get-started/resources/contracts/morpho/#setowner) Copy `function setOwner(address newOwner) external;` Sets `newOwner` as `owner` of the contract. * Warning: No two-step transfer ownership. * Warning: The owner can be set to the zero address. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters) | Name | Type | Description | | --- | --- | --- | | `newOwner` | address | The new owner address. | ### enableIrm[](https://docs.morpho.org/get-started/resources/contracts/morpho/#enableirm) Copy `function enableIrm(address irm) external;` Enables `irm` as a possible IRM for market creation. * Warning: It is not possible to disable an IRM. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-1) | Name | Type | Description | | --- | --- | --- | | `irm` | address | The irm address to enable. | ### enableLltv[](https://docs.morpho.org/get-started/resources/contracts/morpho/#enablelltv) Copy `function enableLltv(uint256 lltv) external;` Enables `lltv` as a possible LLTV for market creation. * Warning: It is not possible to disable a LLTV. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-2) | Name | Type | Description | | --- | --- | --- | | `lltv` | uint256 | The lltv value to enable (18 decimals). | ### setFee[](https://docs.morpho.org/get-started/resources/contracts/morpho/#setfee) Copy `function setFee(MarketParams memory marketParams, uint256 newFee) external;` Sets the `newFee` for the given market `marketParams`. * Warning: The recipient can be the zero address. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-3) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market parameters. | | `newFee` | uint256 | The new fee value. | ### setFeeRecipient[](https://docs.morpho.org/get-started/resources/contracts/morpho/#setfeerecipient) Copy `function setFeeRecipient(address newFeeRecipient) external;` Sets `newFeeRecipient` as `feeRecipient` of the fee. * Warning: If the fee recipient is set to the zero address, fees will accrue there and will be lost. * Modifying the fee recipient will allow the new recipient to claim any pending fees not yet accrued. To ensure that the current recipient receives all due fees, accrue interest manually prior to making any changes. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-4) | Name | Type | Description | | --- | --- | --- | | `newFeeRecipient` | address | The address of the new fee recipient. | ### createMarket[](https://docs.morpho.org/get-started/resources/contracts/morpho/#createmarket) Copy `function createMarket(MarketParams memory marketParams) external;` Creates the market defined by `marketParams`. Here is the list of assumptions on the market's dependencies (tokens, IRM and oracle) that guarantees Morpho behaves as expected: * The token should be ERC20 compliant, except that it can omit return values on `transfer` and `transferFrom`. * The token balance of Morpho should only decrease on `transfer` and `transferFrom`. In particular, tokens with burn functions are not supported. * The token should not re-enter Morpho on `transfer` nor `transferFrom`. * The token balance of the sender (resp. receiver) should decrease (resp. increase) by exactly the given amount on `transfer` and `transferFrom`. In particular, tokens with fees on transfer are not supported. * The IRM should not re-enter Morpho. * The oracle should return a price with the correct scaling. Here is a list of properties on the market's dependencies that could break Morpho's liveness properties: * The token can revert on `transfer` and `transferFrom` for a reason other than an approval or balance issue. * A very high amount of assets (~1e35) supplied or borrowed can make the computation of `toSharesUp` and `toSharesDown` overflow. * The IRM can revert on `borrowRate`. * A very high borrow rate returned by the IRM can make the computation of `interest` in `_accrueInterest` overflow. * The oracle can revert on `price`. Note that this can be used to prevent `borrow`, `withdrawCollateral` and `liquidate` from being used under certain market conditions. * A very high price returned by the oracle can make the computation of `maxBorrow` in `_isHealthy` overflow, or the computation of `assetsRepaid` in `liquidate` overflow. * The borrow share price of a market with less than 1e4 assets borrowed can be decreased by manipulations, to the point where `totalBorrowShares` is very large and borrowing overflows. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-5) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market parameters | ### supply[](https://docs.morpho.org/get-started/resources/contracts/morpho/#supply) Copy `function supply( MarketParams memory marketParams, uint256 assets, uint256 shares, address onBehalf, bytes memory data ) external returns (uint256 assetsSupplied, uint256 sharesSupplied);` Supplies `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's `onMorphoSupply` function with the given `data`. * Either `assets` or `shares` should be zero. Most usecases should rely on `assets` as an input so the caller is guaranteed to have `assets` tokens pulled from their balance, but the possibility to mint a specific amount of shares is given for full compatibility and precision. * Supplying a large amount can revert for overflow. * Supplying an amount of shares may lead to supply more or fewer assets than expected due to slippage. Consider using the `assets` parameter to avoid this. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-6) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to supply assets to. | | `assets` | uint256 | The amount of assets to supply. | | `shares` | uint256 | The amount of shares to mint. | | `onBehalf` | address | The address that will own the increased supply position. | | `data` | bytes | Arbitrary data to pass to the `onMorphoSupply` callback. Pass empty data if not needed. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values) | Name | Type | Description | | --- | --- | --- | | `assetsSupplied` | uint256 | The amount of assets supplied. | | `sharesSupplied` | uint256 | The amount of shares minted. | ### withdraw[](https://docs.morpho.org/get-started/resources/contracts/morpho/#withdraw) Copy `function withdraw( MarketParams memory marketParams, uint256 assets, uint256 shares, address onBehalf, address receiver ) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);` Withdraws `assets` or `shares` on behalf of `onBehalf` to `receiver`. * Either `assets` or `shares` should be zero. To withdraw max, pass the `shares`'s balance of `onBehalf`. * `msg.sender` must be authorized to manage `onBehalf`'s positions. * Withdrawing an amount corresponding to more shares than supplied will revert for underflow. * It is advised to use the `shares` input when withdrawing the full position to avoid reverts due to conversion roundings between `shares` and `assets`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-7) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to withdraw assets from. | | `assets` | uint256 | The amount of assets to withdraw. | | `shares` | uint256 | The amount of shares to burn. | | `onBehalf` | address | The address of the owner of the supply position. | | `receiver` | address | The address that will receive the withdrawn assets. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-1) | Name | Type | Description | | --- | --- | --- | | `assetsWithdrawn` | uint256 | The amount of assets withdrawn. | | `sharesWithdrawn` | uint256 | The amount of shares burned. | ### borrow[](https://docs.morpho.org/get-started/resources/contracts/morpho/#borrow) Copy `function borrow( MarketParams memory marketParams, uint256 assets, uint256 shares, address onBehalf, address receiver ) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed);` Borrows `assets` or `shares` on behalf of `onBehalf` to `receiver`. * Either `assets` or `shares` should be zero. Most usecases should rely on `assets` as an input so the caller is guaranteed to borrow `assets` of tokens, but the possibility to mint a specific amount of shares is given for full compatibility and precision. * `msg.sender` must be authorized to manage `onBehalf`'s positions. * Borrowing a large amount can revert for overflow. * Borrowing an amount of shares may lead to borrow fewer assets than expected due to slippage. Consider using the `assets` parameter to avoid this. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-8) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to borrow assets from. | | `assets` | uint256 | The amount of assets to borrow. | | `shares` | uint256 | The amount of shares to mint. | | `onBehalf` | address | The address that will own the increased borrow position. | | `receiver` | address | The address that will receive the borrowed assets. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-2) | Name | Type | Description | | --- | --- | --- | | `assetsBorrowed` | uint256 | The amount of assets borrowed. | | `sharesBorrowed` | uint256 | The amount of shares minted. | ### repay[](https://docs.morpho.org/get-started/resources/contracts/morpho/#repay) Copy `function repay( MarketParams memory marketParams, uint256 assets, uint256 shares, address onBehalf, bytes memory data ) external returns (uint256 assetsRepaid, uint256 sharesRepaid);` Repays `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's `onMorphoRepay` function with the given `data`. * Either `assets` or `shares` should be zero. To repay max, pass the `shares`'s balance of `onBehalf`. * Repaying an amount corresponding to more shares than borrowed will revert for underflow. * It is advised to use the `shares` input when repaying the full position to avoid reverts due to conversion roundings between shares and assets. * An attacker can front-run a repay with a small repay making the transaction revert for underflow. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-9) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to repay assets from. | | `assets` | uint256 | The amount of assets to repay. | | `shares` | uint256 | The amount of shares to burn. | | `onBehalf` | address | The address of the owner of the debt position. | | `data` | bytes | Arbitrary data (example `0x`) to pass to the `onMorphoRepay` callback. Pass empty data if not needed. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-3) | Name | Type | Description | | --- | --- | --- | | `assetsRepaid` | uint256 | The amount of assets repaid. | | `sharesRepaid` | uint256 | The amount of shares burned. | ### supplyCollateral[](https://docs.morpho.org/get-started/resources/contracts/morpho/#supplycollateral) Copy `function supplyCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, bytes memory data) external;` Supplies `assets` of collateral on behalf of `onBehalf`, optionally calling back the caller's `onMorphoSupplyCollateral` function with the given `data`. * Interest are not accrued since it's not required and it saves gas. * Supplying a large amount can revert for overflow. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-10) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to supply collateral to. | | `assets` | uint256 | The amount of assets to supply. | | `onBehalf` | address | The address that will own the increased collateral position. | | `data` | bytes | Arbitrary data to pass to the `onMorphoSupplyCollateral` callback. Pass empty data if not needed. | ### withdrawCollateral[](https://docs.morpho.org/get-started/resources/contracts/morpho/#withdrawcollateral) Copy `function withdrawCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, address receiver) external;` Withdraws `assets` of collateral on behalf of `onBehalf` to `receiver`. * `msg.sender` must be authorized to manage `onBehalf`'s positions. * Withdrawing an amount corresponding to more collateral than supplied will revert for underflow. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-11) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to withdraw collateral from. | | `assets` | uint256 | The amount of assets to withdraw. | | `onBehalf` | address | The address that owns the collateral position. | | `receiver` | address | The address that will receive the collateral assets. | ### liquidate[](https://docs.morpho.org/get-started/resources/contracts/morpho/#liquidate) Copy `function liquidate( MarketParams memory marketParams, address borrower, uint256 seizedAssets, uint256 repaidShares, bytes memory data ) external returns (uint256, uint256);` Liquidates the given `repaidShares` of debt asset or seize the given `seizedAssets` of collateral on the given market `marketParams` of the given `borrower`'s position, optionally calling back the caller's `onMorphoLiquidate` function with the given `data`. * Either `seizedAssets` or `repaidShares` should be zero. * Seizing more than the collateral balance will underflow and revert without any error message. * Repaying more than the borrow balance will underflow and revert without any error message. * An attacker can front-run a liquidation with a small repay making the transaction revert for underflow. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-12) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market of the position. | | `borrower` | address | The owner of the position. | | `seizedAssets` | uint256 | The amount of collateral to seize. | | `repaidShares` | uint256 | The amount of shares to repay. | | `data` | bytes | Arbitrary data to pass to the `onMorphoLiquidate` callback. Pass empty data if not needed. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-4) | Name | Type | Description | | --- | --- | --- | | `assetsSeized` | uint256 | The amount of assets seized. | | `assetsRepaid` | uint256 | The amount of assets repaid. | ### flashLoan[](https://docs.morpho.org/get-started/resources/contracts/morpho/#flashloan) Copy `function flashLoan(address token, uint256 assets, bytes calldata data) external;` Executes a flash loan. * Flash loans have access to the whole balance of the contract (the liquidity and deposited collateral of all markets combined, plus donations). * Warning: Not ERC-3156 compliant but compatibility is easily reached: a. `flashFee` is zero. b. `maxFlashLoan` is the token's balance of this contract. c. The receiver of `assets` is the caller. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-13) | Name | Type | Description | | --- | --- | --- | | `token` | address | The token to flash loan. | | `assets` | uint256 | The amount of assets to flash loan. | | `data` | bytes | Arbitrary data to pass to the `onMorphoFlashLoan` callback. | ### setAuthorization[](https://docs.morpho.org/get-started/resources/contracts/morpho/#setauthorization) Copy `function setAuthorization(address authorized, bool newIsAuthorized) external;` Sets the authorization for `authorized` to manage `msg.sender`'s positions. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-14) | Name | Type | Description | | --- | --- | --- | | `authorized` | address | The authorized address. | | `newIsAuthorized` | bool | The new authorization status. | ### setAuthorizationWithSig[](https://docs.morpho.org/get-started/resources/contracts/morpho/#setauthorizationwithsig) Copy `struct Authorization { address authorizer; address authorized; bool isAuthorized; uint256 nonce; uint256 deadline; } struct Signature { uint8 v; bytes32 r; bytes32 s; } function setAuthorizationWithSig(Authorization calldata authorization, Signature calldata signature) external;` Sets the authorization for `authorization.authorized` to manage `authorization.authorizer`'s positions. * Warning: Reverts if the signature has already been submitted. * The signature is malleable, but it has no impact on the security here. * The nonce is passed as argument to be able to revert with a different error message. #### Authorization struct[](https://docs.morpho.org/get-started/resources/contracts/morpho/#authorization-struct) | Name | Type | Description | | --- | --- | --- | | `authorizer` | address | The address authorizing the authorization. | | `authorized` | address | The address to authorize. | | `isAuthorized` | bool | The new authorization status. | | `nonce` | uint256 | The nonce of the authorizer. | | `deadline` | uint256 | The deadline after which the signature is invalid. | #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-15) | Name | Type | Description | | --- | --- | --- | | `authorization` | [Authorization](https://docs.morpho.org/get-started/resources/contracts/morpho/#authorization-struct) | The authorization to set. | | `signature` | Signature | The signature to validate. | ### accrueInterest[](https://docs.morpho.org/get-started/resources/contracts/morpho/#accrueinterest) Copy `function accrueInterest(MarketParams memory marketParams) external;` Accrues interest for the given market `marketParams`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-16) | Name | Type | Description | | --- | --- | --- | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market parameters. | Views Functions[](https://docs.morpho.org/get-started/resources/contracts/morpho/#views-functions) ----------------------------------------------------------------------------------------------------- ### DOMAIN\_SEPARATOR[](https://docs.morpho.org/get-started/resources/contracts/morpho/#domain_separator) Copy `function DOMAIN_SEPARATOR() external view returns (bytes32);` The EIP-712 domain separator. * Warning: Every EIP-712 signed message based on this domain separator can be reused on another chain sharing the same chain id because the domain separator would be the same. #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-5) | Type | Description | | --- | --- | | bytes32 | The EIP-712 domain separator. | ### owner[](https://docs.morpho.org/get-started/resources/contracts/morpho/#owner) Copy `function owner() external view returns (address);` The owner of the contract. * It has the power to change the owner. * It has the power to set fees on markets and set the fee recipient. * It has the power to enable but not disable IRMs and LLTVs. #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-6) | Type | Description | | --- | --- | | address | The owner of the contract. | ### feeRecipient[](https://docs.morpho.org/get-started/resources/contracts/morpho/#feerecipient) Copy `function feeRecipient() external view returns (address);` The fee recipient of all markets. * The recipient receives the fees of a given market through a supply position on that market. #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-7) | Type | Description | | --- | --- | | address | The fee recipient address. | ### isIrmEnabled[](https://docs.morpho.org/get-started/resources/contracts/morpho/#isirmenabled) Copy `function isIrmEnabled(address irm) external view returns (bool);` Whether the `irm` is enabled. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-17) | Name | Type | Description | | --- | --- | --- | | `irm` | address | The irm address. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-8) | Type | Description | | --- | --- | | bool | Boolean equals to `true` if irm is enabled, `false` otherwise. | ### isLltvEnabled[](https://docs.morpho.org/get-started/resources/contracts/morpho/#islltvenabled) Copy `function isLltvEnabled(uint256 lltv) external view returns (bool);` Whether the `lltv` is enabled. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-18) | Name | Type | Description | | --- | --- | --- | | `lltv` | address | The lltv address. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-9) | Type | Description | | --- | --- | | bool | Boolean equals to `true` if lltv is enabled, `false` otherwise. | ### isAuthorized[](https://docs.morpho.org/get-started/resources/contracts/morpho/#isauthorized) Copy `function isAuthorized(address authorizer, address authorized) external view returns (bool);` Whether `authorized` is authorized to modify `authorizer`'s position on all markets. * Anyone is authorized to modify their own positions, regardless of this variable. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-19) | Name | Type | Description | | --- | --- | --- | | `authorizer` | address | The authorizer address. | | `authorized` | address | The authorized address. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-10) | Type | Description | | --- | --- | | bool | Boolean equals to `true` if `authorized` address is authorized to modify `authorizer`'s position, `false` otherwise. | ### nonce[](https://docs.morpho.org/get-started/resources/contracts/morpho/#nonce) Copy `function nonce(address authorizer) external view returns (uint256);` The `authorizer`'s current nonce. Used to prevent replay attacks with EIP-712 signatures. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-20) | Name | Type | Description | | --- | --- | --- | | `authorizer` | address | The authorizer address. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-11) | Type | Description | | --- | --- | | uint256 | The current nonce value. | ### extSloads[](https://docs.morpho.org/get-started/resources/contracts/morpho/#extsloads) Copy `function extSloads(bytes32[] memory slots) external view returns (bytes32[] memory);` Returns the data stored on the different `slots`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-21) | Name | Type | Description | | --- | --- | --- | | `slots` | bytes32\[\] | The array of slots to retrieve the data stored into. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-12) | Type | Description | | --- | --- | | bytes32\[\] | The data stored. | ### idToMarketParams[](https://docs.morpho.org/get-started/resources/contracts/morpho/#idtomarketparams) Copy `function idToMarketParams(Id id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv);` The market params corresponding to `id`. * This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-22) | Name | Type | Description | | --- | --- | --- | | `id` | Id | The market id | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-13) | Name | Type | Description | | --- | --- | --- | | `loanToken` | address | The loan token of the market. | | `collateralToken` | address | The collateral token of the market. | | `oracle` | address | The oracle of the market. | | `irm` | address | The IRM of the market. | | `lltv` | uint256 | The LLTV of the market. | ### market[](https://docs.morpho.org/get-started/resources/contracts/morpho/#market) Copy `function market(Id id) external view returns ( uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee );` The market state corresponding to `id`. * Interest are not accrued, and assets values are not updated. Their values are the one at the last update. * One can use the [MorphoBalancesLib](https://docs.morpho.org/get-started/resources/contracts/morpho/#morphobalanceslib) to accrue interests #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-23) | Name | Type | Description | | --- | --- | --- | | `id` | Id | The market id | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-14) | Name | Type | Description | | --- | --- | --- | | `totalSupplyAssets` | uint128 | The total supply assets of the market. | | `totalSupplyShares` | uint128 | The total supply shares of the market. | | `totalBorrowAssets` | uint128 | The total borrow assets of the market. | | `totalBorrowShares` | uint128 | The total borrow shares of the market. | | `lastUpdate` | uint128 | The last update timestamp of the market. | | `fee` | uint128 | The fee of the market. | ### position[](https://docs.morpho.org/get-started/resources/contracts/morpho/#position) Copy `function position(Id id, address user) external view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral);` The state of the position of `user` on the market corresponding to `id`. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-24) | Name | Type | Description | | --- | --- | --- | | `id` | Id | The market id. | | `user` | address | The user address. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-15) | Name | Type | Description | | --- | --- | --- | | `supplyShares` | uint256 | The total supply shares of the user on a given market. | | `borrowShares` | uint128 | The total borrow shares of the user on a given market. | | `collateral` | uint128 | The total collateral assets of the user on a given market. | MorphoBalancesLib[](https://docs.morpho.org/get-started/resources/contracts/morpho/#morphobalanceslib) --------------------------------------------------------------------------------------------------------- > The Github code is available [**here**](https://github.com/morpho-org/morpho-blue/blob/be2306afd655232d2cf16547c18be0077014bae0/src/libraries/periphery/MorphoBalancesLib.sol) ### expectedMarketBalances[](https://docs.morpho.org/get-started/resources/contracts/morpho/#expectedmarketbalances) Copy `function expectedMarketBalances(IMorpho morpho, MarketParams memory marketParams) internal view returns ( uint256 totalSupplyAssets, uint256 totalSupplyShares, uint256 totalBorrowAssets, uint256 totalBorrowShares );` Returns the expected market balances of a market after having accrued interests, defined in [Market](https://docs.morpho.org/get-started/resources/contracts/morpho/#market-struct) . #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-25) | Name | Type | Description | | --- | --- | --- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to get the expected balances from. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-16) | Name | Type | Description | | --- | --- | --- | | `totalSupplyAssets` | uint256 | The total supply assets of the market (with interests accrued). | | `totalSupplyShares` | uint256 | The total supply shares of the market. | | `totalBorrowAssets` | uint256 | The total borrow assets of the market (with interests accrued). | | `totalBorrowShares` | uint256 | The total borrow shares of the market. | ### expectedTotalSupplyAssets[](https://docs.morpho.org/get-started/resources/contracts/morpho/#expectedtotalsupplyassets) Copy `function expectedTotalSupplyAssets(IMorpho morpho, MarketParams memory marketParams) internal view returns (uint256 totalSupplyAssets);` Returns the expected total supply assets of a market after having accrued interests. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-26) | Name | Type | Description | | --- | --- | --- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to get the expected total supply from. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-17) | Name | Type | Description | | --- | --- | --- | | `totalSupplyAssets` | uint256 | The total supply assets of the market (with interests accrued). | ### expectedTotalBorrowAssets[](https://docs.morpho.org/get-started/resources/contracts/morpho/#expectedtotalborrowassets) Copy `function expectedTotalBorrowAssets(IMorpho morpho, MarketParams memory marketParams) internal view returns (uint256 totalBorrowAssets);` Returns the expected total borrow assets of a market after having accrued interests. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-27) | Name | Type | Description | | --- | --- | --- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to get the expected total borrow from. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-18) | Name | Type | Description | | --- | --- | --- | | `totalBorrowAssets` | uint256 | The total borrow assets of the market (with interests accrued). | ### expectedTotalSupplyShares[](https://docs.morpho.org/get-started/resources/contracts/morpho/#expectedtotalsupplyshares) Copy `function expectedTotalSupplyShares(IMorpho morpho, MarketParams memory marketParams) internal view returns (uint256 totalSupplyShares);` Returns the expected total supply shares of a market after having accrued interests. * It can grow only if fees > 0 #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-28) | Name | Type | Description | | --- | --- | --- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to get the expected total supply from. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-19) | Name | Type | Description | | --- | --- | --- | | `totalSupplyShares` | uint256 | The total supply shares of the market (with interests accrued). | ### expectedSupplyAssets[](https://docs.morpho.org/get-started/resources/contracts/morpho/#expectedsupplyassets) Copy `function expectedSupplyAssets(IMorpho morpho, MarketParams memory marketParams, address user) internal view returns (uint256)` Returns the expected supply assets of a user on a market after having accrued interests. * Warning: Wrong for `feeRecipient` because their supply shares increase is not taken into account. * Warning: Withdrawing using the expected supply assets can lead to a revert due to conversion roundings from assets to shares. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-29) | Name | Type | Description | | --- | --- | --- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to get the expected supply assets from. | | `user` | address | The user to get the expected supply assets from. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-20) | Name | Type | Description | | --- | --- | --- | | `supplyAssets` | uint256 | The supply assets of the user (with interests accrued). | ### expectedBorrowAssets[](https://docs.morpho.org/get-started/resources/contracts/morpho/#expectedborrowassets) Copy `function expectedBorrowAssets(IMorpho morpho, MarketParams memory marketParams, address user) internal view returns (uint256)` Returns the expected borrow assets of a user on a market after having accrued interests. * Warning: The expected balance is rounded up, so it may be greater than the market's expected total borrow assets. #### Parameters:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#parameters-30) | Name | Type | Description | | --- | --- | --- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](https://docs.morpho.org/get-started/resources/contracts/morpho/#marketparams-struct) | The market to get the expected borrow assets from. | | `user` | address | The user to get the expected borrow assets from. | #### Return Values:[](https://docs.morpho.org/get-started/resources/contracts/morpho/#return-values-21) | Name | Type | Description | | --- | --- | --- | | `borrowBalance` | uint256 | The borrow assets of the user (with interests accrued). | Errors Codes[](https://docs.morpho.org/get-started/resources/contracts/morpho/#errors-codes) ----------------------------------------------------------------------------------------------- The full list of custom errors are displayed directly in the ErrorsLib of the [Morpho contracts](https://github.com/morpho-org/morpho-blue/blob/main/src/libraries/ErrorsLib.sol) . For example, see the [Morpho contract deployed on Ethereum mainnet](https://etherscan.io/address/0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb#code#F10#L1) . Below is the list of the different **Errors** that can be thrown, along with their explanations: | Errors Message (returned data) | Error Natspec | | --- | --- | | "already set" | Thrown when the value is already set. | | "healthy position" | Thrown when the position to liquidate is healthy. | | "inconsistent input" | Thrown when not exactly one of the input amount is zero. | | "insufficient collateral" | Thrown when the collateral is insufficient to `borrow` or `withdrawCollateral`. | | "insufficient liquidity" | Thrown when the liquidity is insufficient to `withdraw` or `borrow`. | | "invalid nonce" | Thrown when the nonce is invalid. | | "invalid signature" | Thrown when the authorization signature is invalid. | | "irm not enabled" | Thrown when the IRM is not enabled at market creation. | | "lltv not enabled" | Thrown when the LLTV is not enabled at market creation. | | "market already created" | Thrown when the market is already created. | | "market not created" | Thrown when the market is not created. | | "max fee exceeded" | Thrown when the fee to set exceeds the maximum fee. | | "max lltv exceeded" | Thrown when the LLTV to enable exceeds the maximum LLTV. | | "max uint128 exceeded" | Thrown when the maximum uint128 is exceeded. | | "no code" | Thrown when a token to transfer doesn't have code. | | "not owner" | Thrown when the caller is not the owner. | | "signature expired" | Thrown when the authorization signature is expired. | | "transfer from reverted" | Thrown when a token transferFrom reverted. | | "transfer from returned false" | Thrown when a token transferFrom returned false. | | "transfer returned false" | Thrown when a token transfer returned false. | | "transfer reverted" | Thrown when a token transfer reverted. | | "unauthorized" | Thrown when the caller is not authorized to conduct an action. | | "zero address" | Thrown when a zero address is passed as input. | | "zero assets" | Thrown when zero assets is passed as input. | --- # Fetch Rewards Data – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Fetch Rewards Data On this page Chevron Right This tutorial shows you how to fetch reward information for Morpho Vaults and Markets from both **Merkl API** and **Morpho API**. Understanding how to query both systems is essential for displaying complete reward information to your users. What You'll Learn[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#what-youll-learn) ----------------------------------------------------------------------------------------------------------- * How to fetch vault and market reward rates from Morpho API * How to query user-specific rewards from Merkl API * How to get historical reward data from Morpho Rewards API (URD) * How to combine data from multiple sources for a complete picture Prerequisites[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#prerequisites) ---------------------------------------------------------------------------------------------------- * Basic understanding of [Reward Programs](https://docs.morpho.org/build/rewards/concepts/reward-campaigns) * Familiarity with REST and GraphQL APIs * A tool for making API requests (curl, fetch, axios, or GraphQL client) API Landscape Overview[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#api-landscape-overview) ---------------------------------------------------------------------------------------------------------------------- There are **three main APIs** for rewards data: | API | Use Case | Rewards Type | Data Provided | | --- | --- | --- | --- | | **Morpho API** | Vault/Market reward rates | Both Merkl & Old URD | APRs, reward token info, integrated with vault/market data | | **Merkl API** | User claimable rewards | Merkl only | User balances, claim data, real-time rewards | | **Rewards API** | Historical rewards | URD only | Legacy programs, distributions, claim data | **Recommended Strategy:** 1. Use **Morpho API** for displaying reward APRs on vaults/markets (easiest integration) 2. Use **Merkl API** for user-specific Merkl rewards 3. Use **Rewards API** for user-specific URD (legacy) rewards Fetching Vault Rewards[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#fetching-vault-rewards) ---------------------------------------------------------------------------------------------------------------------- ### Using Morpho API (Recommended)[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#using-morpho-api-recommended) Vault rewards come from **two sources** that must be queried and aggregated manually: 1. **Vault-level rewards**: Direct campaigns targeting the vault 2. **Market-level rewards**: Forwarded from markets where the vault allocates #### Query Complete Vault Rewards[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#query-complete-vault-rewards) Copy `query VaultRewards($address: String!, $chainId: Int!) { vaultByAddress(address: $address, chainId: $chainId) { address name symbol state { apy netApy # Convenience field: complete APY including rewards # Vault-level rewards (direct) rewards { supplyApr yearlySupplyTokens asset { address symbol priceUsd chain { id } } } # Market-level rewards (forwarded from allocations) allocation { supplyAssetsUsd # Required for weighted average market { uniqueKey loanAsset { symbol } collateralAsset { symbol } state { rewards { supplyApr asset { address symbol priceUsd chain { id } } } } } } } } }` **Variables:** Copy `{ "address": "0x9aB2d181E4b87ba57D5eD564D3eF652C4E710707", "chainId": 8453 }` #### Calculate Total Rewards APR[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#calculate-total-rewards-apr) Vault rewards require **manual aggregation** with weighted averaging: Copy ``const vault = response.data.vaultByAddress; // 1. Sum vault-level rewards const vaultRewardsApr = vault.state.rewards.reduce( (sum, r) => sum + parseFloat(r.supplyApr), 0 ); // 2. Calculate weighted average of market-level rewards const totalAllocatedUsd = vault.state.allocation.reduce( (sum, alloc) => sum + parseFloat(alloc.supplyAssetsUsd), 0 ); const marketRewardsApr = vault.state.allocation.reduce((sum, alloc) => { const marketRewards = alloc.market.state.rewards.reduce( (marketSum, r) => marketSum + parseFloat(r.supplyApr), 0 ); const weight = parseFloat(alloc.supplyAssetsUsd) / totalAllocatedUsd; return sum + (marketRewards * weight); }, 0); // 3. Total rewards APR const totalRewardsApr = vaultRewardsApr + marketRewardsApr; console.log(`Base APY: ${vault.state.apy}%`); console.log(`Vault Rewards APR: ${vaultRewardsApr}%`); console.log(`Market Rewards APR: ${marketRewardsApr}%`); console.log(`Total APY: ${parseFloat(vault.state.apy) + totalRewardsApr}%`);`` #### Alternative: Use Convenience Fields[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#alternative-use-convenience-fields) For simple total APY display without breakdown: Copy ``const vault = response.data.vaultByAddress; const netApy = parseFloat(vault.state.netApy); // Pre-calculated complete APY console.log(`Total APY: ${netApy}%`);`` **Important Notes:** * Vault rewards are in **two separate API locations**: `state.rewards` and `state.allocation[].market.state.rewards` * Manual weighted average calculation is required for market rewards * Use `supplyAssetsUsd` from allocations to calculate weights * Convenience field `netApy` includes all components but doesn't provide breakdown Fetching Market Rewards[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#fetching-market-rewards) ------------------------------------------------------------------------------------------------------------------------ Markets can have rewards for **supply** and **borrow**. ### Using Morpho API[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#using-morpho-api) Copy `query MarketRewards($uniqueKey: String!) { markets(where: { uniqueKey: $uniqueKey }) { items { uniqueKey loanAsset { symbol } collateralAsset { symbol } state { borrowApy supplyApy rewards { supplyApr borrowApr asset { address symbol priceUsd } } } } } }` **Key Fields:** * `supplyApr`: Reward APR for suppliers * `borrowApr`: Reward APR for borrowers (often negative, meaning borrowers earn rewards) Fetching User-Specific Rewards[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#fetching-user-specific-rewards) -------------------------------------------------------------------------------------------------------------------------------------- ### Merkl API (Current Programs)[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#merkl-api-current-programs) To get a user's claimable Merkl rewards: **Endpoint:** Copy `GET https://api.merkl.xyz/v4/userRewards?user={address}` **Example:** Copy `curl "https://api.merkl.xyz/v4/userRewards?user=0x1234...5678"` **Response Structure:** Copy `{ "1": { // Chain ID "0xVAULT_OR_MARKET_ADDRESS": { "claimable": { "0xREWARD_TOKEN_ADDRESS": { "accumulated": "1234567890", "unclaimed": "1234567890", "symbol": "MORPHO", "decimals": 18 } } } } }` **TypeScript Example:** Copy ``async function fetchMerklRewards(userAddress: string) { const response = await fetch( `https://api.merkl.xyz/v4/userRewards?user=${userAddress}` ); const data = await response.json(); // Parse rewards by chain const chainId = 1; // Ethereum mainnet const rewards = data[chainId] || {}; // Aggregate all claimable rewards const claimableByToken: Record = {}; for (const [campaignAddress, campaignData] of Object.entries(rewards)) { for (const [tokenAddress, tokenData] of Object.entries( campaignData.claimable || {} )) { const unclaimed = BigInt(tokenData.unclaimed || "0"); claimableByToken[tokenAddress] = (claimableByToken[tokenAddress] || 0n) + unclaimed; } } return claimableByToken; }`` ### Morpho Rewards API (Legacy URD Programs)[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#morpho-rewards-api-legacy-urd-programs) To get a user's URD rewards: **Endpoint:** Copy `GET https://rewards.morpho.org/v1/users/{address}/rewards` **Example:** Copy `curl "https://rewards.morpho.org/v1/users/0x0ec553110e53122d1226646670a8475D4C8E6F04/rewards"` **Response Structure:** Copy `[ { "user": "0x0ec553110e53122d1226646670a8475D4C8E6F04", "type": "uniform-reward", "asset": { "id": "0x58D97B57BB95320F9a05dC918Aef65434969c2B2-1", "address": "0x58D97B57BB95320F9a05dC918Aef65434969c2B2", "chain_id": 1 }, "program_id": "0x5068...", "amount": { "total": "115631364898103632676", "claimable_now": "22676259927164556632", "claimable_next": "1688912463745536463", "claimed": "91266192507193539581" } } ]` **Key Fields:** * `claimable_now`: Available to claim right now * `claimable_next`: Will become claimable in next epoch * `claimed`: Already claimed by user * `total`: Sum of all the above **TypeScript Example:** Copy ``async function fetchURDRewards(userAddress: string) { const response = await fetch( `https://rewards.morpho.org/v1/users/${userAddress}/rewards` ); const rewards = await response.json(); // Aggregate claimable by token const claimableByToken: Record = {}; for (const reward of rewards) { const tokenAddress = reward.asset.address; const claimable = BigInt(reward.amount.claimable_now); claimableByToken[tokenAddress] = (claimableByToken[tokenAddress] || 0n) + claimable; } return claimableByToken; }`` Combining Data from Multiple Sources[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#combining-data-from-multiple-sources) -------------------------------------------------------------------------------------------------------------------------------------------------- To show a complete rewards picture, you'll need to combine data from Merkl and URD: Copy `async function fetchAllUserRewards(userAddress: string) { // Fetch from both sources in parallel const [merklRewards, urdRewards] = await Promise.all([ fetchMerklRewards(userAddress), fetchURDRewards(userAddress), ]); // Combine by token address const allRewards: Record = {}; // Add Merkl rewards for (const [token, amount] of Object.entries(merklRewards)) { allRewards[token] = allRewards[token] || { merkl: 0n, urd: 0n, total: 0n }; allRewards[token].merkl = amount; allRewards[token].total += amount; } // Add URD rewards for (const [token, amount] of Object.entries(urdRewards)) { allRewards[token] = allRewards[token] || { merkl: 0n, urd: 0n, total: 0n }; allRewards[token].urd = amount; allRewards[token].total += amount; } return allRewards; }` Performance Considerations[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#performance-considerations) ------------------------------------------------------------------------------------------------------------------------------ ### Caching[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#caching) **Vault/Market Rewards (Morpho API):** * Cache for 5-15 minutes * Rewards rates change infrequently **User Merkl Rewards:** * Cache for 5-10 minutes * Updates every 8 hours, but users expect fresh data ### Parallel Fetching[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#parallel-fetching) Always fetch from multiple APIs in parallel: Copy `const [vaultData, merklRewards, urdRewards] = await Promise.all([ fetchVaultFromMorphoAPI(vaultAddress), fetchMerklRewards(userAddress), fetchURDRewards(userAddress), ]);` ### Error Handling[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#error-handling) Copy `async function fetchRewardsSafely(userAddress: string) { try { const merkl = await fetchMerklRewards(userAddress); } catch (error) { console.error("Merkl API error:", error); merkl = {}; // Fallback to empty } try { const urd = await fetchURDRewards(userAddress); } catch (error) { console.error("URD API error:", error); urd = {}; // Fallback to empty } return { merkl, urd }; }` API Rate Limits[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#api-rate-limits) -------------------------------------------------------------------------------------------------------- Be mindful of rate limits: | API | Rate Limit | Notes | | --- | --- | --- | | Morpho API | 2k / 5 min | Use responsibly | | Merkl API | Unknown, likely generous | Cache responses | | Rewards API | 850 / min | Avoid excessive polling | **Best Practice:** Cache aggressively and fetch only when needed. Next Steps[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#next-steps) ---------------------------------------------------------------------------------------------- * **Display rewards**: Follow the [Integrate Display tutorial](https://docs.morpho.org/build/rewards/tutorials/integrate-display) * **Enable claiming**: See the [Claim Rewards tutorial](https://docs.morpho.org/build/rewards/tutorials/claim-rewards) * **Full example**: Check out the [Complete Integration Guide](https://docs.morpho.org/build/rewards/guides/complete-integration) Resources[](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data#resources) -------------------------------------------------------------------------------------------- * **Morpho API Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql) * **Merkl Docs**: [docs.merkl.xyz/integrate-merkl/app](https://docs.merkl.xyz/integrate-merkl/app) * **Rewards API Docs**: [rewards.morpho.org/docs](https://rewards.morpho.org/docs) * **Example Code**: [morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe) --- # Claim Rewards – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Integrate Rewards Claim On this page Chevron Right This tutorial shows you how to implement reward claiming for both **Merkl** (current programs) and **Morpho URD** (legacy programs) in your application. Supporting both systems ensures users can access all their available rewards. Overview[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#overview) ------------------------------------------------------------------------------------- Claiming rewards involves: 1. Fetching claim data (proof + transaction data) from the appropriate API 2. Constructing or using pre-formatted transaction calldata 3. Submitting the claim transaction onchain 4. Handling the response and updating your UI The process is similar for both Merkl and URD, but they use different APIs and smart contracts. Prerequisites[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#prerequisites) ----------------------------------------------------------------------------------------------- * Understanding of [Distribution Systems](https://docs.morpho.org/build/rewards/concepts/distribution-system) * Familiarity with [Fetching Rewards Data](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data) * A web3 library (viem, ethers, web3.js) * User's wallet connected to your app Claiming via Merkl[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#claiming-via-merkl) --------------------------------------------------------------------------------------------------------- Merkl is the primary distribution system for current reward programs. ### Step 1: Fetch Claim Data[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#step-1-fetch-claim-data) **Endpoint:** Copy `GET https://api.merkl.xyz/v4/claim?user={address}&chainId={chainId}` **Example:** Copy ``async function fetchMerklClaimData( userAddress: string, chainId: number ): Promise { const response = await fetch( `https://api.merkl.xyz/v4/claim?user=${userAddress}&chainId=${chainId}` ); if (!response.ok) { throw new Error(`Merkl API error: ${response.status}`); } return response.json(); }`` **Response Structure:** Copy `{ "claim": { "user": "0x...", "tokens": ["0xTOKEN1", "0xTOKEN2"], "amounts": ["1000000000000000000", "2000000000000000000"], "proofs": [ ["0xproof1a", "0xproof1b"], ["0xproof2a", "0xproof2b"] ] } }` ### Step 2: Execute the Claim[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#step-2-execute-the-claim) Using **viem**: Copy `import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; const MERKL_DISTRIBUTOR = "0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae"; // Mainnet async function claimMerklRewards( userAddress: string, chainId: number ) { // 1. Fetch claim data const claimData = await fetchMerklClaimData(userAddress, chainId); // 2. Setup wallet client const walletClient = createWalletClient({ account: userAddress, chain: mainnet, transport: custom(window.ethereum), }); // 3. Send claim transaction const hash = await walletClient.writeContract({ address: MERKL_DISTRIBUTOR, abi: MERKL_ABI, functionName: "claim", args: [ claimData.claim.user, claimData.claim.tokens, claimData.claim.amounts, claimData.claim.proofs, ], }); // 4. Wait for confirmation const receipt = await walletClient.waitForTransactionReceipt({ hash }); return receipt; } // Merkl Distributor ABI (claim function) const MERKL_ABI = [ { inputs: [ { name: "user", type: "address" }, { name: "tokens", type: "address[]" }, { name: "amounts", type: "uint256[]" }, { name: "proofs", type: "bytes32[][]" }, ], name: "claim", outputs: [], stateMutability: "nonpayable", type: "function", }, ] as const;` ### Step 3: Handle the Result[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#step-3-handle-the-result) Copy `try { const receipt = await claimMerklRewards(userAddress, 1); if (receipt.status === "success") { console.log("✅ Merkl rewards claimed successfully!"); // Update your UI to reflect claimed rewards } else { console.error("❌ Claim transaction failed"); } } catch (error) { console.error("Error claiming Merkl rewards:", error); // Show error message to user }` For more details on Merkl claiming, see the [official Merkl documentation](https://docs.merkl.xyz/integrate-merkl/app#claiming-user-rewards) . Claiming via Morpho URD - Legacy distributions[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#claiming-via-morpho-urd---legacy-distributions) ----------------------------------------------------------------------------------------------------------------------------------------------------------------- The URD handles legacy reward programs. While new programs use Merkl, many users still have unclaimed URD rewards. ### Step 1: Fetch Distribution Data[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#step-1-fetch-distribution-data) **Endpoint:** Copy `GET https://rewards.morpho.org/v1/users/{address}/distributions` **Example:** Copy ``interface URDDistribution { user: string; distributor: string; // URD contract address chain_id: number; asset: { address: string; symbol: string; }; claimable: string; // Cumulative amount proof: string[]; tx_data: string; // Pre-formatted calldata } async function fetchURDDistributions( userAddress: string ): Promise { const response = await fetch( `https://rewards.morpho.org/v1/users/${userAddress}/distributions` ); if (!response.ok) { throw new Error(`Rewards API error: ${response.status}`); } return response.json(); }`` **Response Structure:** Copy `[ { "user": "0x...", "distributor": "0x330eefa8a787552DC5cAd3C3cA644844B1E61Ddb", "chain_id": 1, "asset": { "address": "0x58D97B57BB95320F9a05dC918Aef65434969c2B2", "symbol": "MORPHO" }, "claimable": "115631364898103632676", "proof": ["0x1a2b...", "0x3c4d..."], "tx_data": "0x4e71d92d..." } ]` ### Step 2: Check Already-Claimed Amount[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#step-2-check-already-claimed-amount) Before claiming, verify how much the user has already claimed to avoid unnecessary transactions: Copy ``import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; const URD_ABI = [ { inputs: [ { name: "account", type: "address" }, { name: "reward", type: "address" }, ], name: "claimed", outputs: [{ name: "", type: "uint256" }], stateMutability: "view", type: "function", }, ] as const; async function getClaimedAmount( distributorAddress: string, userAddress: string, rewardTokenAddress: string ): Promise { const publicClient = createPublicClient({ chain: mainnet, transport: http(), }); const claimed = await publicClient.readContract({ address: distributorAddress as `0x${string}`, abi: URD_ABI, functionName: "claimed", args: [userAddress as `0x${string}`, rewardTokenAddress as `0x${string}`], }); return claimed; }`` ### Step 3: Execute the Claim[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#step-3-execute-the-claim) Using Pre-formatted `tx_data` The API provides ready-to-use transaction calldata: Copy ``async function claimURDRewards(distribution: URDDistribution) { // 1. Check if there's anything to claim const alreadyClaimed = await getClaimedAmount( distribution.distributor, distribution.user, distribution.asset.address ); const claimable = BigInt(distribution.claimable); if (alreadyClaimed >= claimable) { console.log("Nothing to claim (already claimed)"); return null; } // 2. Setup wallet client const walletClient = createWalletClient({ account: distribution.user as `0x${string}`, chain: mainnet, transport: custom(window.ethereum), }); // 3. Send transaction with pre-formatted data const hash = await walletClient.sendTransaction({ to: distribution.distributor as `0x${string}`, data: distribution.tx_data as `0x${string}`, }); // 4. Wait for confirmation const receipt = await walletClient.waitForTransactionReceipt({ hash }); return receipt; }`` Resources[](https://docs.morpho.org/build/rewards/tutorials/claim-rewards#resources) --------------------------------------------------------------------------------------- * **Merkl Claim Docs**: [docs.merkl.xyz/integrate-merkl/app#claiming-user-rewards](https://docs.merkl.xyz/integrate-merkl/app#claiming-user-rewards) * **Rewards API**: [rewards.morpho.org/docs](https://rewards.morpho.org/docs) * **Example Code**: [morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe) --- # Integrate Rewards Display – Morpho Docs [Skip to content](https://docs.morpho.org/build/rewards/tutorials/integrate-display#vocs-content) Search... [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) [![Logo](https://docs.morpho.org/img/morpho-logo-light-horizontal.svg)![Logo](https://docs.morpho.org/img/logo-blue.png)](https://docs.morpho.org/) Build Products Chevron Down Menu Integrate Rewards Display On this page Chevron Right This tutorial shows you how to build user interfaces that display reward information from both Merkl and Morpho URD. A well-designed rewards display helps users understand their earnings and encourages engagement with your platform. What to Display[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#what-to-display) ------------------------------------------------------------------------------------------------------- A complete rewards integration should show: 1. **Vault/Market Level Rewards** - The APR users can earn 2. **User Claimable Rewards** - How much users have earned and can claim 3. **Combined APY/APR** - Total yield including base + rewards 4. **Reward Token Information** - What tokens are being distributed 5. **Claim Status** - What's claimable now vs. pending Displaying Vault Rewards[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#displaying-vault-rewards) ------------------------------------------------------------------------------------------------------------------------- ### Fetching and Calculating Total APY[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#fetching-and-calculating-total-apy) Copy ``import { GraphQLClient, gql } from "graphql-request"; const client = new GraphQLClient("https://api.morpho.org/graphql"); async function getVaultWithRewards(vaultAddress: string, chainId: number) { const query = gql` query VaultRewards($address: String!, $chainId: Int!) { vaults(where: { address: $address, chainId: $chainId }) { items { address name symbol asset { symbol } state { apy totalAssets rewards { yearlySupplyTokens supplyApr asset { address symbol priceUsd } } } } } } `; const response = await client.request(query, { address: vaultAddress, chainId, }); const vault = response.vaults.items[0]; return { vault: vault.name, symbol: vault.symbol, asset: vault.asset.symbol, baseApy: parseFloat(vault.state.apy), rewardsApr: vault.state.rewards.reduce( (sum, r) => sum + parseFloat(r.supplyApr), 0 ), totalApy: parseFloat(vault.state.apy) + vault.state.rewards.reduce((sum, r) => sum + parseFloat(r.supplyApr), 0), rewards: vault.state.rewards.map((r) => ({ token: r.asset.symbol, apr: parseFloat(r.supplyApr), tokenAddress: r.asset.address, })), }; }`` ### React Component Example[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#react-component-example) Copy `import React, { useEffect, useState } from "react"; interface VaultRewardsDisplayProps { vaultAddress: string; chainId: number; } function VaultRewardsDisplay({ vaultAddress, chainId }: VaultRewardsDisplayProps) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { getVaultWithRewards(vaultAddress, chainId) .then(setData) .finally(() => setLoading(false)); }, [vaultAddress, chainId]); if (loading) return
Loading...
; if (!data) return
No data
; return (

{data.vault}

Deposit {data.asset}

{/* Total APY */}

Total APY: {data.totalApy.toFixed(2)}%

Base APY: {data.baseApy.toFixed(2)}%
Rewards APR: +{data.rewardsApr.toFixed(2)}%
{/* Rewards Breakdown */} {data.rewards.length > 0 && (

Reward Programs:

{data.rewards.map((reward) => (
{reward.token} {reward.apr.toFixed(2)}% APR
))}
)}
); }` ### Visual Design Tips[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#visual-design-tips) **Highlight Total Yield:** Copy `
Total APY {totalApy.toFixed(2)}%
` **Show Breakdown on Hover/Click:** Copy `
Base APY: {baseApy}%
MORPHO Rewards: +{morphoApr}%
Partner Rewards: +{partnerApr}%
}> {totalApy}%
` **Use Badges for Rewards:** Copy `{rewards.length > 0 && ( +{rewardsApr.toFixed(1)}% Rewards )}` Displaying User Claimable Rewards[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#displaying-user-claimable-rewards) ------------------------------------------------------------------------------------------------------------------------------------------- ### Fetching User Rewards from Both Systems[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#fetching-user-rewards-from-both-systems) Copy ``async function getUserAllClaimableRewards(userAddress: string, chainId: number) { const [merklRewards, urdRewards] = await Promise.all([ fetchMerklClaimable(userAddress, chainId), fetchURDClaimable(userAddress), ]); return { merkl: merklRewards, urd: urdRewards, total: combineRewards(merklRewards, urdRewards), }; } async function fetchMerklClaimable(userAddress: string, chainId: number) { const response = await fetch( `https://api.merkl.xyz/v4/userRewards?user=${userAddress}&chainId=${chainId}` ); const data = await response.json(); const claimable: Array<{ token: string; amount: bigint; symbol: string }> = []; for (const [campaignAddr, campaignData] of Object.entries(data[chainId] || {})) { for (const [tokenAddr, tokenData] of Object.entries( campaignData.claimable || {} )) { claimable.push({ token: tokenAddr, amount: BigInt(tokenData.unclaimed || "0"), symbol: tokenData.symbol, }); } } return claimable; } async function fetchURDClaimable(userAddress: string) { const response = await fetch( `https://rewards.morpho.org/v1/users/${userAddress}/rewards` ); const rewards = await response.json(); return rewards.map((r) => ({ token: r.asset.address, amount: BigInt(r.amount.claimable_now), symbol: r.asset.symbol || "Unknown", })); } function combineRewards(merkl: any[], urd: any[]) { const combined: Record = {}; [...merkl, ...urd].forEach((reward) => { if (!combined[reward.token]) { combined[reward.token] = { ...reward }; } else { combined[reward.token].amount += reward.amount; } }); return Object.values(combined); }`` ### React Component for User Rewards[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#react-component-for-user-rewards) Copy `import { formatUnits } from "viem"; function UserRewardsDisplay({ userAddress, chainId }: { userAddress: string; chainId: number; }) { const [rewards, setRewards] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { getUserAllClaimableRewards(userAddress, chainId) .then(setRewards) .finally(() => setLoading(false)); }, [userAddress, chainId]); if (loading) return
Loading rewards...
; if (!rewards || rewards.total.length === 0) { return
No claimable rewards
; } return (

Your Claimable Rewards

{rewards.total.map((reward) => (
{reward.symbol} {formatUnits(reward.amount, 18)} {reward.symbol}
))} {/* Show separate counts for transparency */}
Merkl: {rewards.merkl.length} rewards • URD: {rewards.urd.length} rewards
{/* Claim button */}
); }` Displaying Rewards in Tables[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#displaying-rewards-in-tables) --------------------------------------------------------------------------------------------------------------------------------- For portfolio or dashboard views: Copy `function VaultPortfolio({ userAddress, chainId }: { userAddress: string; chainId: number; }) { const [vaults, setVaults] = useState([]); return ( {vaults.map((vault) => ( ))}
Vault Your Deposit Base APY Rewards APR Total APY Claimable
{vault.name} {vault.userDeposit} {vault.asset.symbol} {vault.baseApy.toFixed(2)}% +{vault.rewardsApr.toFixed(2)}% {vault.totalApy.toFixed(2)}% {vault.claimable > 0 ? ( ) : ( )}
); }` Showing Reward Program Details[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#showing-reward-program-details) ------------------------------------------------------------------------------------------------------------------------------------- Provide transparency about active programs: Copy `function RewardProgramsCard({ vaultAddress, chainId }) { const [programs, setPrograms] = useState([]); // Fetch active programs for this vault useEffect(() => { fetchActivePrograms(vaultAddress, chainId).then(setPrograms); }, [vaultAddress, chainId]); return (

Active Reward Programs

{programs.map((program) => (
{program.token} {program.token} Rewards
APR: {program.apr.toFixed(2)}%
Ends: {formatDate(program.endDate)}
Source: {program.isMerkl ? "Merkl" : "Morpho URD"}
))}
); }` Real-Time Updates[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#real-time-updates) ----------------------------------------------------------------------------------------------------------- ### Polling for Updates[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#polling-for-updates) Copy `function useRewardsPolling(userAddress: string, chainId: number) { const [rewards, setRewards] = useState(null); useEffect(() => { const fetchRewards = () => { getUserAllClaimableRewards(userAddress, chainId).then(setRewards); }; // Initial fetch fetchRewards(); // Poll every 5 minutes for Merkl updates const interval = setInterval(fetchRewards, 5 * 60 * 1000); return () => clearInterval(interval); }, [userAddress, chainId]); return rewards; }` ### Showing Accruing Rewards[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#showing-accruing-rewards) For a more dynamic experience: Copy `function AccruingRewardsDisplay({ baseAmount, ratePerSecond }) { const [accrued, setAccrued] = useState(baseAmount); useEffect(() => { const interval = setInterval(() => { setAccrued((prev) => prev + ratePerSecond); }, 1000); return () => clearInterval(interval); }, [ratePerSecond]); return (
Accruing: {accrued.toFixed(6)} MORPHO
); }` Handling Edge Cases[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#handling-edge-cases) --------------------------------------------------------------------------------------------------------------- ### No Rewards Available[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#no-rewards-available) Copy `{rewards.length === 0 ? (

No active reward programs for this vault

Check back later or explore other vaults

) : ( )}` ### Failed to Fetch Rewards[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#failed-to-fetch-rewards) Copy `{error ? (

Unable to load rewards data

) : ( )}` ### Dust Amounts[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#dust-amounts) Don't show tiny amounts that aren't worth claiming: Copy `const DUST_THRESHOLD = 0.01; // $0.01 USD function filterDust(rewards: any[], tokenPrices: Record) { return rewards.filter((reward) => { const usdValue = parseFloat(formatUnits(reward.amount, 18)) * tokenPrices[reward.token]; return usdValue > DUST_THRESHOLD; }); }` Accessibility Considerations[](https://docs.morpho.org/build/rewards/tutorials/integrate-display#accessibility-considerations) --------------------------------------------------------------------------------------------------------------------------------- * **Use semantic HTML**: `` for tabular data, `