# Morpho Protocol Documentation > Morpho is a decentralized lending protocol on Ethereum, Base, and other EVM chains. > It consists of Morpho Markets (isolated lending pools) and Morpho Vaults (managed > lending strategies). Curators manage vaults, developers integrate via APIs/SDKs. LLM-friendly endpoints at docs.morpho.org: - /llms.txt — Curated index of ~46 key pages - /llms-full.txt — All 111 pages in clean markdown - /llms-all.txt — All pages with code snippets inlined (this file) - /llms-pages.json — JSON: URL path to {title, section, content} This file contains 111 pages from https://docs.morpho.org, separated by `##` headers. Pages are organized into these sections: - **Get Started** (16 pages): Protocol overview, products, contract addresses, audits - **Learn** (16 pages): Core concepts — markets, vaults, oracles, IRM, liquidation - **Build** (34 pages): Developer tutorials for Earn (vaults), Borrow (markets), Rewards - **Curate** (32 pages): Vault curator guides — roles, V1 & V2 tutorials, security - **Tools** (13 pages): APIs, SDKs, subgraphs, community tools Quick navigation: - New to Morpho? → "Morpho Market V1" and "Morpho Vault V2" in Learn - Building Earn? → "Morpho Vaults for Earn products" in Build - Building Borrow? → "Morpho Markets for Borrow products" in Build - Contract addresses? → "Addresses" in Get Started - API queries? → "Morpho API" in Tools # --- Get Started --- ## [Products](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 → Borrow Provide collateral to borrow any asset + Low costs + Higher collateralization factors + Per market rates + Zero fees Build → ## [Addresses](https://docs.morpho.org/get-started/resources/addresses/) ## Morpho V2 Contracts | 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) | | MorphoMarketV1 AdapterV2Factory | [ 0x32BB1c0D48D8b1B3363e86eeB9A0300BAd61ccc1 ](https://etherscan.io/address/0x32BB1c0D48D8b1B3363e86eeB9A0300BAd61ccc1#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) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x6b46fa3cc9EBF8aB230aBAc664E37F2966Bf7971 ](https://arbiscan.io/address/0x6b46fa3cc9EBF8aB230aBAc664E37F2966Bf7971#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xD8Fc8a85779551e78B516da9f74061cb3b086793 ](https://arbiscan.io/address/0xD8Fc8a85779551e78B516da9f74061cb3b086793#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0xeF84b1ecEbe43283ec5AF95D7a5c4D7dE0a9859b ](https://arbiscan.io/address/0xeF84b1ecEbe43283ec5AF95D7a5c4D7dE0a9859b#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0xc00eb3c7aD1aE986A7f05F5A9d71aCa39c763C65 ](https://arbiscan.io/address/0xc00eb3c7aD1aE986A7f05F5A9d71aCa39c763C65#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0xf7b1d9e43BAeA3705f2B303693766ACbcfec6A55 ](https://snowtrace.io/address/0xf7b1d9e43BAeA3705f2B303693766ACbcfec6A55/contract/43114/code?chainid=43114) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0x9633D22Bb8F42f6f70DbbBe34c11EB9209769b8b ](https://snowtrace.io/address/0x9633D22Bb8F42f6f70DbbBe34c11EB9209769b8b/contract/43114/code?chainid=43114) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x66dC122CF454576684Ad78A2800a8Eb052b2E9a6 ](https://snowtrace.io/address/0x66dC122CF454576684Ad78A2800a8Eb052b2E9a6/contract/43114/code?chainid=43114) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x4501125508079A99ebBebCE205DeC9593C2b5857 ](https://basescan.org/address/0x4501125508079A99ebBebCE205DeC9593C2b5857#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xF42D9c36b34c9c2CF3Bc30eD2a52a90eEB604642 ](https://basescan.org/address/0xF42D9c36b34c9c2CF3Bc30eD2a52a90eEB604642#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0x9a1B378C43BA535cDB89934230F0D3890c51C0EB ](https://basescan.org/address/0x9a1B378C43BA535cDB89934230F0D3890c51C0EB#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x5C2531Cbd2cf112Cf687da3Cd536708aDd7DB10a ](https://basescan.org/address/0x5C2531Cbd2cf112Cf687da3Cd536708aDd7DB10a#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x2C83a291cF1428F915e60D4dC0c063498d9B137A ](https://botanixscan.io/address/0x2C83a291cF1428F915e60D4dC0c063498d9B137A/contract/3637/code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xda8d0b0e00A3062FD09005bBAe843a1C82d67a97 ](https://botanixscan.io/address/0xda8d0b0e00A3062FD09005bBAe843a1C82d67a97/contract/3637/code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0xa4a4b6D925734fa1e45Bb38fbA20d32BB39A3E7A ](https://botanixscan.io/address/0xa4a4b6D925734fa1e45Bb38fbA20d32BB39A3E7A/contract/3637/code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0xcA0CCC121000561134BF5f2a0cF8b8d6FC4Cf044 ](https://botanixscan.io/address/0xcA0CCC121000561134BF5f2a0cF8b8d6FC4Cf044/contract/3637/code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x3137e22F379A1Df004DDb10EBbecF1CfD8CbC0e2 ](https://explorer.mainnet.citrea.xyz/address/0x3137e22F379A1Df004DDb10EBbecF1CfD8CbC0e2?tab=contract) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0x01Ff31888b1FB51f951273C409f653Dba5Ce8200 ](https://explorer.mainnet.citrea.xyz/address/0x01Ff31888b1FB51f951273C409f653Dba5Ce8200?tab=contract) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x83dd673Fa2C4DE16cAAF0e6109845EeEbb6d1E00 ](https://explorer.mainnet.citrea.xyz/address/0x83dd673Fa2C4DE16cAAF0e6109845EeEbb6d1E00?tab=contract) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x05519a0835a1bFD90f110aA7ca46e9A5F81Ed3b4 ](https://explorer.cronos.org/address/0x05519a0835a1bFD90f110aA7ca46e9A5F81Ed3b4#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0x8840F99Bb2D4f69fb02b2d019384C5c98a11746c ](https://explorer.cronos.org/address/0x8840F99Bb2D4f69fb02b2d019384C5c98a11746c#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x295e0aB80f8234398cd0E51C85D873ee69E5F0DD ](https://explorer.cronos.org/address/0x295e0aB80f8234398cd0E51C85D873ee69E5F0DD#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0xD7217E5687FF1071356C780b5fe4803D9D967da7 ](https://hyperevmscan.io/address/0xD7217E5687FF1071356C780b5fe4803D9D967da7#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xdf5202e29654e02011611A086f15477880580CAc ](https://hyperevmscan.io/address/0xdf5202e29654e02011611A086f15477880580CAc#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0xaEff6Ef4B7bbfbAadB18b634A8F11392CBeB72Be ](https://hyperevmscan.io/address/0xaEff6Ef4B7bbfbAadB18b634A8F11392CBeB72Be#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x857B55cEb57dA0C2A83EE08a8dB529B931089aee ](https://hyperevmscan.io/address/0x857B55cEb57dA0C2A83EE08a8dB529B931089aee#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0xFcb8b57E56787bB29e130Fca67f3c5a1232975D1 ](https://katanascan.com/address/0xFcb8b57E56787bB29e130Fca67f3c5a1232975D1#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xc8D22B1adD3D176600E9952e7876e9249254cAAF ](https://katanascan.com/address/0xc8D22B1adD3D176600E9952e7876e9249254cAAF#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0x6d6A3ba62836d6B40277767dCAc8fd390d4BcedC ](https://katanascan.com/address/0x6d6A3ba62836d6B40277767dCAc8fd390d4BcedC#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0xA9132a09838fD20304dF2B2892679d06A4cc6371 ](https://katanascan.com/address/0xA9132a09838fD20304dF2B2892679d06A4cc6371#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x5DC11CF8BA4C39d1194F91218D35008d9F52A5d0 ](https://lineascan.build/address/0x5DC11CF8BA4C39d1194F91218D35008d9F52A5d0#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0x6FaF26DD640e22457cA4fd5DA702BA3E169eEd87 ](https://lineascan.build/address/0x6FaF26DD640e22457cA4fd5DA702BA3E169eEd87#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0xcAB7C66F7191Ad3Ef1e7fEeb67F3137BC975F8cE ](https://lineascan.build/address/0xcAB7C66F7191Ad3Ef1e7fEeb67F3137BC975F8cE#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x122Ea8ff8888C29F8736665d576e3fAEF15D27D5 ](https://lineascan.build/address/0x122Ea8ff8888C29F8736665d576e3fAEF15D27D5#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [0x8B2F922162FBb60A6a072cC784A2E4168fB0bb0c](https://monadscan.com/address/0x8B2F922162FBb60A6a072cC784A2E4168fB0bb0c#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [0x9f3c0999425656fD189C69a8aD68cB64986D644A](https://monadscan.com/address/0x9f3c0999425656fD189C69a8aD68cB64986D644A#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [0xa00666E86C7e2FA8d2c78d9481E687e098340180](https://monadscan.com/address/0xa00666E86C7e2FA8d2c78d9481E687e098340180#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [0x6a42f8b46224baA4DbBBc2F860F4675eeA7bd52B](https://monadscan.com/address/0x6a42f8b46224baA4DbBBc2F860F4675eeA7bd52B#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x6128b680b277Bf4Df80DFE9D8c55A498660870ef ](https://optimistic.etherscan.io/address/0x6128b680b277Bf4Df80DFE9D8c55A498660870ef#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xEe9F7C64dD827ED7b5CAA2272936366FAca00CF3 ](https://optimistic.etherscan.io/address/0xEe9F7C64dD827ED7b5CAA2272936366FAca00CF3#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0x71B299bDb52b6396429cd1E11c418324502CB434 ](https://optimistic.etherscan.io/address/0x71B299bDb52b6396429cd1E11c418324502CB434#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0xD1346be260cd22Eab9E6163010b0D5CbfAAAD32b ](https://optimistic.etherscan.io/address/0xD1346be260cd22Eab9E6163010b0D5CbfAAAD32b#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0xD7373D3597C26e7340B0612C938EEFE6DE02Ab30 ](https://plasmascan.to/address/0xD7373D3597C26e7340B0612C938EEFE6DE02Ab30/contract/9745/code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0x42432F31D085ECb8D9C128092c84b084123C624e ](https://plasmascan.to/address/0x42432F31D085ECb8D9C128092c84b084123C624e/contract/9745/code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0xB241753668F929EB78A0069330c31305C0C83255 ](https://plasmascan.to/address/0xB241753668F929EB78A0069330c31305C0C83255/contract/9745/code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x171b2807E8ce8fb853C37bc3C3b4805aBf6f9896 ](https://plasmascan.to/address/0x171b2807E8ce8fb853C37bc3C3b4805aBf6f9896/contract/9745/code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x4f0a370bb367843CFd914c4d9972523aD2f8FCc9 ](https://explorer.plume.org/address/0x4f0a370bb367843CFd914c4d9972523aD2f8FCc9?tab=contract) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0x5935fFcD1C5D269840ae7c685bC957A73E04AEDB ](https://explorer.plume.org/address/0x5935fFcD1C5D269840ae7c685bC957A73E04AEDB?tab=contract) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0xB7c243AfACb25870775ADFdAe9D0EAc2324dD152 ](https://explorer.plume.org/address/0xB7c243AfACb25870775ADFdAe9D0EAc2324dD152?tab=contract) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x60d3184BDD31BAE7De973894B3bA0b3B6900B79a ](https://explorer.plume.org/address/0x60d3184BDD31BAE7De973894B3bA0b3B6900B79a?tab=contract) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0xC11a53eE9B1eCc7a068D8e40F8F17926584F97Cf ](https://polygonscan.com/address/0xC11a53eE9B1eCc7a068D8e40F8F17926584F97Cf#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xEb174FEA51Da241eB3B516959B216e013de2888a ](https://polygonscan.com/address/0xEb174FEA51Da241eB3B516959B216e013de2888a#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0xc0006f52B38625C283dd2f972dD9B779A5851Dd0 ](https://polygonscan.com/address/0xc0006f52B38625C283dd2f972dD9B779A5851Dd0#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0xb70a43821d2707fA9d0EDd9511CC499F468Ba564 ](https://polygonscan.com/address/0xb70a43821d2707fA9d0EDd9511CC499F468Ba564#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x7fc35488803D49D00a94b206A223f7661898BE3a ](https://stablescan.xyz/address/0x7fc35488803D49D00a94b206A223f7661898BE3a#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0x4EF83ACD552598a1196c1aBDD0bA2EdE6f2237B4 ](https://stablescan.xyz/address/0x4EF83ACD552598a1196c1aBDD0bA2EdE6f2237B4#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0x9282DBa3d1788f4f02B5DdFc4fc5985e70197620 ](https://stablescan.xyz/address/0x9282DBa3d1788f4f02B5DdFc4fc5985e70197620#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0xCe93fcB2849EB886F1e81d45D2747dF803f843C3 ](https://stablescan.xyz/address/0xCe93fcB2849EB886F1e81d45D2747dF803f843C3#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0xC9b34c108014B44e5a189A830e7e04c56704a0c9 ](https://uniscan.xyz/address/0xC9b34c108014B44e5a189A830e7e04c56704a0c9#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xf1Ab9e885C0faa0cbCEd407498BBA895537aD754 ](https://uniscan.xyz/address/0xf1Ab9e885C0faa0cbCEd407498BBA895537aD754#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0x9a13bdA35F98811fbAcf097966b2C838f3F9c58C ](https://uniscan.xyz/address/0x9a13bdA35F98811fbAcf097966b2C838f3F9c58C#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0xB9130D2A87d7c60ED7E7e4b25bdA6e3E6841becB ](https://uniscan.xyz/address/0xB9130D2A87d7c60ED7E7e4b25bdA6e3E6841becB#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | VaultV2Factory | [ 0x6846EA318B6B987Ee6b28eBFd87c3409F1d13108 ](https://worldscan.org/address/0x6846EA318B6B987Ee6b28eBFd87c3409F1d13108#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoVaultV1 AdapterFactory | [ 0xbF7DEa3756668C7E396C655D646C039826ba8416 ](https://worldscan.org/address/0xbF7DEa3756668C7E396C655D646C039826ba8416#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoMarketV1 AdapterV2Factory | [ 0xEd0b06fcdDB6dD0985e2de9D22ad034d313b7dBd ](https://worldscan.org/address/0xEd0b06fcdDB6dD0985e2de9D22ad034d313b7dBd#code) | [vault-v2](https://github.com/morpho-org/vault-v2) | | MorphoRegistry | [ 0x06A47994B4890dcA28C076969cedE1151d86EFCF ](https://worldscan.org/address/0x06A47994B4890dcA28C076969cedE1151d86EFCF#code) | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) | ## Morpho V1 Contracts | 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) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xc85CE8ffdA27b646D269516B8d0Fa6ec2E958B55 ](https://abscan.org/address/0xc85CE8ffdA27b646D269516B8d0Fa6ec2E958B55#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xd334eb112CfD1EB4a50FB871b7D9895EBB955C43 ](https://abscan.org/address/0xd334eb112CfD1EB4a50FB871b7D9895EBB955C43#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x3585E3fD72F8d1b02250E1F6496b706c6e092884 ](https://abscan.org/address/0x3585E3fD72F8d1b02250E1F6496b706c6e092884#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x83A7f60c9fc57cEf1e8001bda98783AA1A53E4b1 ](https://abscan.org/address/0x83A7f60c9fc57cEf1e8001bda98783AA1A53E4b1#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x609f3DF49806B5617A0Bd3301f04Ac3CB26d9e82 ](https://abscan.org/address/0x609f3DF49806B5617A0Bd3301f04Ac3CB26d9e82#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x1058DA51242dF63bA3A61c838A61405ea6Edb083 ](https://abscan.org/address/0x1058DA51242dF63bA3A61c838A61405ea6Edb083#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x6c247b1F6182318877311737BaC0844bAa518F5e ](https://arbiscan.io/address/0x6c247b1F6182318877311737BaC0844bAa518F5e) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x66F30587FB8D4206918deb78ecA7d5eBbafD06DA ](https://arbiscan.io/address/0x66F30587FB8D4206918deb78ecA7d5eBbafD06DA) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x98Ce5D183DC0c176f54D37162F87e7eD7f2E41b5 ](https://arbiscan.io/address/0x98Ce5D183DC0c176f54D37162F87e7eD7f2E41b5) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x878988f5f561081deEa117717052164ea1Ef0c82 ](https://arbiscan.io/address/0x878988f5f561081deEa117717052164ea1Ef0c82) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x769583Af5e9D03589F159EbEC31Cc2c23E8C355E ](https://arbiscan.io/address/0x769583Af5e9D03589F159EbEC31Cc2c23E8C355E) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x635c31B5DF1F7EFbCbC07E302335Ef4230758e3d ](https://arbiscan.io/address/0x635c31B5DF1F7EFbCbC07E302335Ef4230758e3d) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x895383274303AA19fe978AFB4Ac55C7f094f982C ](https://snowtrace.io/address/0x895383274303AA19fe978AFB4Ac55C7f094f982C/contract/43114/code?chainid=43114) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xb6ac9477D574EE2a7BF32d2475b303fb70968AA4 ](https://snowtrace.io/address/0xb6ac9477D574EE2a7BF32d2475b303fb70968AA4/contract/43114/code?chainid=43114) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xF0c1299D44b3803243d7c1eEC2042e9484Db13f2 ](https://snowtrace.io/address/0xF0c1299D44b3803243d7c1eEC2042e9484Db13f2/contract/43114/code?chainid=43114) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | PreLiquidation Factory | [ 0xDF63DE139fe183561b6438aF883DBb28d41Cb948 ](https://snowtrace.io/address/0xDF63DE139fe183561b6438aF883DBb28d41Cb948/contract/43114/code?chainid=43114) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb ](https://basescan.org/address/0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x46415998764C29aB2a25CbeA6254146D50D22687 ](https://basescan.org/address/0x46415998764C29aB2a25CbeA6254146D50D22687) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x2DC205F24BCb6B311E5cdf0745B0741648Aebd3d ](https://basescan.org/address/0x2DC205F24BCb6B311E5cdf0745B0741648Aebd3d) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xFf62A7c278C62eD665133147129245053Bbf5918 ](https://basescan.org/address/0xFf62A7c278C62eD665133147129245053Bbf5918) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | MetaMorpho Factory [OLD] | [ 0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101 ](https://basescan.org/address/0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101) | [metamorpho](https://github.com/morpho-org/metamorpho/tree/c5e758da97d210ede921bf228d37d31e744bd5bf) | | Public Allocator | [ 0xA090dD1a701408Df1d4d0B85b716c87565f90467 ](https://basescan.org/address/0xA090dD1a701408Df1d4d0B85b716c87565f90467) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x8cd16b62E170Ee0bA83D80e1F80E6085367e2aef ](https://basescan.org/address/0x8cd16b62E170Ee0bA83D80e1F80E6085367e2aef) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xAeA7eFF1bD3c875c18ef50F0387892dF181431C6 ](https://www.btrscan.com/address/0xaea7eff1bd3c875c18ef50f0387892df181431c6?tab=Contract) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xefB565442B9Eb740B50Cf928C14d21c0111254F9 ](https://www.btrscan.com/address/0xefB565442B9Eb740B50Cf928C14d21c0111254F9?tab=Contract) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xfDc69d06De855701731D142F28bD401802DA4daF ](https://www.btrscan.com/address/0xfDc69d06De855701731D142F28bD401802DA4daF?tab=Contract) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xb95De4a9C81Ba6240378F383f88592d30937d048 ](https://www.btrscan.com/address/0xb95De4a9C81Ba6240378F383f88592d30937d048?tab=Contract) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x3A1db0038361528756bED147abe3d41255c7128c ](https://www.btrscan.com/address/0x3A1db0038361528756bED147abe3d41255c7128c?tab=Contract) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x4E28CAE07A008FF2D7D345992C969118eb253CD6 ](https://www.btrscan.com/address/0x4E28CAE07A008FF2D7D345992C969118eb253CD6?tab=Contract) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x01b0Bd309AA75547f7a37Ad7B1219A898E67a83a ](https://bscscan.com/address/0x01b0Bd309AA75547f7a37Ad7B1219A898E67a83a#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x7112D95cB5f6b13bF5F5B94a373bB3b2B381F979 ](https://bscscan.com/address/0x7112D95cB5f6b13bF5F5B94a373bB3b2B381F979#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xDf2035fC15919588526dBb5560863C812F135236 ](https://bscscan.com/address/0xDf2035fC15919588526dBb5560863C812F135236#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x92983687e672cA6d96530f9Dbe11a196cE905d72 ](https://bscscan.com/address/0x92983687e672cA6d96530f9Dbe11a196cE905d72#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x842bEccF8eBC11006c4bE96DEfE09b60326D0495 ](https://bscscan.com/address/0x842bEccF8eBC11006c4bE96DEfE09b60326D0495#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xEB8871F0FA8aB787AbCD28d1095f7B486d241D42 ](https://bscscan.com/address/0xEB8871F0FA8aB787AbCD28d1095f7B486d241D42#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x8183d41556Be257fc7aAa4A48396168C8eF2bEAD ](https://botanixscan.io/address/0x8183d41556Be257fc7aAa4A48396168C8eF2bEAD/contract/3637/code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x28021Ef0269C83302c09D2A89f7b202C4AeDf0C2 ](https://botanixscan.io/address/0x28021Ef0269C83302c09D2A89f7b202C4AeDf0C2/contract/3637/code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x627D51CE8D56b6D8562F6EbD301e4DE0a8a8bf8e ](https://botanixscan.io/address/0x627D51CE8D56b6D8562F6EbD301e4DE0a8a8bf8e/contract/3637/code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xADfE7FF70F98157E020aD7725e149D2E573480Ee ](https://botanixscan.io/address/0xADfE7FF70F98157E020aD7725e149D2E573480Ee/contract/3637/code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x1251473c33E398226C7b9453d75dF59548f1D228 ](https://botanixscan.io/address/0x1251473c33E398226C7b9453d75dF59548f1D228/contract/3637/code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x2e999ddEbd85bdA0B87C370f30ad18cCb943De60 ](https://botanixscan.io/address/0x2e999ddEbd85bdA0B87C370f30ad18cCb943De60/contract/3637/code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xea4f2979D7A99B40404b447Cf71c008e3805760F ](https://camp.cloud.blockscout.com/address/0xea4f2979D7A99B40404b447Cf71c008e3805760F?tab=contract) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xd5661D965cc60ed1954d4f6725b766051De3ef97 ](https://camp.cloud.blockscout.com/address/0xd5661D965cc60ed1954d4f6725b766051De3ef97?tab=contract) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x391A3fd481743FE48409e2e31eDac8a5f4C7653A ](https://camp.cloud.blockscout.com/address/0x391A3fd481743FE48409e2e31eDac8a5f4C7653A?tab=contract) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x3F4b9246b7Cd3F7671c70BeBd5AAFC08e5bb5f16 ](https://camp.cloud.blockscout.com/address/0x3F4b9246b7Cd3F7671c70BeBd5AAFC08e5bb5f16?tab=contract) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x0b7a3A49dafd98363B428cEC966106f29c0eee75 ](https://camp.cloud.blockscout.com/address/0x0b7a3A49dafd98363B428cEC966106f29c0eee75?tab=contract) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xD55fA5DF6F1A21C2B93009A702aad3a0891C1B48 ](https://camp.cloud.blockscout.com/address/0xD55fA5DF6F1A21C2B93009A702aad3a0891C1B48?tab=contract) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xd24ECdD8C1e0E57a4E26B1a7bbeAa3e95466A569 ](https://celoscan.io/address/0xd24ECdD8C1e0E57a4E26B1a7bbeAa3e95466A569#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x683CAAADdfA2F42e24880E202676526d501a5dED ](https://celoscan.io/address/0x683CAAADdfA2F42e24880E202676526d501a5dED#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x3a4849b5174Dc6828c6Dc9BBD87e61Ed1ebE9fFA ](https://celoscan.io/address/0x3a4849b5174Dc6828c6Dc9BBD87e61Ed1ebE9fFA#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x6870aA9f66C1e5Efe8Dbe8730e86E9e91f688275 ](https://celoscan.io/address/0x6870aA9f66C1e5Efe8Dbe8730e86E9e91f688275#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x3Fe12193D178B76BaF4e23a083A64e49ACDE3188 ](https://celoscan.io/address/0x3Fe12193D178B76BaF4e23a083A64e49ACDE3188#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x717a3eF7D366F5ce4636011924D0Bd65ea5eCE2f ](https://celoscan.io/address/0x717a3eF7D366F5ce4636011924D0Bd65ea5eCE2f#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x99D31FEcc885204b4136ea5D2ef2a37F36E3AeB8 ](https://explorer.mainnet.citrea.xyz/address/0x99D31FEcc885204b4136ea5D2ef2a37F36E3AeB8?tab=contract) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x723E35C4CBb5B91669b62F130f2aC12931DF8049 ](https://explorer.mainnet.citrea.xyz/address/0x723E35C4CBb5B91669b62F130f2aC12931DF8049?tab=contract) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xFd32e705E2bc6e716e2522Df0391BF26DfbADBAB ](https://explorer.mainnet.citrea.xyz/address/0xFd32e705E2bc6e716e2522Df0391BF26DfbADBAB?tab=contract) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | PreLiquidation Factory | [ 0xdc1078a8A29dB9FB1eb9266e92fA5f2130432E5A ](https://explorer.mainnet.citrea.xyz/address/0xdc1078a8A29dB9FB1eb9266e92fA5f2130432E5A?tab=contract) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xc2B1E031540e3F3271C5F3819F0cC7479a8DdD90 ](https://cornscan.io/address/0xc2B1E031540e3F3271C5F3819F0cC7479a8DdD90) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x58a42117d753a0e69694545DfA19d64c2fB759fB ](https://cornscan.io/address/0x58a42117d753a0e69694545DfA19d64c2fB759fB) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x16278156D366fC91536b6b81482ffaC47EEa06D6 ](https://cornscan.io/address/0x16278156D366fC91536b6b81482ffaC47EEa06D6) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xe430821595602eA5DD0cD350f86987437c7362fA ](https://cornscan.io/address/0xe430821595602eA5DD0cD350f86987437c7362fA) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xDFde06e2B2A2D718eE5560b73dA4F830E56A2f10 ](https://cornscan.io/address/0xDFde06e2B2A2D718eE5560b73dA4F830E56A2f10) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xb9065AC18d3EBdb3263B77B587f9c5CD570545D1 ](https://cornscan.io/address/0xb9065AC18d3EBdb3263B77B587f9c5CD570545D1) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xDF9a1DC07e5dEe5ccCCaBeC35e446C70fAF7434e ](https://explorer.cronos.org/address/0xDF9a1DC07e5dEe5ccCCaBeC35e446C70fAF7434e#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x1Db002C086439d55B9f33E6c0693Eb850F7c0607 ](https://explorer.cronos.org/address/0x1Db002C086439d55B9f33E6c0693Eb850F7c0607#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x44b2c8e4474751EF2BBC57B92928aFB99DA785De ](https://explorer.cronos.org/address/0x44b2c8e4474751EF2BBC57B92928aFB99DA785De#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xEA67e5566Ca2c0176d9db172A7f9A1e1F22E9D3A ](https://explorer.cronos.org/address/0xEA67e5566Ca2c0176d9db172A7f9A1e1F22E9D3A#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xFEAbEf95f3C937Ff4d5fD70005CF3392f8Ca02d5 ](https://explorer.cronos.org/address/0xFEAbEf95f3C937Ff4d5fD70005CF3392f8Ca02d5#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x8bedC738f5F0D54dF7E003297AAc6692b870F3Ed ](https://explorer.cronos.org/address/0x8bedC738f5F0D54dF7E003297AAc6692b870F3Ed#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xbCE7364E63C3B13C73E9977a83c9704E2aCa876e ](https://explorer.etherlink.com/address/0xbCE7364E63C3B13C73E9977a83c9704E2aCa876e?tab=contract) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xC1523BE776e66ba07b609b1914D0925278f21FE5 ](https://explorer.etherlink.com/address/0xC1523BE776e66ba07b609b1914D0925278f21FE5?tab=contract) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x12FA40f687a35611720E1DcB59976B6e51247298 ](https://explorer.etherlink.com/address/0x12FA40f687a35611720E1DcB59976B6e51247298?tab=contract) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x997a79c3C04c5B9eb27d343ae126bcCFb5D74781 ](https://explorer.etherlink.com/address/0x997a79c3C04c5B9eb27d343ae126bcCFb5D74781?tab=contract) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x8b8B1bd41d36c06253203CD21463994aB752c1e6 ](https://explorer.etherlink.com/address/0x8b8B1bd41d36c06253203CD21463994aB752c1e6?tab=contract) | | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xd1c37fDd941256FC184eF3A07Be540a90b81Ec21 ](https://explorer.etherlink.com/address/0xd1c37fDd941256FC184eF3A07Be540a90b81Ec21?tab=contract) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xa6030627d724bA78a59aCf43Be7550b4C5a0653b ](https://fraxscan.com/address/0xa6030627d724bA78a59aCf43Be7550b4C5a0653b) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xA0D4D77b5D9933073572E19C172BFE866312673b ](https://fraxscan.com/address/0xA0D4D77b5D9933073572E19C172BFE866312673b) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x39d8622C607A691D7705E8842fbB12E3c38dCD41 ](https://fraxscan.com/address/0x39d8622C607A691D7705E8842fbB12E3c38dCD41) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x27D4Af0AC9E7FDfA6D0853236f249CC27AE79488 ](https://fraxscan.com/address/0x27D4Af0AC9E7FDfA6D0853236f249CC27AE79488) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x37a888192165fC39884f87c64E2476BfD2C09675 ](https://fraxscan.com/address/0x37a888192165fC39884f87c64E2476BfD2C09675) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x373ccddcd3F09D2e1430B3F2b290B9bF56Ae7336 ](https://fraxscan.com/address/0x373ccddcd3F09D2e1430B3F2b290B9bF56Ae7336) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xB74D4dd451E250bC325AFF0556D717e4E2351c66 ](https://gnosisscan.io/address/0xB74D4dd451E250bC325AFF0556D717e4E2351c66#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xae529333703C34b8976BaB9D04AF3f0B9Cff05c5 ](https://gnosisscan.io/address/0xae529333703C34b8976BaB9D04AF3f0B9Cff05c5#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x8FFd9e3A4B02D217C3EBB5e48E64f748d7476c32 ](https://gnosisscan.io/address/0x8FFd9e3A4B02D217C3EBB5e48E64f748d7476c32#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xFf3623eAdB1DD8590b902fA23baCfaB3c361Bf68 ](https://gnosisscan.io/address/0xFf3623eAdB1DD8590b902fA23baCfaB3c361Bf68#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x6F3313A395Fb09a56502710aB75cf69fb692270A ](https://gnosisscan.io/address/0x6F3313A395Fb09a56502710aB75cf69fb692270A#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x919d1273014Ec7e34aDb952Bff161D6dC9964261 ](https://gnosisscan.io/address/0x919d1273014Ec7e34aDb952Bff161D6dC9964261#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xa4Ca2c2e25b97DA19879201bA49422bc6f181f42 ](https://explorer.hemi.xyz/address/0xa4Ca2c2e25b97DA19879201bA49422bc6f181f42) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xdEbdEa31624552DF904A065221cD14088ABDeD70 ](https://explorer.hemi.xyz/address/0xdEbdEa31624552DF904A065221cD14088ABDeD70) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xB3cb32E6185446a6Bc7A047E4FfA138fA939e133 ](https://explorer.hemi.xyz/address/0xB3cb32E6185446a6Bc7A047E4FfA138fA939e133) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x8e52179BeB18E882040b01632440d8Ca0f01da82 ](https://explorer.hemi.xyz/address/0x8e52179BeB18E882040b01632440d8Ca0f01da82) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x4107Ea1746909028d6212B315dE5fE9538F9eb39 ](https://explorer.hemi.xyz/address/0x4107Ea1746909028d6212B315dE5fE9538F9eb39) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x40F2896C551194e364F7C846046C34d8a9FE97e4 ](https://explorer.hemi.xyz/address/0x40F2896C551194e364F7C846046C34d8a9FE97e4) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x68e37dE8d93d3496ae143F2E900490f6280C57cD ](https://hyperevmscan.io/address/0x68e37dE8d93d3496ae143F2E900490f6280C57cD#code) | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xD4a426F010986dCad727e8dd6eed44cA4A9b7483 ](https://hyperevmscan.io/address/0xD4a426F010986dCad727e8dd6eed44cA4A9b7483#code) | [morpho-org/morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho Chainlink Oracle V2 Factory | [ 0xeb476f124FaD625178759d13557A72394A6f9aF5 ](https://hyperevmscan.io/address/0xeb476f124FaD625178759d13557A72394A6f9aF5#code) | [morpho-org/morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0) | | MetaMorpho Factory V1.1 | [ 0xec051b19d654C48c357dC974376DeB6272f24e53 ](https://hyperevmscan.io/address/0xec051b19d654C48c357dC974376DeB6272f24e53#code) | [morpho-org/metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x517505be22D9068687334e69ae7a02fC77edf4Fc ](https://hyperevmscan.io/address/0x517505be22D9068687334e69ae7a02fC77edf4Fc#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x1b6782Ac7A859503cE953FBf4736311CC335B8f0 ](https://hyperevmscan.io/address/0x1b6782Ac7A859503cE953FBf4736311CC335B8f0#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x857f3EefE8cbda3Bc49367C996cd664A880d3042 ](https://explorer.inkonchain.com/address/0x857f3EefE8cbda3Bc49367C996cd664A880d3042) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x9515407b1512F53388ffE699524100e7270Ee57B ](https://explorer.inkonchain.com/address/0x9515407b1512F53388ffE699524100e7270Ee57B) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x3FFFE273ee348b9E1ef89533025C7f165B17B439 ](https://explorer.inkonchain.com/address/0x3FFFE273ee348b9E1ef89533025C7f165B17B439) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xd3f39505d0c48AFED3549D625982FdC38Ea9904b ](https://explorer.inkonchain.com/address/0xd3f39505d0c48AFED3549D625982FdC38Ea9904b) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x85416891752a6B81106c1C2999AE1AF5d8Cd3357 ](https://explorer.inkonchain.com/address/0x85416891752a6B81106c1C2999AE1AF5d8Cd3357) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x30607fEa77168d2c0401B6f60F0B40E32F9339E3 ](https://explorer.inkonchain.com/address/0x30607fEa77168d2c0401B6f60F0B40E32F9339E3) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xD50F2DffFd62f94Ee4AEd9ca05C61d0753268aBc ](https://katanascan.com/address/0xD50F2DffFd62f94Ee4AEd9ca05C61d0753268aBc#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x4F708C0ae7deD3d74736594C2109C2E3c065B428 ](https://katanascan.com/address/0x4F708C0ae7deD3d74736594C2109C2E3c065B428#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x7D047fB910Bc187C18C81a69E30Fa164f8c536eC ](https://katanascan.com/address/0x7D047fB910Bc187C18C81a69E30Fa164f8c536eC#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x1c8De6889acee12257899BFeAa2b7e534de32E16 ](https://katanascan.com/address/0x1c8De6889acee12257899BFeAa2b7e534de32E16#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x39EB6Da5e88194C82B13491Df2e8B3E213eD2412 ](https://katanascan.com/address/0x39EB6Da5e88194C82B13491Df2e8B3E213eD2412#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x678EB53A3bB79111263f47B84989d16D81c36D85 ](https://katanascan.com/address/0x678EB53A3bB79111263f47B84989d16D81c36D85#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x6B0D716aC0A45536172308e08fC2C40387262c9F ](https://lineascan.build/address/0x6B0D716aC0A45536172308e08fC2C40387262c9F#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x85C2Ef4Bd69f42D7Da19Fb9dcdD7Fb8d0F59cDeE ](https://lineascan.build/address/0x85C2Ef4Bd69f42D7Da19Fb9dcdD7Fb8d0F59cDeE#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x3FFF726062B03BfD5BC485eeEEcc92CF1d8F0105 ](https://lineascan.build/address/0x3FFF726062B03BfD5BC485eeEEcc92CF1d8F0105#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xA148a8223B622A72dC36472DE1492aBb5c089BA7 ](https://lineascan.build/address/0xA148a8223B622A72dC36472DE1492aBb5c089BA7#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x2d4cf00e18D48fD030d9b1E2FAAE6e0384C7610B ](https://lineascan.build/address/0x2d4cf00e18D48fD030d9b1E2FAAE6e0384C7610B#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x05a0Ff4E564ED1ba6B42247E19edFf83545C3C40 ](https://lineascan.build/address/0x05a0Ff4E564ED1ba6B42247E19edFf83545C3C40#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x00cD58DEEbd7A2F1C55dAec715faF8aed5b27BF8 ](https://blockscout.lisk.com/address/0x00cD58DEEbd7A2F1C55dAec715faF8aed5b27BF8?tab=contract) | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x5576629f21D528A8c3e06C338dDa907B94563902 ](https://blockscout.lisk.com/address/0x5576629f21D528A8c3e06C338dDa907B94563902?tab=contract) | [morpho-org/morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho Chainlink Oracle V2 Factory | [ 0x2eb4D17C2AAf1EA62Bf83Fb49Dd1128b14AF4D93 ](https://blockscout.lisk.com/address/0x2eb4D17C2AAf1EA62Bf83Fb49Dd1128b14AF4D93?tab=contract) | [morpho-org/morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0) | | MetaMorpho Factory V1.1 | [ 0x01dD876130690469F685a65C2B295A90a81BaD91 ](https://blockscout.lisk.com/address/0x01dD876130690469F685a65C2B295A90a81BaD91?tab=contract) | [morpho-org/metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xb1E5B1De2a54ab55C412B5ee1E38e46799588103 ](https://blockscout.lisk.com/address/0xb1E5B1De2a54ab55C412B5ee1E38e46799588103?tab=contract) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xF2c325F26691b6556e6f66451bb38bDa37FEbaa7 ](https://blockscout.lisk.com/address/0xF2c325F26691b6556e6f66451bb38bDa37FEbaa7?tab=contract) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xd85cE6BD68487E0AaFb0858FDE1Cd18c76840564 ](https://explorer.mode.network/address/0xd85cE6BD68487E0AaFb0858FDE1Cd18c76840564) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xE3d46Ae190Cb39ccA3655E966DcEF96b4eAe1d1c ](https://explorer.mode.network/address/0xE3d46Ae190Cb39ccA3655E966DcEF96b4eAe1d1c) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xf9380f7898423Bd7FDe3C9fDD1b2671A2471f39D ](https://explorer.mode.network/address/0xf9380f7898423Bd7FDe3C9fDD1b2671A2471f39D) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xae5b0884bfff430493D6C844B9fd052Af7d79278 ](https://explorer.mode.network/address/0xae5b0884bfff430493D6C844B9fd052Af7d79278) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xEE868Bf3359DA30c10ea472EAEBFC0a06E8F0120 ](https://explorer.mode.network/address/0xEE868Bf3359DA30c10ea472EAEBFC0a06E8F0120) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x249E4808264c545861e43728186a731dE7c7D745 ](https://explorer.mode.network/address/0x249E4808264c545861e43728186a731dE7c7D745) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [0xD5D960E8C380B724a48AC59E2DfF1b2CB4a1eAee](https://monadscan.com/address/0xd5d960e8c380b724a48ac59e2dff1b2cb4a1eaee#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [0x09475a3D6eA8c314c592b1a3799bDE044E2F400F](https://monadscan.com/address/0x09475a3D6eA8c314c592b1a3799bDE044E2F400F#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [0xC8659Bcd5279DB664Be973aEFd752a5326653739](https://monadscan.com/address/0xC8659Bcd5279DB664Be973aEFd752a5326653739#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [0x33f20973275B2F574488b18929cd7DCBf1AbF275](https://monadscan.com/address/0x33f20973275B2F574488b18929cd7DCBf1AbF275#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [0xfd70575B732F9482F4197FE1075492e114E97302](https://monadscan.com/address/0xfd70575B732F9482F4197FE1075492e114E97302#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [0xB5b3e541abD19799E0c65905a5a42BD37d6c94c0](https://monadscan.com/address/0xB5b3e541abD19799E0c65905a5a42BD37d6c94c0#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xce95AfbB8EA029495c66020883F87aaE8864AF92 ](https://optimistic.etherscan.io/address/0xce95AfbB8EA029495c66020883F87aaE8864AF92) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x8cD70A8F399428456b29546BC5dBe10ab6a06ef6 ](https://optimistic.etherscan.io/address/0x8cD70A8F399428456b29546BC5dBe10ab6a06ef6) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x1ec408D4131686f727F3Fd6245CF85Bc5c9DAD70 ](https://optimistic.etherscan.io/address/0x1ec408D4131686f727F3Fd6245CF85Bc5c9DAD70) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x3Bb6A6A0Bc85b367EFE0A5bAc81c5E52C892839a ](https://optimistic.etherscan.io/address/0x3Bb6A6A0Bc85b367EFE0A5bAc81c5E52C892839a) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x0d68a97324E602E02799CD83B42D337207B40658 ](https://optimistic.etherscan.io/address/0x0d68a97324E602E02799CD83B42D337207B40658) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x3d05C01EE8e97361b9E19D172128255eaE5F98B9 ](https://optimistic.etherscan.io/address/0x3d05C01EE8e97361b9E19D172128255eaE5F98B9) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :--------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x2fF74A46536f5c67ef5A42FD5B4e2Ed8A2cee249 ](https://plasmascan.to/address/0x2fF74A46536f5c67ef5A42FD5B4e2Ed8A2cee249/contract/9745/code) | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xf37f73028b5B4ebAdC055Deb24B1cde271CF0f71 ](https://plasmascan.to/address/0xf37f73028b5B4ebAdC055Deb24B1cde271CF0f71/contract/9745/code) | [morpho-org/morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho Chainlink Oracle V2 Factory | [ 0x5476AeEE80D87649fDD8Ee19eA65976F28525f7a ](https://plasmascan.to/address/0x5476AeEE80D87649fDD8Ee19eA65976F28525f7a/contract/9745/code) | [morpho-org/morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0) | | MetaMorpho Factory V1.1 | [ 0x69410429099018fa1586aAB0aFADC525314f5830 ](https://plasmascan.to/address/0x69410429099018fa1586aAB0aFADC525314f5830/contract/9745/code) | [morpho-org/metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xb41Aa3E41131947f4cd070617C582c1f9604ED11 ](https://plasmascan.to/address/0xb41Aa3E41131947f4cd070617C582c1f9604ED11/contract/9745/code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xA15Ec8609646A62b97522FC2568063145d081B91 ](https://plasmascan.to/address/0xA15Ec8609646A62b97522FC2568063145d081B91/contract/9745/code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :--------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x42b18785CE0Aed7BF7Ca43a39471ED4C0A3e0bB5 ](https://explorer.plume.org/address/0x42b18785CE0Aed7BF7Ca43a39471ED4C0A3e0bB5?tab=contract) | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x7420302Ddd469031Cd2282cd64225cCd46F581eA ](https://explorer.plume.org/address/0x7420302Ddd469031Cd2282cd64225cCd46F581eA?tab=contract) | [morpho-org/morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho Chainlink Oracle V2 Factory | [ 0x133F742c0D36864F37e15C33a18bA6fdc950ED0f ](https://explorer.plume.org/address/0x133F742c0D36864F37e15C33a18bA6fdc950ED0f?tab=contract) | [morpho-org/morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0) | | MetaMorpho Factory V1.1 | [ 0x2525D453D9BA13921D5aB5D8c12F9202b0e19456 ](https://explorer.plume.org/address/0x2525D453D9BA13921D5aB5D8c12F9202b0e19456?tab=contract) | [morpho-org/metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x58485338D93F4e3b4Bf2Af1C9f9C0aDF087AEf1C ](https://explorer.plume.org/address/0x58485338D93F4e3b4Bf2Af1C9f9C0aDF087AEf1C?tab=contract) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xF184156Cf6Ad4D3dA7F6449D40755A0f9de97ef3 ](https://explorer.plume.org/address/0xF184156Cf6Ad4D3dA7F6449D40755A0f9de97ef3?tab=contract) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x1bF0c2541F820E775182832f06c0B7Fc27A25f67 ](https://polygonscan.com/address/0x1bF0c2541F820E775182832f06c0B7Fc27A25f67) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xe675A2161D4a6E2de2eeD70ac98EEBf257FBF0B0 ](https://polygonscan.com/address/0xe675A2161D4a6E2de2eeD70ac98EEBf257FBF0B0) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x1ff7895Eb842794c5d07C4c547b6730e61295215 ](https://polygonscan.com/address/0x1ff7895Eb842794c5d07C4c547b6730e61295215) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xa9c87daB340631C34BB738625C70499e29ddDC98 ](https://polygonscan.com/address/0xa9c87daB340631C34BB738625C70499e29ddDC98) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xfac15aff53ADd2ff80C2962127C434E8615Df0d3 ](https://polygonscan.com/address/0xfac15aff53ADd2ff80C2962127C434E8615Df0d3) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xeDadDe37D76c72b98725614d0b41C20Fe612d304 ](https://polygonscan.com/address/0xeDadDe37D76c72b98725614d0b41C20Fe612d304) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x2d012EdbAdc37eDc2BC62791B666f9193FDF5a55 ](https://scrollscan.com/address/0x2d012EdbAdc37eDc2BC62791B666f9193FDF5a55) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xa5EA7500A27C0079961D93366A6e93aafF18CB90 ](https://scrollscan.com/address/0xa5EA7500A27C0079961D93366A6e93aafF18CB90) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xb5961902E60b188b1c665B7b72Ef616656A9e24E ](https://scrollscan.com/address/0xb5961902E60b188b1c665B7b72Ef616656A9e24E) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x56b65742ade55015e6480959808229Ad6dbc9295 ](https://scrollscan.com/address/0x56b65742ade55015e6480959808229Ad6dbc9295) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x8a7f671E45E51dE245649Cf916cA0256FB8a9927 ](https://scrollscan.com/address/0x8a7f671E45E51dE245649Cf916cA0256FB8a9927) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xeD960178e4aDA0296786Fa79D84e8FDF7bd44B25 ](https://scrollscan.com/address/0xeD960178e4aDA0296786Fa79D84e8FDF7bd44B25) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xc9cDAc20FCeAAF616f7EB0bb6Cd2c69dcfa9094c ](https://seiscan.io/address/0xc9cDAc20FCeAAF616f7EB0bb6Cd2c69dcfa9094c#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x6eFA8e3Aa8279eB2fd46b6083A9E52dA72EA56c4 ](https://seiscan.io/address/0x6eFA8e3Aa8279eB2fd46b6083A9E52dA72EA56c4#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x4bD68c2FF3274207EC07ED281C915758b6F23F07 ](https://seiscan.io/address/0x4bD68c2FF3274207EC07ED281C915758b6F23F07#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x8Dea49ec5bd5AeAc8bcf96B3E187F59354118291 ](https://seiscan.io/address/0x8Dea49ec5bd5AeAc8bcf96B3E187F59354118291#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xD878509446bE2C601f0f032F501851001B159D6B ](https://seiscan.io/address/0xD878509446bE2C601f0f032F501851001B159D6B#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x65eD61058cEB4895B7d62437BaCEA39b04f6D27B ](https://seiscan.io/address/0x65eD61058cEB4895B7d62437BaCEA39b04f6D27B#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :--------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xE75Fc5eA6e74B824954349Ca351eb4e671ADA53a ](https://soneium.blockscout.com/address/0xE75Fc5eA6e74B824954349Ca351eb4e671ADA53a?tab=contract) | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x68F9b666b984527A7c145Db4103Cc6d3171C797F ](https://soneium.blockscout.com/address/0x68F9b666b984527A7c145Db4103Cc6d3171C797F?tab=contract) | [morpho-org/morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho Chainlink Oracle V2 Factory | [ 0x669F1A4cE3127740eCdB3E36adFC5Df6Db1EA74b ](https://soneium.blockscout.com/address/0x669F1A4cE3127740eCdB3E36adFC5Df6Db1EA74b?tab=contract) | [morpho-org/morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0) | | MetaMorpho Factory V1.1 | [ 0x7026b436f294e560b3C26E731f5cac5992cA2B33 ](https://soneium.blockscout.com/address/0x7026b436f294e560b3C26E731f5cac5992cA2B33?tab=contract) | [morpho-org/metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x76f93A21573014Ab7d634D3204818922A234249e ](https://soneium.blockscout.com/address/0x76f93A21573014Ab7d634D3204818922A234249e?tab=contract) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xcBD0710425613d666C5Ffb4dE2eE73554F21c34B ](https://soneium.blockscout.com/address/0xcBD0710425613d666C5Ffb4dE2eE73554F21c34B?tab=contract) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xd6c916eB7542D0Ad3f18AEd0FCBD50C582cfa95f ](https://sonicscan.org/address/0xd6c916eB7542D0Ad3f18AEd0FCBD50C582cfa95f) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xDEfCf242226425f93d8DD0e314735C28517C473F ](https://sonicscan.org/address/0xDEfCf242226425f93d8DD0e314735C28517C473F) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x7DA59Fa482F1F49fADc486d8e47BADc506fEb86d ](https://sonicscan.org/address/0x7DA59Fa482F1F49fADc486d8e47BADc506fEb86d) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x0cE9e3512CB4df8ae7e265e62Fb9258dc14f12e8 ](https://sonicscan.org/address/0x0cE9e3512CB4df8ae7e265e62Fb9258dc14f12e8) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x6Cef2EDC70D87E8f1623f3096efF05d066E59B36 ](https://sonicscan.org/address/0x6Cef2EDC70D87E8f1623f3096efF05d066E59B36) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xc72129DA4CC808e955699111b8c22B22Ca8A10b8 ](https://sonicscan.org/address/0xc72129DA4CC808e955699111b8c22B22Ca8A10b8) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xa40103088A899514E3fe474cD3cc5bf811b1102e ](https://stablescan.xyz/address/0xa40103088A899514E3fe474cD3cc5bf811b1102e#code) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x41e846FC8108b8527C1D4EDB4c9564E56442940f ](https://stablescan.xyz/address/0x41e846FC8108b8527C1D4EDB4c9564E56442940f#code) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xF24C6eAB91e43EacE18a4e893a48565C09132505 ](https://stablescan.xyz/address/0xF24C6eAB91e43EacE18a4e893a48565C09132505#code) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xb4ae5673c48621189E2bEfBA96F31912032DD1AE ](https://stablescan.xyz/address/0xb4ae5673c48621189E2bEfBA96F31912032DD1AE#code) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xbCB063D4B6D479b209C186e462828CBACaC82DbE ](https://stablescan.xyz/address/0xbCB063D4B6D479b209C186e462828CBACaC82DbE#code) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x741A6604e974FeAF35a5FBb1416B3e01c33e5C0e ](https://stablescan.xyz/address/0x741A6604e974FeAF35a5FBb1416B3e01c33e5C0e#code) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x918B9F2E4B44E20c6423105BB6cCEB71473aD35c ](https://explorer.tac.build/address/0x918B9F2E4B44E20c6423105BB6cCEB71473aD35c?tab=contract) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x7E82b16496fA8CC04935528dA7F5A2C684A3C7A3 ](https://explorer.tac.build/address/0x7E82b16496fA8CC04935528dA7F5A2C684A3C7A3?tab=contract) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xbf10eD52dD60C60E901BF022c3675303ad4a56b1 ](https://explorer.tac.build/address/0xbf10eD52dD60C60E901BF022c3675303ad4a56b1?tab=contract) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xcDA78f4979d17Ec93052A84A12001fe0088AD734 ](https://explorer.tac.build/address/0xcDA78f4979d17Ec93052A84A12001fe0088AD734?tab=contract) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x414247afcf1fE3b94C617e7E3A7adB81D8D3208F ](https://explorer.tac.build/address/0x414247afcf1fE3b94C617e7E3A7adB81D8D3208F?tab=contract) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x5851C1e423A2F93aFb821834a63cA052D19ae4Ef ](https://explorer.tac.build/address/0x5851C1e423A2F93aFb821834a63cA052D19ae4Ef?tab=contract) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0x8f5ae9CddB9f68de460C77730b018Ae7E04a140A ](https://uniscan.xyz/address/0x8f5ae9CddB9f68de460C77730b018Ae7E04a140A) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x9a6061d51743B31D2c3Be75D83781Fa423f53F0E ](https://uniscan.xyz/address/0x9a6061d51743B31D2c3Be75D83781Fa423f53F0E) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0x43269546e1D586a1f7200a0AC07e26f9631f7539 ](https://uniscan.xyz/address/0x43269546e1D586a1f7200a0AC07e26f9631f7539) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xe9EdE3929F43a7062a007C3e8652e4ACa610Bdc0 ](https://uniscan.xyz/address/0xe9EdE3929F43a7062a007C3e8652e4ACa610Bdc0) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xB0c9a107fA17c779B3378210A7a593e88938C7C9 ](https://uniscan.xyz/address/0xB0c9a107fA17c779B3378210A7a593e88938C7C9) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xb04e4D3D59Ee47Ca9BA192707AF13A7D02969911 ](https://uniscan.xyz/address/0xb04e4D3D59Ee47Ca9BA192707AF13A7D02969911) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xE741BC7c34758b4caE05062794E8Ae24978AF432 ](https://worldscan.org/address/0xE741BC7c34758b4caE05062794E8Ae24978AF432) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x34E99D604751a72cF8d0CFDf87069292d82De472 ](https://worldscan.org/address/0x34E99D604751a72cF8d0CFDf87069292d82De472) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xd706690BA1Fe26b70c4AD89e60ff62cEB3A2eD02 ](https://worldscan.org/address/0xd706690BA1Fe26b70c4AD89e60ff62cEB3A2eD02) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0x4DBB3a642a2146d5413750Cca3647086D9ba5F12 ](https://worldscan.org/address/0x4DBB3a642a2146d5413750Cca3647086D9ba5F12) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0xef9889B4e443DEd35FA0Bd060f2104Cca94e6A43 ](https://worldscan.org/address/0xef9889B4e443DEd35FA0Bd060f2104Cca94e6A43) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0xe3cE2051a24e58DBFC0eFBe4c2d9e89c5eAe4695 ](https://worldscan.org/address/0xe3cE2051a24e58DBFC0eFBe4c2d9e89c5eAe4695) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xA902A365Fe10B4a94339B5A2Dc64F60c1486a5c8 ](https://explorer.zircuit.com/address/0xA902A365Fe10B4a94339B5A2Dc64F60c1486a5c8?activeTab=3) | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0xBADb1809ecF658F36e31CcC980F72de029e1cE46 ](https://explorer.zircuit.com/address/0xBADb1809ecF658F36e31CcC980F72de029e1cE46?activeTab=3) | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho ChainlinkOracleV2 Factory | [ 0xf8ddd4745dCB3c00eA5C6211E74A8c7328153cf9 ](https://explorer.zircuit.com/address/0xf8ddd4745dCB3c00eA5C6211E74A8c7328153cf9?activeTab=3) | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/releases/tag/v2.0.0) | | MetaMorpho Factory V1.1 | [ 0xd2c9068aD68c4c9F1A4fE1Ea650BdFE13DC5EaF1 ](https://explorer.zircuit.com/address/0xd2c9068aD68c4c9F1A4fE1Ea650BdFE13DC5EaF1?activeTab=3) | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Public Allocator | [ 0x7ac8F86Be7D7A15d9C95c07684004574647E0Af5 ](https://explorer.zircuit.com/address/0x7ac8F86Be7D7A15d9C95c07684004574647E0Af5?activeTab=3) | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0) | | PreLiquidation Factory | [ 0x09d7629E82DdD80890495672201fe5FE1f909B0b ](https://explorer.zircuit.com/address/0x09d7629E82DdD80890495672201fe5FE1f909B0b?activeTab=3) | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) | | Contract | Address | Source Code | | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb ](https://sepolia.basescan.org/address/0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb) | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x46415998764C29aB2a25CbeA6254146D50D22687 ](https://sepolia.basescan.org/address/0x46415998764C29aB2a25CbeA6254146D50D22687) | [morpho-org/morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho Chainlink Oracle V2 Factory | [ 0x2DC205F24BCb6B311E5cdf0745B0741648Aebd3d ](https://sepolia.basescan.org/address/0x2DC205F24BCb6B311E5cdf0745B0741648Aebd3d) | [morpho-org/morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0) | | MetaMorpho Factory V1.1 | [ 0x2c3FE6D71F8d54B063411Abb446B49f13725F784 ](https://sepolia.basescan.org/address/0x2c3FE6D71F8d54B063411Abb446B49f13725F784) | [morpho-org/metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | | Contract | Address | Source Code | | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- | | Morpho | [ 0xd011EE229E7459ba1ddd22631eF7bF528d424A14 ](https://sepolia.etherscan.io/address/0xd011EE229E7459ba1ddd22631eF7bF528d424A14) | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0) | | Adaptive Curve Irm | [ 0x8C5dDCD3F601c91D1BF51c8ec26066010ACAbA7c ](https://sepolia.etherscan.io/address/0x8C5dDCD3F601c91D1BF51c8ec26066010ACAbA7c) | [morpho-org/morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0) | | Morpho Chainlink Oracle V2 Factory | [ 0xa6c843fc53aAf6EF1d173C4710B26419667bF6CD ](https://sepolia.etherscan.io/address/0xa6c843fc53aAf6EF1d173C4710B26419667bF6CD) | [morpho-org/morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0) | | MetaMorpho Factory V1.1 | [ 0x98CbFE4053ad6778E0E3435943aC821f565D0b03 ](https://sepolia.etherscan.io/address/0x98CbFE4053ad6778E0E3435943aC821f565D0b03) | [morpho-org/metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) | ## Bundlers | 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) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xc13A3Ca3B0120EE6121d1E0ca9Da22fDD7ed28Cd ](https://abscan.org/address/0xc13A3Ca3B0120EE6121d1E0ca9Da22fDD7ed28Cd#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x3716AA06304D1bC70f553Da44904d13086A4a791 ](https://abscan.org/address/0x3716AA06304D1bC70f553Da44904d13086A4a791#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x1FA4431bC113D308beE1d46B0e98Cb805FB48C13 ](https://arbiscan.io/address/0x1FA4431bC113D308beE1d46B0e98Cb805FB48C13#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x9954aFB60BB5A222714c478ac86990F221788B88 ](https://arbiscan.io/address/0x9954aFB60BB5A222714c478ac86990F221788B88#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ParaswapAdapter | [ 0xAA5c30C1482c189cA0d56057D3ac4dD7Af1e4726 ](https://arbiscan.io/address/0xAA5c30C1482c189cA0d56057D3ac4dD7Af1e4726#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | AaveV3MigrationAdapter | [ 0x1923670d4F4eB7435d865E7477d28FEAFfA40C93 ](https://arbiscan.io/address/0x1923670d4F4eB7435d865E7477d28FEAFfA40C93#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | CompoundV3MigrationAdapter | [ 0x86Ca77a4a37A9CDBe9bBf4975F6d69531B96444b ](https://arbiscan.io/address/0x86Ca77a4a37A9CDBe9bBf4975F6d69531B96444b#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x708e04d46D82d8f1D0A70a3Aa0a780F27fcb3F92 ](https://snowtrace.io/address/0x708e04d46D82d8f1D0A70a3Aa0a780F27fcb3F92/contract/43114/code?chainid=43114) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x8BcC016Ab7334A16DCcbEE9AB3FD6E52fEb29E96 ](https://snowtrace.io/address/0x8BcC016Ab7334A16DCcbEE9AB3FD6E52fEb29E96/contract/43114/code?chainid=43114) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ParaswapAdapter | [ 0x0ED0478946E00ca8BCF65475E7c8dfACA4a30005 ](https://snowtrace.io/address/0x0ED0478946E00ca8BCF65475E7c8dfACA4a30005/contract/43114/code?chainid=43114) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :--------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x6BFd8137e702540E7A42B74178A4a49Ba43920C4 ](https://basescan.org/address/0x6BFd8137e702540E7A42B74178A4a49Ba43920C4) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xb98c948CFA24072e58935BC004a8A7b376AE746A ](https://basescan.org/address/0xb98c948CFA24072e58935BC004a8A7b376AE746A) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ERC20WrapperAdapter | [ 0xdeEf55F0A7366cC3Baf5E04313269389Fe17E9AE ](https://basescan.org/address/0xdeEf55F0A7366cC3Baf5E04313269389Fe17E9AE) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ParaswapAdapter | [ 0x6abE8ABd0275E5564ed1336F0243A52C32562F71 ](https://basescan.org/address/0x6abE8ABd0275E5564ed1336F0243A52C32562F71) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | CompoundV3MigrationAdapter | [ 0x85D4812Ef92c040d4270eD8547b6835e41FbbB70 ](https://basescan.org/address/0x85D4812Ef92c040d4270eD8547b6835e41FbbB70) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | AaveV3MigrationAdapter | [ 0xb27Aa2a964eAd5ed661D86974b37e4fB995b36f5 ](https://basescan.org/address/0xb27Aa2a964eAd5ed661D86974b37e4fB995b36f5) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ChainAgnosticBundlerV2 | [ 0x23055618898e202386e6c13955a58D3C68200BFB ](https://basescan.org/address/0x23055618898e202386e6c13955a58D3C68200BFB) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/releases/tag/v1.2.0) | | CompoundV2MigrationBundlerV2 | [ 0x123f3167a416cA19365dE03a65e0AF3532af7223 ](https://basescan.org/address/0x123f3167a416cA19365dE03a65e0AF3532af7223) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/releases/tag/v1.2.0) | | CompoundV3MigrationBundlerV2 | [ 0x1f8076e2EB6f10b12e6886f30D4909A91969F7dA ](https://basescan.org/address/0x1f8076e2EB6f10b12e6886f30D4909A91969F7dA) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/releases/tag/v1.2.0) | | AaveV3MigrationBundlerV2 | [ 0xcAe2929baBc60Be34818EaA5F40bF69265677108 ](https://basescan.org/address/0xcAe2929baBc60Be34818EaA5F40bF69265677108) | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/releases/tag/v1.2.0) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x82b3ea7558Fc383b949fa42Db7ee3eB101447B96 ](https://www.btrscan.com/address/0x82b3ea7558fc383b949fa42db7ee3eb101447b96?tab=Contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xa87F1422Df88B5f490203D71e2f8e7244843E62F ](https://www.btrscan.com/address/0xa87f1422df88b5f490203d71e2f8e7244843e62f?tab=Contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x16D40b9DF1497468195BFAfeb2718e486E15bF91 ](https://bscscan.com/address/0x16D40b9DF1497468195BFAfeb2718e486E15bF91#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x87c93660ECe6E68C6492EabBbBdbaafA102ae3a3 ](https://bscscan.com/address/0x87c93660ECe6E68C6492EabBbBdbaafA102ae3a3#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ParaswapAdapter | [ 0xBb12B012Fa31f7FE418236cAf625713Edc852F82 ](https://bscscan.com/address/0xBb12B012Fa31f7FE418236cAf625713Edc852F82#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x8d0d5c4c4EDf537971B689A7d406349d230b2E7A ](https://botanixscan.io/address/0x8d0d5c4c4EDf537971B689A7d406349d230b2E7A/contract/3637/code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x2Cf5D5A68D70979d97968A8894EB93706eeAe3f1 ](https://botanixscan.io/address/0x2Cf5D5A68D70979d97968A8894EB93706eeAe3f1/contract/3637/code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x88A4038BB4A14ecD7301c8Fb1f1e8732c4355D53 ](https://camp.cloud.blockscout.com/address/0x88A4038BB4A14ecD7301c8Fb1f1e8732c4355D53?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x29dcA26F9862CFb8064163ddc3401aaB4D4D05c6 ](https://camp.cloud.blockscout.com/address/0x29dcA26F9862CFb8064163ddc3401aaB4D4D05c6?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :-------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xbd142f98f847c170D51d8B23e5FEBc51FC9a67D9 ](https://celoscan.io/address/0xbd142f98f847c170D51d8B23e5FEBc51FC9a67D9#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x3E7544a07157D03a49359eE89f2fCac9a6467230 ](https://celoscan.io/address/0x3E7544a07157D03a49359eE89f2fCac9a6467230#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xe7C7271AfE4E49C12c66a0B8A9B774ed8b1640C8 ](https://explorer.mainnet.citrea.xyz/address/0xe7C7271AfE4E49C12c66a0B8A9B774ed8b1640C8?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x722B0e321544042741B3E45F200FBEDAc20529dC ](https://explorer.mainnet.citrea.xyz/address/0x722B0e321544042741B3E45F200FBEDAc20529dC?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x086889F9bdE8349512dD77088A7114E6C1c42Af7 ](https://cornscan.io/address/0x086889F9bdE8349512dD77088A7114E6C1c42Af7) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x464a402244bCDdc0c2091D5193E8ffdb2be54Ca9 ](https://cornscan.io/address/0x464a402244bCDdc0c2091D5193E8ffdb2be54Ca9) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xb1c59fE6A0DCE25b804F6113C441Bf4F3a4Ab6bC ](https://explorer.cronos.org/address/0xb1c59fE6A0DCE25b804F6113C441Bf4F3a4Ab6bC#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xCa470cBBc3de56FDe336466f2107cC969174d513 ](https://explorer.cronos.org/address/0xCa470cBBc3de56FDe336466f2107cC969174d513#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x69dc8086191437b55775b79C730BB3876397e7D1 ](https://explorer.etherlink.com/address/0x69dc8086191437b55775b79C730BB3876397e7D1?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xEabdAC78A7f0a9B3dF0e23D69A5a5fF7f580a910 ](https://explorer.etherlink.com/address/0xEabdAC78A7f0a9B3dF0e23D69A5a5fF7f580a910?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :---------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xA7a414823Ef0F8CFb2c4f67f2F445DA940641d91 ](https://fraxscan.com/address/0xA7a414823Ef0F8CFb2c4f67f2F445DA940641d91) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x228dDF333DDf6D1895dA1dE8a846EDD27F1284eD ](https://fraxscan.com/address/0x228dDF333DDf6D1895dA1dE8a846EDD27F1284eD) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :---------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x2AC3ea771547926D4714078e807eFbeF70D0997f ](https://gnosisscan.io/address/0x2AC3ea771547926D4714078e807eFbeF70D0997f#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x832625F5C0aAD4bc14d39291156D37898a40973b ](https://gnosisscan.io/address/0x832625F5C0aAD4bc14d39291156D37898a40973b#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x8eDa6E01a20E3Cd90B3B2AF6F790cB8FADEf3Ea8 ](https://explorer.hemi.xyz/address/0x8eDa6E01a20E3Cd90B3B2AF6F790cB8FADEf3Ea8) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x9623090C3943ad63F7d794378273610Dd0deeFD4 ](https://explorer.hemi.xyz/address/0x9623090C3943ad63F7d794378273610Dd0deeFD4) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xa3F50477AfA601C771874260A3B34B40e244Fa0e ](https://hyperevmscan.io/address/0xa3F50477AfA601C771874260A3B34B40e244Fa0e#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xD7F48aDE56613E8605863832B7B8A1985B934aE4 ](https://hyperevmscan.io/address/0xD7F48aDE56613E8605863832B7B8A1985B934aE4#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x7db0F1E2bf1f47ec82220090F388d75D8B9BB6BC ](https://explorer.inkonchain.com/address/0x7db0F1E2bf1f47ec82220090F388d75D8B9BB6BC) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xB8B2aDdCDe1cdC94AaE18a0F8A19df03D8683610 ](https://explorer.inkonchain.com/address/0xB8B2aDdCDe1cdC94AaE18a0F8A19df03D8683610) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :----------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xA8C5e23C9C0DF2b6fF716486c6bBEBB6661548C8 ](https://katanascan.com/address/0xA8C5e23C9C0DF2b6fF716486c6bBEBB6661548C8#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x916Aa175C36E845db45fF6DDB886AE437d403B61 ](https://katanascan.com/address/0x916Aa175C36E845db45fF6DDB886AE437d403B61#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x1Ee8Ec299E8014760D50A4E3CfC3b44Cc2242625 ](https://lineascan.build/address/0x1Ee8Ec299E8014760D50A4E3CfC3b44Cc2242625#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x454dAb6ce9891245696b239b4845a1cDC268255d ](https://lineascan.build/address/0x454dAb6ce9891245696b239b4845a1cDC268255d#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xD96E5e02580C4EAfE15B5537b25eE3dEe5861e00 ](https://blockscout.lisk.com/address/0xD96E5e02580C4EAfE15B5537b25eE3dEe5861e00?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x76cFE4BF840C7b461772fE7CDE399f58c4173584 ](https://blockscout.lisk.com/address/0x76cFE4BF840C7b461772fE7CDE399f58c4173584?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xFEA0edFa081C8D5960Ec9Bf6684981dB1834305d ](https://explorer.mode.network/address/0xFEA0edFa081C8D5960Ec9Bf6684981dB1834305d) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xF53925b95Cc409447066cd5c1A7756084b2Ee0a4 ](https://explorer.mode.network/address/0xF53925b95Cc409447066cd5c1A7756084b2Ee0a4) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [0x82b684483e844422FD339df0b67b3B111F02c66E](https://monadscan.com/address/0x82b684483e844422FD339df0b67b3B111F02c66E#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [0x725AB8CAd931BCb80Fdbf10955a806765cCe00e5](https://monadscan.com/address/0x725AB8CAd931BCb80Fdbf10955a806765cCe00e5#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xFBCd3C258feB131D8E038F2A3a670A7bE0507C05 ](https://optimistic.etherscan.io/address/0xFBCd3C258feB131D8E038F2A3a670A7bE0507C05) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x79481C87f24A3C4332442A2E9faaf675e5F141f0 ](https://optimistic.etherscan.io/address/0x79481C87f24A3C4332442A2E9faaf675e5F141f0) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ParaswapAdapter | [ 0x31F539f4Ed14fA1fd18781e93f6739249692aDC5 ](https://optimistic.etherscan.io/address/0x31F539f4Ed14fA1fd18781e93f6739249692aDC5) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xeC6f72cF30fb5d3D0f9Bea8509B61902Cf3B1E45 ](https://plasmascan.to/address/0xeC6f72cF30fb5d3D0f9Bea8509B61902Cf3B1E45/contract/9745/code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x6A7389f9D4fD199254479d6735aAd7aa5D4Db0cE ](https://plasmascan.to/address/0x6A7389f9D4fD199254479d6735aAd7aa5D4Db0cE/contract/9745/code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x5437C8788f4CFbaA55be6FBf30379bc7dd7f69C3 ](https://explorer.plume.org/address/0x5437C8788f4CFbaA55be6FBf30379bc7dd7f69C3?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x65ff368930Cb7eB4CA5C5eBC58bb69E6Ed198BA5 ](https://explorer.plume.org/address/0x65ff368930Cb7eB4CA5C5eBC58bb69E6Ed198BA5?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x2d9C3A9E67c966C711208cc78b34fB9E9f8db589 ](https://polygonscan.com/address/0x2d9C3A9E67c966C711208cc78b34fB9E9f8db589) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xB261B51938A9767406ef83bbFbaAFE16691b7047 ](https://polygonscan.com/address/0xB261B51938A9767406ef83bbFbaAFE16691b7047) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ParaswapAdapter | [ 0x5F2617F12D1fDd1e43e72Cb80C92dFcE8124Db8d ](https://polygonscan.com/address/0x5F2617F12D1fDd1e43e72Cb80C92dFcE8124Db8d) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x60F9159d4dCd724e743212416FD57d8aC0B60768 ](https://scrollscan.com/address/0x60F9159d4dCd724e743212416FD57d8aC0B60768) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xD2780fae0869cDc06EE202152304A39653361525 ](https://scrollscan.com/address/0xD2780fae0869cDc06EE202152304A39653361525) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xF9457356F18A3349Bb317Ac144c3Bcc62e5761aD ](https://seiscan.io/address/0xF9457356F18A3349Bb317Ac144c3Bcc62e5761aD#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x02e0e71e145f254820B9D89c9E6068f08256F601 ](https://seiscan.io/address/0x02e0e71e145f254820B9D89c9E6068f08256F601#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x461378B79d400c963F48F57b3a99416bc3C5c6a6 ](https://soneium.blockscout.com/address/0x461378B79d400c963F48F57b3a99416bc3C5c6a6?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xA47EeDE3Aac741B830E394B2e291f6774BD8bb48 ](https://soneium.blockscout.com/address/0xA47EeDE3Aac741B830E394B2e291f6774BD8bb48?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :----------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xB06F1Ad8c908b958E596c42973f67F2f1d9a9afF ](https://sonicscan.org/address/0xB06F1Ad8c908b958E596c42973f67F2f1d9a9afF) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x31D5aee8D75EEab548cfA0d11C4f9843a5201eaf ](https://sonicscan.org/address/0x31D5aee8D75EEab548cfA0d11C4f9843a5201eaf) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0xA0bb114F927dF03d9a1a639b9c71F71B0FaFDf1B ](https://stablescan.xyz/address/0xA0bb114F927dF03d9a1a639b9c71F71B0FaFDf1B#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x59b1F4376a81e39c466A0A218447E4D36f39A96b ](https://stablescan.xyz/address/0x59b1F4376a81e39c466A0A218447E4D36f39A96b#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x84b189823D0f84c36728Bb3335dD8C833564e72f ](https://explorer.tac.build/address/0x84b189823D0f84c36728Bb3335dD8C833564e72f?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x6D94E7dCA6d8FAE2CF954633C2Cf9c286258E0af ](https://explorer.tac.build/address/0x6D94E7dCA6d8FAE2CF954633C2Cf9c286258E0af?tab=contract) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x7DD85759182495AF7F6757DA75036d24A9B58bc3 ](https://uniscan.xyz/address/0x7dd85759182495af7f6757da75036d24a9b58bc3#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0xC11329d19C2275c9E759867e879ECFcEeD7e30A0 ](https://uniscan.xyz/address/0xC11329d19C2275c9E759867e879ECFcEeD7e30A0#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | ParaswapAdapter | [ 0xAa870Da2a9F611A3A53d0D2AEe5664B3700a59c9 ](https://uniscan.xyz/address/0xAa870Da2a9F611A3A53d0D2AEe5664B3700a59c9#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | CompoundV3MigrationAdapter | [ 0x617f8d7885CCE689115Af04576F7cB6F2534fA9a ](https://uniscan.xyz/address/0x617f8d7885CCE689115Af04576F7cB6F2534fA9a#code) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :----------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x3D07BF2FFb23248034bF704F3a4786F1ffE2a448 ](https://worldscan.org/address/0x3D07BF2FFb23248034bF704F3a4786F1ffE2a448) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x30fa9A3cF56931ACEea42E28D35519a97D90aA67 ](https://worldscan.org/address/0x30fa9A3cF56931ACEea42E28D35519a97D90aA67) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | Contract | Address | Source Code | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- | | Bundler3 | [ 0x04C17BA8BAe185e655086e7f35357F7c3C70Dc53 ](https://explorer.zircuit.com/address/0x04C17BA8BAe185e655086e7f35357F7c3C70Dc53?activeTab=3) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | | GeneralAdapter1 | [ 0x2d09A9A5d41863314571E3c902D1b9DDfe6cAf9e ](https://explorer.zircuit.com/address/0x2d09A9A5d41863314571E3c902D1b9DDfe6cAf9e?activeTab=3) | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) | ## Rewards | 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) | | Contract | Address | Source Code | | :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x7b792Ef7e91fbc78Ef482E3bBB52193A73367fbf ](https://arbiscan.io/address/0x7b792Ef7e91fbc78Ef482E3bBB52193A73367fbf) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :---------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x7276454fc1cf9C408deeed722fd6b5E7A4CA25D8 ](https://basescan.org/address/0x7276454fc1cf9C408deeed722fd6b5E7A4CA25D8) | [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) | [ 0x5400dBb270c956E8985184335A1C62AcA6Ce1333 ](https://basescan.org/address/0x5400dBb270c956E8985184335A1C62AcA6Ce1333) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UniversalRewardsDistributor.sol) | | Contract | Address | Source Code | | :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0xaBC2CBa3C8E265d63C04BF5fA41EE105d3D85ae3 ](https://cornscan.io/address/0xaBC2CBa3C8E265d63C04BF5fA41EE105d3D85ae3) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :---------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0xeb8AA0388b03c74FA48E78f56543e7b8d1965eaf ](https://fraxscan.com/address/0xeb8AA0388b03c74FA48E78f56543e7b8d1965eaf) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x184e0A5a6e52b30B7139D2C02FEE11516B8a8562 ](https://explorer.hemi.xyz/address/0x184e0A5a6e52b30B7139D2C02FEE11516B8a8562) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x2884732D25b97090CaB59d0d2B78cD9c85A83411 ](https://explorer.inkonchain.com/address/0x2884732D25b97090CaB59d0d2B78cD9c85A83411) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0xB605Ae0D112c117638592ec4F78148e6322a7b7b ](https://katanascan.com/address/0xB605Ae0D112c117638592ec4F78148e6322a7b7b#code) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0xC3da6acf214e322Cc0E07D1582c9a546fB4338da ](https://blockscout.lisk.com/address/0xC3da6acf214e322Cc0E07D1582c9a546fB4338da?tab=contract) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x063A8f498B4A1423c62Be360007B7d9d0C60c481 ](https://explorer.mode.network/address/0x063A8f498B4A1423c62Be360007B7d9d0C60c481) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0xe41AEcB4570A7B68d15a4Fb0a03ACEe421A21498 ](https://optimistic.etherscan.io/address/0xe41AEcB4570A7B68d15a4Fb0a03ACEe421A21498) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x92428E3906a1e7F4ecEBaF88949f76a6FB32cC78 ](https://explorer.plume.org/address/0x92428E3906a1e7F4ecEBaF88949f76a6FB32cC78?tab=contract) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0xfc5BE756236Feaf4297d3279Bf6532bf100f0AC9 ](https://polygonscan.com/address/0xfc5BE756236Feaf4297d3279Bf6532bf100f0AC9) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x78F44e1ed61210952B6e23d09C930BfA64a359c1 ](https://scrollscan.com/address/0x78F44e1ed61210952B6e23d09C930BfA64a359c1) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x90D441D6B232Eb30Edb74256995fB9bcb59AD63a ](https://soneium.blockscout.com/address/0x90D441D6B232Eb30Edb74256995fB9bcb59AD63a?tab=contract) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0xdFA21A9189425187fF6e44D7ebeA19F64E8836ee ](https://sonicscan.org/address/0xdFA21A9189425187fF6e44D7ebeA19F64E8836ee) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x72cc7A247f389D327bC898420837477fb4a57Cc4 ](https://uniscan.xyz/address/0x72cc7A247f389D327bC898420837477fb4a57Cc4) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | | Contract | Address | Source Code | | :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Universal Rewards Distributor Factory | [ 0x02C895e99Db5348284B743512CF32a016f76286B ](https://worldscan.org/address/0x02C895e99Db5348284B743512CF32a016f76286B) | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor/blob/v1.0.0/src/UrdFactory.sol) | ## MORPHO Token The MORPHO token has 18 decimals. | 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) | | Contract | Address | Source Code | | :------- | :---------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------- | | MORPHO | [ 0xBAa5CC21fd487B8Fcc2F632f3F4E8D37262a0842 ](https://basescan.org/address/0xBAa5CC21fd487B8Fcc2F632f3F4E8D37262a0842) | [morpho-org/morpho-token](https://github.com/morpho-org/morpho-token) | | Contract | Address | Source Code | | :------------------------- | :-----------------------------------------------------------------------------------------------------------------------| :---------------------------------------------------------------------------------- | | MORPHO | [ 0x40BD670A58238e6E230c430BBb5cE6ec0d40df48 ](https://arbiscan.io/address/0x40bd670a58238e6e230c430bbb5ce6ec0d40df48) | [morpho-org/morpho-token-l0](https://github.com/morpho-org/morpho-token-l0) | | MorphoMintBurnOFTAdapter | [ 0xFc3329363cd51adBBaa52E389bEE389981ccaAE0 ](https://arbiscan.io/address/0xFc3329363cd51adBBaa52E389bEE389981ccaAE0) | [morpho-org/morpho-token-l0](https://github.com/morpho-org/morpho-token-l0) | | Contract | Address | Source Code | | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | MORPHO | [ 0x1e5eFCA3D0dB2c6d5C67a4491845c43253eB9e4e ](https://explorer.katanarpc.com/token/0x1e5eFCA3D0dB2c6d5C67a4491845c43253eB9e4e?tab=contract_code) | [agglayer/TokenWrappedBridgeUpgradeable](https://github.com/agglayer/agglayer-contracts/blob/feature/update-sovereign-L2/contracts/v2/lib/TokenWrappedBridgeUpgradeable.sol) | ## [Morpho Apps](https://docs.morpho.org/get-started/resources/app-ecosystem/) This section details the critical applications developed by Morpho Association for effective vault management and ecosystem participation. ## Consumer ### Main App - [app.morpho.org](https://app.morpho.org/) **Purpose:** Interface for both lenders interacting with Morpho vaults and Borrowers interacting with Morpho Markets. **Key Features:** - View listed 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** #### If the main App is not accessible If you don't want to use the Main Morpho app (https://app.morpho.org/) or if you are not able to access it, it is always possible to interact with Morpho via alternative apps, the [Fallback app](/get-started/resources/app-ecosystem/#fallback-app---fallbackmorphoorg) or at contract level via explorers. #### Morpho Warnings Morpho has a warning system built within the Morpho API. These warnings allow to surface potential risk that could impact markets or vaults on Morpho. Some of this warnings are used and featured in the main Morpho app. The tables below explicitly explain some of the reasons why warnings may appear: ##### Market V1 Warnings | Warning Type | Level | Criteria / Threshold | Notes | |------------------------------------|----------|----------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **bad_debt_unrealized** | 🔴 RED | Unrealized bad debt / total supply assets > 5% (500 bps) | Detects accumulating bad debt | | **not_whitelisted** | 🟡 YELLOW | Market not listed by a listed vault | - | | **unrecognized_loan_asset** | 🔴 RED | Loan asset not in Morpho token database | Asset are added in the Morpho database for aesthetic purpose (logo, $ value display). See process [here](/get-started/resources/app-ecosystem#tokens-checks) | | **unrecognized_collateral_asset** | 🔴 RED | Collateral asset not in Morpho token database | Asset are added in the Morpho database for aesthetic purpose (logo, $ value display). See process [here](/get-started/resources/app-ecosystem#tokens-checks) Exception: listed Vault V1 allowed. | | **incorrect_oracle_configuration** | 🔴 RED | Scale factor incorrect or negative exponent | For Morpho Chainlink Oracle V1/V2 | ##### Vault V1 Warnings | Warning Type | Level | Criteria / Threshold | Notes | |--------------------------------|----------|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| | **invalid_name** | 🔴 RED | Contains "morpho" OR SQL injection | Brand protection & security | | **invalid_symbol** | 🔴 RED | Contains "morpho" OR SQL injection | Brand protection & security | | **short_timelock** | 🔴 RED | Timelock < 3 days | Governance security | | **not_whitelisted** | 🟡 YELLOW | Vault not in listed curators database | - | | **unrecognized_deposit_asset** | 🔴 RED | Deposit asset not listed | Asset are added in the Morpho database for aesthetic purpose (logo, $ value display). See process [here](/get-started/resources/app-ecosystem#tokens-checks) | ##### Vault V2 Warnings | Warning Type | Level | Criteria / Threshold | Notes | |------------------------|----------|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| | **not_whitelisted** | 🟡 YELLOW | Vault not in listed curators database | - | | **unrecognized_asset** | 🔴 RED | Deposit asset not listed | Asset are added in the Morpho database for aesthetic purpose (logo, $ value display). See process [here](/get-started/resources/app-ecosystem#tokens-checks) | | **timelock** | 🔴 RED | Functions without minimum timelock | See timelock requirements below | ##### Vault V2 Timelock Requirements | Function | Minimum Timelock | Purpose | |-----------------------------|------------------|------------------------------------------| | `setReceiveSharesGate` | **7 days** | Controls who can receive vault shares | | `setSendSharesGate` | **7 days** | Controls who can send vault shares | | `setReceiveAssetsGate` | **7 days** | Controls deposit permissions | | `setAdapterRegistry` | **7 days** | Updates adapter registry address | | `increaseTimelock` | **7 days** | Increases timelock duration | | `abdicate` | **7 days** | Removes timelock requirement permanently | | `removeAdapter` | **7 days** | Removes approved adapter | | `addAdapter` | **3 days** | Adds new approved adapter | | `increaseRelativeCap` | **3 days** | Increases relative allocation cap | | `setForceDeallocatePenalty` | **3 days** | Sets penalty for forced deallocation | | `increaseAbsoluteCap` | **3 days** | Increases absolute allocation cap | Refer to this [risk documentation](/learn/resources/risks/) to be sure you understand all the risks. #### Tokens checks Tokens are added to the Morpho database to enable their use on the Morpho apps. Before being added to the token database [here](https://github.com/morpho-org/morpho-blue-api-metadata/blob/main/data/tokens.json), checks are performed to ensure compatibility. Here are the checks performed: - **Contract Existence** - A valid smart contract exists at the provided address - **ERC-20 Compliance** - The contract implements the core ERC-20 interface (name, symbol, decimals) - **Non-zero total supply** - The token’s total supply is greater than 0 - **DefiLlama Price Data** - The token has a recent price data available on DeFiLlama - **Logo Availability** - Token logo exists in Morpho database - **Not already listed** - The token is not already listed on the chain #### Policy ##### Asset blocking policy The Morpho protocol is a self-executing, permissionless, decentralized series of smart contracts that cannot be changed by anyone except the governance for given parameters. Morpho Association maintains one of many ways to interact with the Protocol (the Morpho Interface for instance), and as a non-profit association based in France is subject to certain laws and regulations. As such, there may be certain circumstances under which Morpho Association blocks access to certain markets and vaults through our the interface provided. ##### Criteria for Restricting Access on Morpho Association Interfaces 1. Morpho Association will block some components of the Protocol for the following reasons: 1. Risks to users. Morpho Association believes there are technical, fraud, or other risks that could significantly affect user safety. 2. Legal and regulatory requirements. 3. Fraud allegations. 2. Morpho Association *will* block individual or smart contract addresses that are subject to U.S. government sanctions or associated with certain types of illegal activity. 3. Morpho Association *may* block individual or smart contract addresses for any other reason at their discretion. For example, Morpho Association might have reason to believe that an address is associated with fraud, theft, or market manipulation, or that a smart contract has unacceptable security vulnerabilities. #### Additional disclosures Interface Warnings are created using information from third-party data providers. Morpho Association does not guarantee their accuracy and makes no representations or warranties about their relevance or currentness. The Morpho Protocol operates on a permissionless and decentralized basis, allowing Markets and Vaults to be established and administered by any third-party individual or entity. Any information provided by the Morpho Association on Vaults, Markets or any of their parameters does not constitute an endorsement of the Markets or Vaults and is provided solely for informational purposes. It does not represent an endorsement, recommendation, or any form of advice on how to engage with or utilize the Morpho Protocol. Morpho Association Token Lists and Interface Warnings are not investment advice and should not be construed as such. Morpho Association strongly advise that before engaging in any financial, legal, technical, or other significant decisions related to the Morpho Protocol, you perform your own research (including, but not limited to, an analysis of the market or vault's structure, the assets involved, the parties responsible for its creation and management, and the potential risks and rewards associated with participation) and consult with an independent professional who is licensed and qualified in the relevant field. Such advice is crucial to ensure that your decisions are well-informed and take into account the specific nuances and complexities of your situation. #### Slippage Considerations When interacting with [Morpho Markets](/learn/concepts/market/) and [Morpho Vaults](/learn/concepts/vault/) through the Morpho Interface, slippage protection is implemented to safeguard users against unexpected price movements between transaction submission and execution. Understanding how slippage is handled is crucial for both users and developers. ##### Types of Slippage Protection 1. **Token Wrapping Operations** - Applied to: stETH → wstETH conversions, ERC4626 deposits (including Morpho Vaults deposits) - Fixed maximum slippage: 3 basis points (0.03%) 2. **Market Operations** - Formula: ```math e^{4 \cdot r_{\text{target}} \cdot d} - 1 ``` - Where: - **r_target** is the target interest rate - **d** is the expected transaction duration (15 minutes for EOA, 45 minutes for Safe) 3. **Vault Operations** - Formula: ```math \left( 1 + r_{apy} \right)^{\frac{d}{yearInSeconds}} - 1 ``` - Where: - **r_apy** is the Annual Percentage Yield - **d** is the expected transaction duration (15 minutes for EOA, 45 minutes for Safe) - **yearInSeconds** is the number of seconds in a year ##### Shares Conversion and Slippage In operations involving asset-to-share conversions (e.g. borrowing, repaying, Morpho Vaults deposits/withdrawals), the interface accounts for worst-case slippage scenarios. This is particularly important in the following cases: - **Asset-Based Operations**: Borrowing, partial repayments, Morpho Vaults deposits/partial withdrawals, supplying/withdrawing collateral - **Shares-Based Operations**: Maximum repayments, Morpho Vaults deposits in rehypothecation, maximum Morpho Vaults withdrawals **Note**: Slippage can significantly impact transactions combining asset-based and shares-based operations for the same token. ##### Special Considerations for Morpho Vaults Morpho Vaults ERC4626-compliant tokens are treated differently depending on the context: - As assets when supplied as collateral - As shares when supplied as deposits In rehypothecation, they are treated as shares during Morpho Vaults Deposit and as assets during Supply Collateral. #### At which level is it implemented? These slippage calculations are automatically applied in relevant `bundlerActions` to protect users from adverse price movements during transaction processing. ### Fallback App - [fallback.morpho.org](https://fallback.morpho.org/) **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**
**Deploy your own independent Fallback App** #### Why deploy your own? The Morpho Fallback App can be self-hosted, giving you: - **Independence**: Access to your funds even if app.morpho.org is unavailable - **Censorship resistance**: No reliance on any single provider - **Version control**: Stay on a trusted version you've reviewed The app is fully static (just files, no server needed) and connects directly to public blockchain nodes. -----------------|-----------------------------------| | DWeb (Recommended) | `https://YOUR_CID.ipfs.dweb.link` | | IPFS.io | `https://ipfs.io/ipfs/YOUR_CID` | | Web3.Storage | `https://YOUR_CID.ipfs.w3s.link` | --- #### Updating Your Deployment Since IPFS content is immutable (never changes), updating means creating a new deployment: 1. From your morpho-lite-apps folder, get the latest code from the [morpho-lite-apps repository](https://github.com/morpho-org/morpho-lite-apps): `git pull origin main` 2. Rebuild 3. Upload the new `dist/` folder to Pinata (or your chosen host) 4. Use your new CID Your old CID continues working forever, so you can stay on a known version or upgrade when ready. --- #### Alternative: Use a Community Deployment If you prefer not to build your own, you can use an existing community-hosted version. The official [fallback.morpho.org](https://fallback.morpho.org/) app displays available IPFS CIDs that you can access directly through any gateway. A community deployment is also available at: **https://bafybeihdvi6wgow3wk7mztnldoyyg5m2pmudslafry2ckelcalm2pw3wiq.ipfs.dweb.link** Note: When using third-party deployments, you trust that the deployer built from the official source without modifications. --- #### Security Best Practices - **Verify the source**: Only build from the official repository ([morpho-lite-apps repository](https://github.com/morpho-org/morpho-lite-apps)) - **Review before trusting**: Check the code before deploying, especially if you're security-conscious - **Use HTTPS gateways**: Always access via `https://` to prevent tampering - **Safe by design**: The app never asks for your private keys - it only requests transaction signatures through your wallet
### Rewards - [campaigns.morpho.org](https://campaigns.morpho.org/) **Purpose:** Monitor reward campaigns on Morpho, track rewards linked to a specific address, and claim rewards. Merkl is an application developed by a third party allowing to interact with rewards distributed on Morpho. The Morpho Association does not endorse or guarantee its functionality. Use at your own discretion. ## Prime ### Curator App V2 - [curator.morpho.org](https://curator.morpho.org/vaults) **Purpose:** Delivers specialized tools for Morpho Vault V2 curators to manage vault operations. **Key Features:** - Create and deploy new vaults V2 - Curate adapter listings and parameters - Configure vault settings and permissions - Set allocation caps, strategies and timelocks **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. See curate section [here](/curate/tutorials-v2/vault-creation/). ### Curator App V1 - [curator-v1.morpho.org](https://curator-v1.morpho.org/) **Purpose:** Delivers specialized tools for Morpho Vault V1 curators to manage vault operations. **Key Features:** - Create and deploy new vaults V1 - Curate market listings and parameters - Configure vault settings and permissions - Set allocation caps, strategies and timelocks **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. See curate section [here](/curate/tutorials-v1/vault-creation/). ## Other ### Oracle Portal - [oracles.morpho.dev](https://oracles.morpho.dev/) **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/) **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. ## [Audits - Security Reviews](https://docs.morpho.org/get-started/resources/audits/) 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/). The Morpho apps and smart contracts have been audited extensively by a wide range of security firms, with every new app and feature undergoing audits before release. The full list of audits is available below. | Auditors | Scope | Date | Report | | :--------------------------------------------------------------------------------------- | :--------------------------------------------- | :----------------- | :----------------------------------------------------------------------------------------------------------- | | [Certora](https://www.certora.com/) | Vaults V2 - MarketV1AdapterV2 | 2025-15-12 | [certora-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Vaults V2 - MarketV1AdapterV2 | 2025-04-12 | [spearbit-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [Blackthorn](https://www.blackthorn.xyz/) | Vaults V2 - MarketV1AdapterV2 | 2025-04-12 | [blackthorn-report](https://github.com/morpho-org/vault-v2/tree/main/audits) | | [Certora](https://www.certora.com/) | Vaults V2 - MarketV1AdapterV2 Registry | 2025-04-12 | [certora-report](https://github.com/morpho-org/vault-v2-adapter-registries/tree/main/audits) | | [Spearbit](https://spearbit.com/) | Vaults V2 - Adapters Registry | 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) | | [Omniscia](https://omniscia.io/) | MORPHO Token | 2022-06-15 | [omniscia-report](https://omniscia.io/morpho-specialized-token/) | | [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 Contracts](https://docs.morpho.org/get-started/resources/contracts/) | **Category** | **Contract** | **Github Repositories** | **Specs** | | ------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | **Morpho Core** | Morpho Market V1 | [morpho-blue](https://github.com/morpho-org/morpho-blue) | [spec](/get-started/resources/contracts/morpho/) | | | Interest Rate Model | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm) | [spec](/get-started/resources/contracts/irm/) | | | Oracle | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles) | [spec](/get-started/resources/contracts/oracles/) | | | Pre-Liquidation | [pre-liquidation](https://github.com/morpho-org/pre-liquidation) | [spec](/get-started/resources/contracts/morpho/#liquidation) | | **Morpho Vaults V1** | Vaults V1.1 | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1) | [spec](/get-started/resources/contracts/morpho-vaults/) | | | Vaults V1.0 | [metamorpho](https://github.com/morpho-org/metamorpho) | [spec](/get-started/resources/contracts/morpho-vaults/) | | **Morpho Vaults V2** | Vaults V2 | [vault-v2](https://github.com/morpho-org/vault-v2) | [spec](/get-started/resources/contracts/morpho-vaults-v2/) | | **Public Allocator** | Public-Allocator | [public-allocator](https://github.com/morpho-org/public-allocator) | [spec](/get-started/resources/contracts/public-allocator/) | | **Bundlers** | Bundler3 | [bundler3](https://github.com/morpho-org/bundler3) | [spec](/get-started/resources/contracts/bundlers/) | | | Bundler2 | [morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers) | [spec](/get-started/resources/contracts/bundlers/) | | **Rewards** | Universal-Rewards-Distributor | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor) | [spec](/get-started/resources/contracts/rewards/) | ## [Bundler3 & Bundler2](https://docs.morpho.org/get-started/resources/contracts/bundlers/) [← Back to contracts](/get-started/resources/contracts/) # Bundler3 & Bundler2 ## Code ## Bundler3 Structure Bundler3 is a call dispatcher that enables atomic execution of arbitrary calls with enhanced features for authorization management and callback handling. 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 Each Bundler is a domain-specific abstract layer of contract that implements some functions that can be bundled in a single call by EOAs to a single contract. 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)). # Permit 2 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). ## [Interest Rate Models](https://docs.morpho.org/get-started/resources/contracts/irm/) [← Back to contracts](/get-started/resources/contracts/) # Interest Rate Models ## Code 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 ### borrowRate ```solidity function borrowRate(MarketParams memory marketParams, Market memory market) external returns (uint256); ``` Returns the borrow rate of the market `marketParams`. #### Parameters: | Name | Type | Description | | :------------- | :------------------------------------------------------------------------ | :------------------------------------- | | `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The MarketParams struct of the market. | | `market` | [Market](/get-started/resources/contracts/morpho/#market-struct) | The Market struct of the market. | #### Return values: | Name | Type | Description | | :----------- | :------ | :----------------------------- | | `borrowRate` | uint256 | The borrow rate of the market. | ## View Function ### borrowRateView: ```solidity 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: | Name | Type | Description | | :------------- | :------------------------------------------------------------------------ | :------------------------------------- | | `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The MarketParams struct of the market. | | `market` | [Market](/get-started/resources/contracts/morpho/#market-struct) | The Market struct of the market. | #### Return values: | Name | Type | Description | | :----------- | :------ | :----------------------------- | | `borrowRate` | uint256 | The borrow rate of the market. | Make sure the input parameters correspond to the last time the market was updated (check `lastUpdate`) and apply the returned borrow rate as is applied in Morpho over the period between the market's `lastUpdate` and the query's block timestamp. ## 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 The Borrow APY is calculated using the following formula: ```math \text{borrowAPY} = \left(e^{\left(\text{borrowRate} \times \text{secondsPerYear}\right)} - 1\right) ``` 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 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](/curate/concepts/fee). ```math \text{supplyAPY} = \text{borrowAPY} \times \text{utilization} \times (1 - \text{fee}) ``` Where: - `fee` is the fee of the market, to be activated by the governance, on a per-market basis, - `utilization` is calculated as: ```math \text{utilization} = \frac{\text{totalBorrowAssets}}{\text{totalSupplyAssets}} ``` # AdaptiveCurveIRM Here is a video that shows how the Adaptive Curve IRM works: ## 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 This mechanism is similar to the interest rate curve used in traditional lending pools. The curve is characterized by two parameters: ```math r_{90\%} ``` which is the target rate at utilization target ```math u\_{target}=0.9 ``` and ```math c=4 ``` a fixed parameter that determines the steepness of the curve above and below the utilization target. 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 ```math r\_{90\%} ``` - if utilization is 100%, the rate is ```math 4*r\_{90\%} ``` (APR) The aim of the Curve Mechanism is to manage short-term utilization changes. ## 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 ```math r\_{90\%} ``` over time: - When the utilization is above the target utilization, ```math r\_{90\%} ``` continuously shifts upwards. - When the utilization is below the target utilization, ```math r_{90\%} ``` continuously shifts downwards. {" "} The speed at which `math r_{90\%} ` moves is updated at each interaction: the farther we are from the target, the faster ```math r\_{90\%} ``` hence the curve, shifts. For example, if the utilization remains at 100% for 5 days, ```math r\_{90\%} ``` will progressively double. This is the maximum speed at which ```math r\_{90\%} ``` can move. The values of some [constants](https://github.com/morpho-org/morpho-blue-irm/blob/main/src/adaptive-curve-irm/libraries/ConstantsLib.sol) are hardcoded into the code deployed on Ethereum, such as `TARGET_UTILIZATION`, `INITIAL_RATE_AT_TARGET`, etc. ## Formal description We define: - Utilzation ( ```math u ``` ) ```math u(t) ``` is the ratio of total borrow over total supply at time ```math t ``` The utilization target is constant: ```math u\_{target}=0.9 ``` - Error ( ```math e ``` ): ```math \forall t, ``` ```math e(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} ``` 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 ```math u=0 ``` - Curve: ```math \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} ``` with ```math k_d=4 ``` - History of interactions ( ```math \mathcal{H} ``` ): Noting ```math t_i ``` the time at which the ```math i^{th} ``` interaction occurred, ```math \forall t, ``` ```math \mathcal{H}(t)=\{0\}+\{t_i\}_{t_i< t} ``` - Last interaction ( ```math \text{last} ``` ```math \forall t, ``` ```math \text{last}(t) = \max(\mathcal{H}(t)) ``` - Speed factor ( ```math \text{speed} ``` ): ```math \forall t, \text{ speed}(t) = \exp \big({k_P*e(\text{u}(\text{last}(t)))*(t-\text{last}(t))\big)}, \text{ with } k_p = 50 ``` - Rate at target ( ```math r_T ``` ```math r_T(0) ``` is set to an arbitrary value Then, ```math \forall t >0, r_T(t)=r_{T}(\text{last}(t))*\text{speed}(t) ``` At any time `math t `, the borrow rate ```math r ``` is given by the formula: ```math r(t) = r_{T}(t)* \text{curve}(u(t)) ``` ## 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 ### 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 - `MORPHO`: Address of Morpho. ## Mappings ### Rate at target ```solidity mapping(Id => uint256) public rateAtTarget; ``` Rate at target utilization for each market. Tells the height of the curve. ## Events ### BorrowRateUpdate ```solidity event BorrowRateUpdate(Id indexed id, uint256 avgBorrowRate, uint256 rateAtTarget); ``` Emitted when the borrow rate is updated (called by Morpho). #### Parameters: | 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. | ## [Morpho V0 (Optimizers - Deprecated)](https://docs.morpho.org/get-started/resources/contracts/morpho-v0/) [← Back to contracts](/get-started/resources/contracts/) # Morpho V0 (Optimizers - Deprecated) Morpho V0 has been **deprecated** following the vote of the [MIP 120](https://snapshot.box/#/s:morpho.eth/proposal/0x026c3360d4616532952f5ed0d728daa090dd9a9670c7bf58160cd0709c7d73f8) and [MIP 121](https://snapshot.box/#/s:morpho.eth/proposal/0x60b31cceca2beee55f8845f86b7988ee36f29ad50f5dda636164ab50b561936b). If you have a position on a Morpho V0 protocol, please reach out via the chatbox on [the Morpho Help Page](https://help.morpho.org/). ## Code ## Morpho V0 deployment addresses | 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 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. | 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) | ## Audits and Formal Verification 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/). The full list of audits and formal verifications is available below. ### Audits | Auditors | Scope | Date | Report | | :--------------------------------------------------------------------------------------- | :--------------------------------------------- | :----------------- | :----------------------------------------------------------------------------------------------------------- | | [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) | | [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) | ### Formal verifications | Formally Proven | Scope | Date | Tool Used | | :-------------------------------------------------------------------------------------------------------------------------- | :--------------------------------- | :------------ | :----------------------------------------------------------------------------- | | [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 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 Vaults V2](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/) [← Back to contracts](/get-started/resources/contracts/) # Morpho Vaults V2 ## Code ## Introduction to principles ### Caps structure ```solidity 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. | ### `deposit` ```solidity function deposit(uint256 assets, address onBehalf) external returns (uint256) ``` Deposits `assets` of the underlying token to mint vault shares for `onBehalf`. #### 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: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The amount of vault shares minted. | --- ### `mint` ```solidity 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: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The exact amount of shares to mint. | | `onBehalf` | address | The recipient of the minted vault shares. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The amount of the underlying asset deposited. | --- ### `withdraw` ```solidity 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: | 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: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The amount of vault shares burned. | --- ### `redeem` ```solidity 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: | 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: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The amount of the underlying asset withdrawn. | --- ### `forceDeallocate` ```solidity 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 can be set and taken from `onBehalf`'s shares to disincentivize misuse (see [`setForceDeallocatePenalty`](/get-started/resources/contracts/morpho-vaults-v2/#setforcedeallocatepenalty)). This function is permissionless and serves as an in-kind redemption mechanism. A `forceDeallocatePenalty` of 0 allows anyone to call `forceDeallocate` on behalf of any user. It would not lead to loss of funds, but could be used to cause vault funds to become idle at times unintended by the curator. #### Parameters: | 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: | Name | Type | Description | | :--- | :--- | :--- | | `withdrawnShares` | uint256 | The amount of shares burned from `onBehalf` as a penalty. | --- ### `accrueInterest` ```solidity 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` ```solidity function accrueInterestView() public view returns (uint256, uint256, uint256) ``` Returns the view version of interest accrual without updating state. #### Return Values: | 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` ```solidity function previewDeposit(uint256 assets) public view returns (uint256) ``` Returns previewed minted shares for a given asset amount. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The amount of assets to preview deposit for. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The amount of shares that would be minted. | --- ### `previewMint` ```solidity function previewMint(uint256 shares) public view returns (uint256) ``` Returns previewed deposited assets for a given share amount. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The amount of shares to preview mint for. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The amount of assets that would be deposited. | --- ### `previewWithdraw` ```solidity function previewWithdraw(uint256 assets) public view returns (uint256) ``` Returns previewed redeemed shares for a given asset amount. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The amount of assets to preview withdrawal for. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The amount of shares that would be burned. | --- ### `previewRedeem` ```solidity function previewRedeem(uint256 shares) public view returns (uint256) ``` Returns previewed withdrawn assets for a given share amount. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The amount of shares to preview redemption for. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The amount of assets that would be withdrawn. | --- ### `convertToShares` ```solidity 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: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The amount of assets to convert. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The corresponding amount of shares. | --- ### `convertToAssets` ```solidity 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: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The amount of shares to convert. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The corresponding amount of assets. | --- ### `maxDeposit` ```solidity 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` ```solidity 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` ```solidity 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` ```solidity 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` ```solidity 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: | Name | Type | Description | | :--- | :--- | :--- | | `data` | bytes[] | Array of encoded function calls to execute. | --- As a reminder, there are four distinct [roles](/curate/concepts/roles#morpho-vaults-v2-roles) in Morpho Vaults V2: 1. **Owner**: Manages role assignments. 2. **Curator**: The chief risk curator and strategist. 3. **Allocator**: The active portfolio curator. 4. **Sentinel**: A safety-oriented role for reactive risk mitigation. ## Owner Functions --- ### `setOwner` ```solidity function setOwner(address newOwner) external ``` Transfers ownership of the vault to `newOwner`. Only callable by the current `owner`. --- ### `setCurator` ```solidity function setCurator(address newCurator) external ``` Sets the vault's `Curator`. Only callable by the `owner`. --- ### `setIsSentinel` ```solidity function setIsSentinel(address account, bool newIsSentinel) external ``` Grants or revokes the `Sentinel` role for an `account`. Only callable by the `owner`. --- ### `setName` ```solidity function setName(string memory newName) external ``` Sets the vault's name. Only callable by the `owner`. --- ### `setSymbol` ```solidity function setSymbol(string memory newSymbol) external ``` Sets the vault's symbol. Only callable by the `owner`. ## 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` ```solidity function abdicate(bytes4 selector) external ``` Irreversibly disables the ability to submit a specific type of action. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `selector` | bytes4 | The function selector to abdicate. | --- ### `addAdapter` ```solidity function addAdapter(address account) external ``` Adds a new adapter to the vault. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The adapter address to add. | --- ### `decreaseAbsoluteCap` ```solidity function decreaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external ``` Decreases the absolute cap for an allocation target. The `id` is computed as `keccak256(idData)` where `idData` is the market-specific data identifying the allocation target. **Instant Action** (also callable by a `Sentinel`) #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `idData` | bytes | Market-specific data identifying the allocation target (e.g., market ID for Morpho markets). The hash of this data (`keccak256(idData)`) is used as the unique identifier. | | `newAbsoluteCap` | uint256 | The new absolute cap value. | --- ### `decreaseRelativeCap` ```solidity function decreaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external ``` Decreases the relative cap for an allocation target. The `id` is computed as `keccak256(idData)` where `idData` is the market-specific data identifying the allocation target. **Instant Action** (also callable by a `Sentinel`) #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `idData` | bytes | Market-specific data identifying the allocation target (e.g., market ID for Morpho markets). The hash of this data (`keccak256(idData)`) is used as the unique identifier. | | `newRelativeCap` | uint256 | The new relative cap value (scaled by 1e18). | --- ### `decreaseTimelock` ```solidity function decreaseTimelock(bytes4 selector, uint256 newDuration) external ``` Decreases a function's timelock duration. This action's timelock equals the current timelock of the function being decreased. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `selector` | bytes4 | The function selector. | | `newDuration` | uint256 | The new timelock duration. | --- ### `increaseAbsoluteCap` ```solidity function increaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external ``` Increases the absolute cap for an allocation target. The `id` is computed as `keccak256(idData)` where `idData` is the market-specific data identifying the allocation target. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `idData` | bytes | Market-specific data identifying the allocation target (e.g., market ID for Morpho markets). The hash of this data (`keccak256(idData)`) is used as the unique identifier. | | `newAbsoluteCap` | uint256 | The new absolute cap value. | --- ### `increaseRelativeCap` ```solidity function increaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external ``` Increases the relative cap for an allocation target. The `id` is computed as `keccak256(idData)` where `idData` is the market-specific data identifying the allocation target. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `idData` | bytes | Market-specific data identifying the allocation target (e.g., market ID for Morpho markets). The hash of this data (`keccak256(idData)`) is used as the unique identifier. | | `newRelativeCap` | uint256 | The new relative cap value (scaled by 1e18). | --- ### `increaseTimelock` ```solidity function increaseTimelock(bytes4 selector, uint256 newDuration) external ``` Increases a function's timelock duration. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `selector` | bytes4 | The function selector. | | `newDuration` | uint256 | The new timelock duration. | --- ### `removeAdapter` ```solidity function removeAdapter(address account) external ``` Removes an adapter from the vault. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The adapter address to remove. | --- ### `revoke` ```solidity function revoke(bytes calldata data) external ``` Revokes a pending timelocked action. **Instant Action** (also callable by a `Sentinel`) #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `data` | bytes | The ABI-encoded function call data to revoke. | --- ### `setAdapterRegistry` ```solidity function setAdapterRegistry(address newAdapterRegistry) external ``` Sets the adapter registry contract. The function validates that the new registry approves all currently added adapters. If the new registry returns false for any existing adapter, the transaction will revert. This ensures that changing the registry doesn't invalidate adapters that are already in use. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newAdapterRegistry` | address | The new adapter registry contract. | --- ### `setForceDeallocatePenalty` ```solidity function setForceDeallocatePenalty(address adapter, uint256 newForceDeallocatePenalty) external ``` Sets the penalty for using [`forceDeallocate`](/get-started/resources/contracts/morpho-vaults-v2/#forcedeallocate) on a specific adapter. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `adapter` | address | The adapter to set penalty for. | | `newForceDeallocatePenalty` | uint256 | The new penalty value (scaled by 1e18). | --- ### `setIsAllocator` ```solidity function setIsAllocator(address account, bool newIsAllocator) external ``` Grants or revokes the `Allocator` role for an account. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The account to modify. | | `newIsAllocator` | bool | Whether the account should be an allocator. | --- ### `setManagementFee` ```solidity function setManagementFee(uint256 newManagementFee) external ``` Sets the vault's management fee. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newManagementFee` | uint256 | The new management fee (scaled by 1e18). | --- ### `setManagementFeeRecipient` ```solidity function setManagementFeeRecipient(address newManagementFeeRecipient) external ``` Sets the management fee recipient. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newManagementFeeRecipient` | address | The new management fee recipient. | --- ### `setPerformanceFee` ```solidity function setPerformanceFee(uint256 newPerformanceFee) external ``` Sets the vault's performance fee. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newPerformanceFee` | uint256 | The new performance fee (scaled by 1e18). | --- ### `setPerformanceFeeRecipient` ```solidity function setPerformanceFeeRecipient(address newPerformanceFeeRecipient) external ``` Sets the performance fee recipient. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newPerformanceFeeRecipient` | address | The new performance fee recipient. | --- ### `setReceiveAssetsGate` ```solidity function setReceiveAssetsGate(address newReceiveAssetsGate) external ``` Sets the contract for gating asset receipts. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newReceiveAssetsGate` | address | The new receive assets gate contract. | --- ### `setReceiveSharesGate` ```solidity function setReceiveSharesGate(address newReceiveSharesGate) external ``` Sets the contract for gating share receipts. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newReceiveSharesGate` | address | The new receive shares gate contract. | --- ### `setSendAssetsGate` ```solidity function setSendAssetsGate(address newSendAssetsGate) external ``` Sets the contract for gating asset sends. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newSendAssetsGate` | address | The new send assets gate contract. | --- ### `setSendSharesGate` ```solidity function setSendSharesGate(address newSendSharesGate) external ``` Sets the contract for gating share sends. **Timelocked Action** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newSendSharesGate` | address | The new send shares gate contract. | --- ### `submit` ```solidity function submit(bytes calldata data) external ``` Submits a timelocked action for execution after the timelock period expires. **Timelock Management Function** #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `data` | bytes | The ABI-encoded function call data. | ## Allocator Functions --- ### `allocate` ```solidity function allocate(address adapter, bytes memory data, uint256 assets) external ``` Allocates `assets` from the vault's idle pool to a specific `adapter`. The allocation is subject to the caps configured for the target market. Only callable by an `Allocator`. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `adapter` | address | The adapter to allocate assets to. | | `data` | bytes | Market-specific data encoding passed to the adapter (e.g., market ID for Morpho markets). The hash of this data (`keccak256(data)`) identifies the allocation target for cap enforcement. | | `assets` | uint256 | The amount of assets to allocate. | --- ### `deallocate` ```solidity 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`. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `adapter` | address | The adapter to deallocate assets from. | | `data` | bytes | Market-specific data encoding passed to the adapter (e.g., market ID for Morpho markets). Must match the data used when allocating. | | `assets` | uint256 | The amount of assets to deallocate. | --- ### `setLiquidityAdapterAndData` ```solidity function setLiquidityAdapterAndData(address newLiquidityAdapter, bytes memory newLiquidityData) external ``` Sets the default adapter for handling user deposits and withdrawals. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newLiquidityAdapter` | address | The new liquidity adapter address. | | `newLiquidityData` | bytes | The new liquidity data for the adapter. | --- ### `setMaxRate` ```solidity function setMaxRate(uint256 newMaxRate) external ``` Sets the maximum rate at which `totalAssets` can grow. A curator-controlled parameter that caps how quickly totalAssets can grow, useful for implementing fixed-rate distributions or preventing unrealistic yield spikes. `maxRate` is capped at 200% APR (see `MAX_MAX_RATE` constant [here](https://github.com/morpho-org/vault-v2/blob/00881eb5f5c8031252c7fcdb7cd7e026bb21cfa4/src/libraries/ConstantsLib.sol#L9)) If `maxRate` is 0, yield does not accrue to vault's suppliers. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `newMaxRate` | uint256 | The new maximum rate per second (scaled by 1e18). | --- ## Gating Functions Gates are optional external smart contracts that implement access control for the vault. The vault supports four independent gates: `receiveSharesGate`, `sendSharesGate`, `receiveAssetsGate`, and `sendAssetsGate`. Gates are separate smart contracts that you (or the curator) must deploy independently. They are not part of the vault contract itself. The curator configures them using functions like `setReceiveSharesGate`, `setSendSharesGate`, etc. Each gate contract must implement a function that returns `bool` to indicate whether an account is allowed to perform the action. The vault calls these gates during transfers and deposits/withdrawals to enforce access control. --- ### `canReceiveShares` ```solidity function canReceiveShares(address account) public view returns (bool) ``` Checks if an account can receive shares based on the receive shares gate. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The account to check. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `allowed` | bool | Whether the account can receive shares. | --- ### `canSendShares` ```solidity function canSendShares(address account) public view returns (bool) ``` Checks if an account can send shares based on the send shares gate. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The account to check. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `allowed` | bool | Whether the account can send shares. | --- ### `canReceiveAssets` ```solidity 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: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The account to check. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `allowed` | bool | Whether the account can receive assets. | --- ### `canSendAssets` ```solidity function canSendAssets(address account) public view returns (bool) ``` Checks if an account can send assets based on the send assets gate. #### Parameters | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The account to check. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `allowed` | bool | Whether the account can send assets. | ## View Functions --- ### `totalAssets` ```solidity function totalAssets() external view returns (uint256) ``` Returns the total amount of underlying assets held by the vault, including both idle assets and assets allocated to adapters. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The total assets in the vault. | --- ### `adaptersLength` ```solidity function adaptersLength() external view returns (uint256) ``` Returns the number of adapters currently added to the vault. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `length` | uint256 | The number of adapters. | --- ### `absoluteCap` ```solidity function absoluteCap(bytes32 id) external view returns (uint256) ``` Returns the absolute cap for a given allocation `id`. The `id` is computed as `keccak256(idData)` where `idData` is the market-specific data identifying the allocation target. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `id` | bytes32 | The allocation identifier (keccak256 hash of idData). | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `cap` | uint256 | The absolute cap value. | --- ### `relativeCap` ```solidity function relativeCap(bytes32 id) external view returns (uint256) ``` Returns the relative cap for a given allocation `id`. The `id` is computed as `keccak256(idData)` where `idData` is the market-specific data identifying the allocation target. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `id` | bytes32 | The allocation identifier (keccak256 hash of idData). | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `cap` | uint256 | The relative cap value (scaled by 1e18). | --- ### `allocation` ```solidity function allocation(bytes32 id) external view returns (uint256) ``` Returns the current allocation amount for a given `id`. The `id` is computed as `keccak256(idData)` where `idData` is the market-specific data identifying the allocation target. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `id` | bytes32 | The allocation identifier (keccak256 hash of idData). | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `amount` | uint256 | The current allocation amount. | --- ### `owner` ```solidity function owner() external view returns (address) ``` Returns the current owner address of the vault. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `owner` | address | The owner address. | --- ### `curator` ```solidity function curator() external view returns (address) ``` Returns the current curator address of the vault. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `curator` | address | The curator address. | --- ### `isSentinel` ```solidity function isSentinel(address account) external view returns (bool) ``` Checks if an account has the Sentinel role. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The account to check. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `isSentinel` | bool | Whether the account is a sentinel. | --- ### `isAllocator` ```solidity function isAllocator(address account) external view returns (bool) ``` Checks if an account has the Allocator role. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The account to check. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `isAllocator` | bool | Whether the account is an allocator. | --- ### `receiveSharesGate` ```solidity function receiveSharesGate() external view returns (address) ``` Returns the address of the receive shares gate contract. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `gate` | address | The receive shares gate address. | --- ### `sendSharesGate` ```solidity function sendSharesGate() external view returns (address) ``` Returns the address of the send shares gate contract. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `gate` | address | The send shares gate address. | --- ### `receiveAssetsGate` ```solidity function receiveAssetsGate() external view returns (address) ``` Returns the address of the receive assets gate contract. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `gate` | address | The receive assets gate address. | --- ### `sendAssetsGate` ```solidity function sendAssetsGate() external view returns (address) ``` Returns the address of the send assets gate contract. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `gate` | address | The send assets gate address. | --- ### `adapterRegistry` ```solidity function adapterRegistry() external view returns (address) ``` Returns the address of the adapter registry contract. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `registry` | address | The adapter registry address. | --- ### `adapters` ```solidity function adapters(uint256 index) external view returns (address) ``` Returns the adapter address at a specific index (index list retrievable via the [`adaptersLength`](/get-started/resources/contracts/morpho-vaults-v2/#adapterslength) function). #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `index` | uint256 | The index in the adapters array. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `adapter` | address | The adapter address at the given index. | --- ### `isAdapter` ```solidity function isAdapter(address account) external view returns (bool) ``` Checks if an account is a registered adapter. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `account` | address | The account to check. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `isAdapter` | bool | Whether the account is an adapter. | --- ### `liquidityAdapter` ```solidity function liquidityAdapter() external view returns (address) ``` Returns the default adapter used for handling user deposits and withdrawals. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `adapter` | address | The liquidity adapter address. | --- ### `liquidityData` ```solidity function liquidityData() external view returns (bytes memory) ``` Returns the data associated with the liquidity adapter. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `data` | bytes | The liquidity adapter data. | --- ### `forceDeallocatePenalty` ```solidity function forceDeallocatePenalty(address adapter) external view returns (uint256) ``` Returns the penalty for using `forceDeallocate` on a specific adapter. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `adapter` | address | The adapter to check. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `penalty` | uint256 | The force deallocate penalty (scaled by 1e18). | --- ### `virtualShares` ```solidity function virtualShares() external view returns (uint256) ``` Returns the virtual shares used for avoiding initial share inflation attacks. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `shares` | uint256 | The virtual shares amount. | --- ### `firstTotalAssets` ```solidity function firstTotalAssets() external view returns (uint256) ``` Returns the total assets after the first interest accrual of the current transaction. Used to prevent bypassing relative caps with flashloans. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint256 | The total assets after the first interest accrual of the transaction. | --- ### `_totalAssets` ```solidity function _totalAssets() external view returns (uint128) ``` Returns the internal cached total assets value. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `assets` | uint128 | The cached total assets. | --- ### `lastUpdate` ```solidity function lastUpdate() external view returns (uint64) ``` Returns the timestamp of the last interest accrual. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `timestamp` | uint64 | The last update timestamp. | --- ### `maxRate` ```solidity function maxRate() external view returns (uint64) ``` Returns the maximum rate at which `totalAssets` can grow. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `rate` | uint64 | The maximum rate per second (scaled by 1e18). | --- ### `performanceFee` ```solidity function performanceFee() external view returns (uint96) ``` Returns the current performance fee. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `fee` | uint96 | The performance fee (scaled by 1e18). | --- ### `performanceFeeRecipient` ```solidity function performanceFeeRecipient() external view returns (address) ``` Returns the recipient address of performance fees. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `recipient` | address | The performance fee recipient address. | --- ### `managementFee` ```solidity function managementFee() external view returns (uint96) ``` Returns the current management fee. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `fee` | uint96 | The management fee (scaled by 1e18). | --- ### `managementFeeRecipient` ```solidity function managementFeeRecipient() external view returns (address) ``` Returns the recipient address of management fees. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `recipient` | address | The management fee recipient address. | --- ### `timelock` ```solidity function timelock(bytes4 selector) external view returns (uint256) ``` Returns the timelock duration for a specific function selector. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `selector` | bytes4 | The function selector. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `duration` | uint256 | The timelock duration in seconds. | --- ### `abdicated` ```solidity function abdicated(bytes4 selector) external view returns (bool) ``` Checks if the curator has abdicated the ability to submit a specific action. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `selector` | bytes4 | The function selector. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `abdicated` | bool | Whether the action has been abdicated. | --- ### `executableAt` ```solidity function executableAt(bytes memory data) external view returns (uint256) ``` Returns the timestamp when a submitted timelocked action becomes executable. #### Parameters: | Name | Type | Description | | :--- | :--- | :--- | | `data` | bytes | The ABI-encoded function call data. | #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `timestamp` | uint256 | The timestamp when the action becomes executable. | --- ### `DOMAIN_SEPARATOR` ```solidity function DOMAIN_SEPARATOR() external view returns (bytes32) ``` Returns the EIP-712 domain separator used for permit signatures. #### Return Values: | Name | Type | Description | | :--- | :--- | :--- | | `separator` | bytes32 | The domain separator. | ## [Morpho Vaults](https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/) [← Back to contracts](/get-started/resources/contracts/) # Morpho Vaults ## Code ## Market Those following 3 elements are defined in the [Morpho related section](/get-started/resources/contracts/morpho#market-parameters). - `MarketParams` struct, - `market` struct, - `Id` of markets. Also we have: ```solidity struct MarketAllocation { MarketParams marketParams; uint256 assets; } ``` | Name | Type | Description | | :------------- | :------------------------------------------------------------------------ | :-------------------------------- | | `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The market to allocate funds to. | | `assets` | uint256 | The amount of assets to allocate. | ## External Functions ### deposit ```solidity 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: | 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: | Name | Type | Description | | :------- | :------ | :--------------------------------- | | `shares` | uint256 | The amount of vault shares minted. | ### mint ```solidity 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: | 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: | Name | Type | Description | | :------- | :------ | :---------------------------------------- | | `assets` | uint256 | The amount of underlying token deposited. | ### withdraw ```solidity 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: | 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: | Name | Type | Description | | :------- | :------ | :--------------------------- | | `shares` | uint256 | The amount of shares burned. | ### redeem ```solidity 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: | 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: | Name | Type | Description | | :------- | :------ | :---------------------------------------- | | `assets` | uint256 | The amount of underlying token withdrawn. | ### acceptTimelock ```solidity 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 ```solidity 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 ```solidity 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: | Name | Type | Description | | :--- | :--------------------------------------------------- | :-------------------------------------- | | `id` | [Id](/get-started/resources/contracts/morpho#market-id) | The id of the market to accept the cap. | ### skim ```solidity function skim(address token) external {} ``` Skims the vault `token` balance to `skimRecipient`. #### Parameters: | 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) As a reminder, there are specific types of [roles](/curate/concepts/roles/) in Morpho Vaults: 1. **Owner**, 2. **Curator**, 3. **Allocator**, 4. **Guardian**. ## OnlyOwner Functions ### setName (V1.1) ```solidity function setName(string memory newName) external onlyOwner {} ``` Sets the vault's name to `newName`. #### Parameters: | Name | Type | Description | | :-------- | :----- | :------------------------ | | `newName` | string | The new name of the vault | ### setSymbol (V1.1) ```solidity function setSymbol(string memory newSymbol) external onlyOwner {} ``` Sets the vault's symbol to `newSymbol`. #### Parameters: | Name | Type | Description | | :---------- | :----- | :-------------------------- | | `newSymbol` | string | The new symbol of the vault | ### setCurator ```solidity function setCurator(address newCurator) external onlyOwner {}; ``` Sets `curator` to `newCurator`. #### Parameters: | Name | Type | Description | | :----------- | :------ | :------------------------------ | | `newCurator` | address | The address of the new curator. | ### setIsAllocator ```solidity function setIsAllocator(address newAllocator, bool newIsAllocator) external onlyOwner {}; ``` Sets `newAllocator` as an allocator or not (`newIsAllocator`). #### Parameters: | 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 ```solidity function setSkimRecipient(address newSkimRecipient) external onlyOwner {}; ``` Sets `skimRecipient` to `newSkimRecipient`. #### Parameters: | Name | Type | Description | | :----------------- | :------ | :------------------------------------------- | | `newSkimRecipient` | address | The address of the new recipient parameters. | ### submitTimelock ```solidity 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: | Name | Type | Description | | :------------ | :------ | :------------------------------------------ | | `newTimelock` | uint256 | The value of the new timelock (in seconds). | ### setFee ```solidity function setFee(uint256 newFee) external onlyOwner {}; ``` Sets the `fee` to `newFee`. #### Parameters: | Name | Type | Description | | :------- | :------ | :-------------------------------------- | | `newFee` | uint256 | The value of the new fee scaled in wad. | ### setFeeRecipient ```solidity function setFeeRecipient(address newFeeRecipient) external onlyOwner {}; ``` Sets `feeRecipient` to `newFeeRecipient`. #### Parameters: | Name | Type | Description | | :---------------- | :------ | :------------------------------------ | | `newFeeRecipient` | address | The address of the new fee recipient. | ### submitGuardian ```solidity 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: | Name | Type | Description | | :------------ | :------ | :------------------------------- | | `newGuardian` | address | The address of the new guardian. | ## onlyCuratorRole Functions Note that owner and curator has the `onlyCuratorRole`. ### submitCap ```solidity 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: | Name | Type | Description | | :------------- | :------------------------------------------------------------------------ | :-------------------------------------- | | `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The market parameters. | | `newSupplyCap` | uint256 | The new supply cap in underlying units. | ### submitMarketRemoval ```solidity 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: | Name | Type | Description | | :------------- | :------------------------------------------------------------------------ | :--------------------- | | `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The market parameters. | ## onlyAllocatorRole Functions Note that owner, curator and an address that has been set as an allocator has the `onlyAllocatorRole`. ### setSupplyQueue ```solidity function setSupplyQueue(Id[] calldata newSupplyQueue) external onlyAllocatorRole {}; ``` Sets `supplyQueue` to `newSupplyQueue`. #### Parameters: | Name | Type | Description | | :--------------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | | `newSupplyQueue` | [Id](/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 ```solidity 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: | Name | Type | Description | | :-------- | :---------- | :-------------------------------------------------------------------------------------------- | | `indexes` | uint256 [ ] | The indexes of each market in the previous withdraw queue, in the new withdraw queue's order. | ### reallocate ```solidity 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: | Name | Type | Description | | :------------ | :--------------------------------------------------------------------- | :------------------------------------------------ | | `allocations` | [MarketAllocation](/get-started/resources/contracts/morpho-vaults#market) | The respective allocations in each market chosen. | ## onlyGuardianRole Functions Note that owner and guardian has the `onlyAllocatorRole`. ### revokePendingTimelock ```solidity function revokePendingTimelock() external onlyGuardianRole {}; ``` Revokes the pending timelock. - Does not revert if there is no pending timelock. ### revokePendingGuardian ```solidity function revokePendingGuardian() external onlyGuardianRole {}; ``` Revokes the pending guardian. ## onlyCuratorOrGuardianRole Functions Note that owner, curator and guardian has the `onlyAllocatorRole`. ### revokePendingCap ```solidity 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: | Name | Type | Description | | :--- | :--------------------------------------------------- | :---------------------------------------------- | | `id` | [Id](/get-started/resources/contracts/morpho#market-id) | The id of the market to revoke the pending cap. | ### revokePendingMarketRemoval ```solidity 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: | Name | Type | Description | | :--- | :--------------------------------------------------- | :-------------------------------------------------- | | `id` | [Id](/get-started/resources/contracts/morpho#market-id) | The id of the market to revoke the pending removal. | # Errors Codes 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: ```solidity 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](https://docs.morpho.org/get-started/resources/contracts/morpho/) [← Back to contracts](/get-started/resources/contracts/) # Morpho ## Code ## Market Parameters ### Market id The market id is a `bytes32` keccak256 hash of the [5 parameters of a market](#marketparams-struct). It is used to identify a market in Morpho. ```solidity 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 The market struct is defined as follows: ```solidity 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 The majority of the entrypoints accept a `MarketParams` struct as parameter. This struct is defined as follows: ```solidity 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](#idtomarketparams) view function to recover the parameters of a given market from the bytes32 id. ## Functions ### setOwner ```solidity 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: | Name | Type | Description | | :--------- | :------ | :--------------------- | | `newOwner` | address | The new owner address. | ### enableIrm ```solidity function enableIrm(address irm) external; ``` Enables `irm` as a possible IRM for market creation. - Warning: It is not possible to disable an IRM. #### Parameters: | Name | Type | Description | | :---- | :------ | :------------------------- | | `irm` | address | The irm address to enable. | ### enableLltv ```solidity function enableLltv(uint256 lltv) external; ``` Enables `lltv` as a possible LLTV for market creation. - Warning: It is not possible to disable a LLTV. #### Parameters: | Name | Type | Description | | :----- | :------ | :-------------------------------------- | | `lltv` | uint256 | The lltv value to enable (18 decimals). | ### setFee ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------- | | `marketParams` | [MarketParams](#marketparams-struct) | The market parameters. | | `newFee` | uint256 | The new fee value. | ### setFeeRecipient ```solidity 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: | Name | Type | Description | | :---------------- | :------ | :------------------------------------ | | `newFeeRecipient` | address | The address of the new fee recipient. | ### createMarket ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :-------------------- | | `marketParams` | [MarketParams](#marketparams-struct) | The market parameters | ### supply ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :-------------------------------------------------------------------------------------- | | `marketParams` | [MarketParams](#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: | Name | Type | Description | | :--------------- | :------ | :----------------------------- | | `assetsSupplied` | uint256 | The amount of assets supplied. | | `sharesSupplied` | uint256 | The amount of shares minted. | ### withdraw ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :-------------------------------------------------- | | `marketParams` | [MarketParams](#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: | Name | Type | Description | | :---------------- | :------ | :------------------------------ | | `assetsWithdrawn` | uint256 | The amount of assets withdrawn. | | `sharesWithdrawn` | uint256 | The amount of shares burned. | ### borrow ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :------------------------------------------------------- | | `marketParams` | [MarketParams](#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: | Name | Type | Description | | :--------------- | :------ | :----------------------------- | | `assetsBorrowed` | uint256 | The amount of assets borrowed. | | `sharesBorrowed` | uint256 | The amount of shares minted. | ### repay ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :---------------------------------------------------------------------------------------------------- | | `marketParams` | [MarketParams](#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: | Name | Type | Description | | :------------- | :------ | :--------------------------- | | `assetsRepaid` | uint256 | The amount of assets repaid. | | `sharesRepaid` | uint256 | The amount of shares burned. | ### supplyCollateral ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :------------------------------------------------------------------------------------------------ | | `marketParams` | [MarketParams](#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 ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------------------------------------- | | `marketParams` | [MarketParams](#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 ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :----------------------------------------------------------------------------------------- | | `marketParams` | [MarketParams](#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: | Name | Type | Description | | :------------- | :------ | :--------------------------- | | `assetsSeized` | uint256 | The amount of assets seized. | | `assetsRepaid` | uint256 | The amount of assets repaid. | ### flashLoan ```solidity 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: | 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 ```solidity function setAuthorization(address authorized, bool newIsAuthorized) external; ``` Sets the authorization for `authorized` to manage `msg.sender`'s positions. #### Parameters: | Name | Type | Description | | :---------------- | :------ | :---------------------------- | | `authorized` | address | The authorized address. | | `newIsAuthorized` | bool | The new authorization status. | ### setAuthorizationWithSig ```solidity 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. While both functions achieve the same outcome (managing operator permissions), they serve different use cases: - **`setAuthorization`**: Requires an onchain transaction directly from the `authorizer`'s address (or a contract they control). It's simpler for direct interactions but costs gas for the authorizer. - **`setAuthorizationWithSig`**: Uses an EIP-712 signature created offchain by the `authorizer`. This signature can then be submitted onchain by _any_ address (e.g., the `authorized` party, a relayer, or the Morpho Bundler). This enables gasless approvals for the authorizer and is essential for meta-transactions and efficient bundling flows, especially with EOAs. #### 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: | Name | Type | Description | | :-------------- | :------------------------------------- | :------------------------- | | `authorization` | [Authorization](#authorization-struct) | The authorization to set. | | `signature` | Signature | The signature to validate. | ### accrueInterest ```solidity function accrueInterest(MarketParams memory marketParams) external; ``` Accrues interest for the given market `marketParams`. #### Parameters: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------- | | `marketParams` | [MarketParams](#marketparams-struct) | The market parameters. | ## Views Functions ### DOMAIN_SEPARATOR ```solidity 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: | Type | Description | | :------ | :---------------------------- | | bytes32 | The EIP-712 domain separator. | ### owner ```solidity 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: | Type | Description | | :------ | :------------------------- | | address | The owner of the contract. | ### feeRecipient ```solidity 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: | Type | Description | | :------ | :------------------------- | | address | The fee recipient address. | ### isIrmEnabled ```solidity function isIrmEnabled(address irm) external view returns (bool); ``` Whether the `irm` is enabled. #### Parameters: | Name | Type | Description | | :---- | :------ | :--------------- | | `irm` | address | The irm address. | #### Return Values: | Type | Description | | :--- | :------------------------------------------------------------- | | bool | Boolean equals to `true` if irm is enabled, `false` otherwise. | ### isLltvEnabled ```solidity function isLltvEnabled(uint256 lltv) external view returns (bool); ``` Whether the `lltv` is enabled. #### Parameters: | Name | Type | Description | | :----- | :------ | :---------------- | | `lltv` | address | The lltv address. | #### Return Values: | Type | Description | | :--- | :-------------------------------------------------------------- | | bool | Boolean equals to `true` if lltv is enabled, `false` otherwise. | ### isAuthorized ```solidity 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: | Name | Type | Description | | :----------- | :------ | :---------------------- | | `authorizer` | address | The authorizer address. | | `authorized` | address | The authorized address. | #### Return Values: | Type | Description | | :--- | :------------------------------------------------------------------------------------------------------------------- | | bool | Boolean equals to `true` if `authorized` address is authorized to modify `authorizer`'s position, `false` otherwise. | ### nonce ```solidity function nonce(address authorizer) external view returns (uint256); ``` The `authorizer`'s current nonce. Used to prevent replay attacks with EIP-712 signatures. #### Parameters: | Name | Type | Description | | :----------- | :------ | :---------------------- | | `authorizer` | address | The authorizer address. | #### Return Values: | Type | Description | | :------ | :----------------------- | | uint256 | The current nonce value. | ### extSloads ```solidity function extSloads(bytes32[] memory slots) external view returns (bytes32[] memory); ``` Returns the data stored on the different `slots`. #### Parameters: | Name | Type | Description | | :------ | :-------- | :--------------------------------------------------- | | `slots` | bytes32[] | The array of slots to retrieve the data stored into. | #### Return Values: | Type | Description | | :-------- | :--------------- | | bytes32[] | The data stored. | ### idToMarketParams ```solidity 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: | Name | Type | Description | | :--- | :--- | :------------ | | `id` | Id | The market id | #### Return Values: | 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 ```solidity 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](#morphobalanceslib) to accrue interests #### Parameters: | Name | Type | Description | | :--- | :--- | :------------ | | `id` | Id | The market id | #### Return Values: | 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 ```solidity 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: | Name | Type | Description | | :----- | :------ | :---------------- | | `id` | Id | The market id. | | `user` | address | The user address. | #### Return Values: | 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 The MorphoBalancesLib is a library that allows you to accrue interest and update the assets values of a market. You can easily retrieve market amounts and user balances with interests. > The Github code is available [**here**](https://github.com/morpho-org/morpho-blue/blob/be2306afd655232d2cf16547c18be0077014bae0/src/libraries/periphery/MorphoBalancesLib.sol) ### expectedMarketBalances ```solidity 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](#market-struct). #### Parameters: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------------------------------------- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected balances from. | #### Return Values: | 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 ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------------------------------------- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected total supply from. | #### Return Values: | Name | Type | Description | | :------------------ | :------ | :-------------------------------------------------------------- | | `totalSupplyAssets` | uint256 | The total supply assets of the market (with interests accrued). | ### expectedTotalBorrowAssets ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------------------------------------- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected total borrow from. | #### Return Values: | Name | Type | Description | | :------------------ | :------ | :-------------------------------------------------------------- | | `totalBorrowAssets` | uint256 | The total borrow assets of the market (with interests accrued). | ### expectedTotalSupplyShares ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------------------------------------- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected total supply from. | #### Return Values: | Name | Type | Description | | :------------------ | :------ | :-------------------------------------------------------------- | | `totalSupplyShares` | uint256 | The total supply shares of the market (with interests accrued). | ### expectedSupplyAssets ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------------------------------------- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected supply assets from. | | `user` | address | The user to get the expected supply assets from. | #### Return Values: | Name | Type | Description | | :------------- | :------ | :------------------------------------------------------ | | `supplyAssets` | uint256 | The supply assets of the user (with interests accrued). | ### expectedBorrowAssets ```solidity 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: | Name | Type | Description | | :------------- | :----------------------------------- | :--------------------------------------------------- | | `morpho` | IMorpho | The Morpho contract (injected when used as library). | | `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected borrow assets from. | | `user` | address | The user to get the expected borrow assets from. | #### Return Values: | Name | Type | Description | | :-------------- | :------ | :------------------------------------------------------ | | `borrowBalance` | uint256 | The borrow assets of the user (with interests accrued). | ## 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. | ## [Oracles](https://docs.morpho.org/get-started/resources/contracts/oracles/) [← Back to contracts](/get-started/resources/contracts/) # Oracles ## Code ## 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 ```solidity 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: | 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 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 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 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 > [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 - `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 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. ## [Public Allocator](https://docs.morpho.org/get-started/resources/contracts/public-allocator/) [← Back to contracts](/get-started/resources/contracts/) # Public Allocator ## Code ## 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. **Fee Collection** The reallocation fees are set and collected by the vault curator (admin or vault owner), not by Morpho. Curators can set the fee to any value, including zero, and can withdraw accrued fees using the `transferFee` function. ## Constants ### 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 ### FlowCaps The `FlowCaps` struct is defined as follows: ```solidity struct FlowCaps { uint128 maxIn; uint128 maxOut; } ``` It contains the maximum allowed inflow and outflow for a market. ### FlowCapsConfig The `FlowCapsConfig` struct is defined as follows: ```solidity struct FlowCapsConfig { Id id; FlowCaps caps; } ``` It is used to configure the flow caps for a market. ### Withdrawal The `Withdrawal` struct is defined as follows: ```solidity struct Withdrawal { MarketParams marketParams; uint128 amount; } ``` It specifies the market and the amount to withdraw. ## Functions ### setAdmin ```solidity function setAdmin(address vault, address newAdmin) external; ``` Sets `newAdmin` as the admin for the specified vault. #### Parameters: | Name | Type | Description | | :--------- | :------ | :------------------------ | | `vault` | address | The address of the vault. | | `newAdmin` | address | The new admin address. | ### setFee ```solidity function setFee(address vault, uint256 newFee) external; ``` Sets the `newFee` for the specified vault. #### Parameters: | Name | Type | Description | | :------- | :------ | :------------------------ | | `vault` | address | The address of the vault. | | `newFee` | uint256 | The new fee value. | ### setFlowCaps ```solidity function setFlowCaps(address vault, FlowCapsConfig[] calldata config) external; ``` Sets the maximum inflow and outflow for the specified markets in the given vault. #### Parameters: | Name | Type | Description | | :------- | :------------------------ | :--------------------------------- | | `vault` | address | The address of the vault. | | `config` | FlowCapsConfig[] calldata | The flow caps configuration array. | ### transferFee ```solidity function transferFee(address vault, address payable feeRecipient) external; ``` Transfers the accrued fee to the specified recipient for the given vault. #### Parameters: | Name | Type | Description | | :------------- | :------ | :---------------------------- | | `vault` | address | The address of the vault. | | `feeRecipient` | address | The address of the recipient. | ### reallocateTo ```solidity 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: | 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 ### PublicWithdrawal ```solidity event PublicWithdrawal(address indexed sender, address indexed vault, Id indexed id, uint256 withdrawnAssets); ``` Emitted during a public reallocation for each withdrawn-from market. ### PublicReallocateTo ```solidity event PublicReallocateTo(address indexed sender, address indexed vault, Id indexed supplyMarketId, uint256 suppliedAssets); ``` Emitted at the end of a public reallocation. ### SetAdmin ```solidity event SetAdmin(address indexed sender, address indexed vault, address admin); ``` Emitted when the admin is set for a vault. ### SetFee ```solidity event SetFee(address indexed sender, address indexed vault, uint256 fee); ``` Emitted when the fee is set for a vault. ### TransferFee ```solidity event TransferFee(address indexed sender, address indexed vault, uint256 amount, address indexed feeRecipient); ``` Emitted when the fee is transferred for a vault. ### SetFlowCaps ```solidity event SetFlowCaps(address indexed sender, address indexed vault, FlowCapsConfig[] config); ``` Emitted when the flow caps are set for a vault. ## Error Handling ### 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 ### IPublicAllocatorBase Defines the basic interface for the `PublicAllocator`. ### IPublicAllocatorStaticTyping Inherits from `IPublicAllocatorBase` and includes a function to get flow caps. ### IPublicAllocator The primary interface for the `PublicAllocator`. ## 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. ## [Universal Rewards Distributors](https://docs.morpho.org/get-started/resources/contracts/rewards/) [← Back to contracts](/get-started/resources/contracts/) # Universal Rewards Distributors ## Code ## 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 ### submitRoot ```solidity 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: | Name | Type | Description | | :------------ | :------ | :--------------------------------------------------------- | | `newRoot` | bytes32 | The new merkle root. | | `newIpfsHash` | bytes32 | The optional ipfs hash containing metadata about the root. | ### acceptRoot ```solidity 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 ```solidity 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 ```solidity 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: | 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: | Name | Type | Description | | :------- | :------ | :---------------------------------- | | `amount` | uint256 | The amount of reward token claimed. | ### setRoot ```solidity 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: | Name | Type | Description | | :------------ | :------ | :--------------------------------------------------------- | | `newRoot` | bytes32 | The new merkle root. | | `newIpfsHash` | bytes32 | The optional ipfs hash containing metadata about the root. | ### setTimelock ```solidity 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: | Name | Type | Description | | :------------ | :------ | :---------------- | | `newTimelock` | uint256 | The new timelock. | ### setRootUpdater ```solidity function setRootUpdater(address updater, bool active) external onlyOwner; ``` Sets or unsets an address as a root updater. #### Parameters: | 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 ```solidity 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: | Name | Type | Description | | :--------- | :------ | :---------------------------- | | `newOwner` | address | The address of the new owner. | ## 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 There are only 2 roles: - **Owner**: owner of the contract that has access to the updater's functions and [`setTimelock`](#settimelock), [`setRootUpdater`](#setrootupdater), and [`setOwner`](#setowner) functions. - **Updater**: addresses that can trigger the [`submitRoot`](#submitroot), [`setRoot`](#setroot), and [`revokePendingRoot`](#revokependingroot) functions. ## [Legal Disclaimer](https://docs.morpho.org/get-started/resources/disclaimer/) The materials, information, descriptions, data, and examples contained in this documentation (the “Documentation”) are provided solely for general informational purposes. The Documentation does not constitute, and shall not be interpreted as, legal, financial, investment, accounting, technological, or professional advice of any kind. Nothing herein shall be construed as an offer to sell or the solicitation of an offer to purchase any product, service, or financial instrument. Morpho Association and its affiliates, directors, officers, employees, contractors, contributors, and agents (collectively, “Morpho”) make no representations or warranties, express or implied, regarding the accuracy, completeness, reliability, suitability, or availability of the Documentation or any information contained herein. All information is provided “as is” and “as available,” and may be incomplete, inaccurate, outdated, or subject to change without notice. To the fullest extent permitted by applicable law, Morpho disclaims all liability for any direct, indirect, incidental, consequential, special, exemplary, or punitive losses or damages, or for any claims, liabilities, or costs of any kind, arising out of or in connection with (i) access to, use of, reliance on, inability to use, or interpretation of the Documentation, (ii) interactions with or use of the Morpho protocol, smart contracts, interfaces, or any related software, or (iii) any decision made or action taken based on the Documentation. Users are solely responsible for conducting their own independent investigation and due diligence and for obtaining any professional advice they deem necessary prior to interacting with the Morpho protocol or relying on any information contained in the Documentation. No user shall have any right of action against Morpho based on the Documentation or any reliance hereon. ## [Use Cases on the Morpho Stack](https://docs.morpho.org/get-started/use-cases/) ### Discover who is building and trusting the Morpho Stack. {/* Coinbase Card */} Coinbase Borrow Coinbase leverages the Morpho Stack to offer the Bitcoin-Backed Loan product to their users. e.stopPropagation()} target="_blank" rel="noopener noreferrer"> Coinbase article Learn more → {/* Moonwell Card */} Moonwell Borrow Earn Moonwell builds innovative lending vaults powered by the Morpho protocol infrastructure. Learn more → {/* Spark Card */} Spark Earn Spark utilizes Morpho's infrastructure to provide efficient lending solutions for DeFi users. Learn more → {/* Seamless Card */} Seamless Borrow Earn Seamless leverages Morpho's protocol to deliver seamless lending experiences for users. Learn more → # --- Learn --- ## [Morpho Overview](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](/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](/learn/governance/organization/#morpho-association) hosts one of the Morpho Interfaces. ## 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 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 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 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. 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](/get-started/resources/contracts/bundlers). ## What Bundler3 Allows You To Do 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: - **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 ## [Curator](https://docs.morpho.org/learn/concepts/curator/) 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](/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 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 Allocators**: 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 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 Curation** | 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 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. ## [Flash Loans](https://docs.morpho.org/learn/concepts/flashloans/) 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? 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 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 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 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 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 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 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: ```solidity // 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 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 ## [Interest Rate Model](https://docs.morpho.org/learn/concepts/irm/) 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](#the-adaptivecurveirm), which is described in more detail later in this page. ## 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? #### Borrow APY Calculation The Borrow APY is obtained by compounding the per-second borrow rate over the entire year. The formula is: ```math \text{borrowAPY} = \left(e^{\left(\text{borrowRate} \times \text{secondsPerYear}\right)} - 1\right) ``` Here, `borrowRate` is the rate provided by the IRM and `secondsPerYear` equals 31,536,000. #### Supply APY Calculation The Supply APY is obtained by adjusting the Borrow APY like this: ```math \text{supplyAPY} = \text{borrowAPY} \times \text{utilization} \times (1 - \text{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)) Below is a basic typescript snippet showcasing the rate calculus with a rate returned by the IRM of `1512768697` ```typescript // [!include ~/snippets/learn/math.ts:function] ``` The output here is: ``` // [!include ~/snippets/learn/math.ts:output] ``` ### 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.org/blog/introducing-the-adaptivecurveirm-efficient-and-autonomous/) 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 ### 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. ### 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. ```math r_{90\%} ``` is the target rate at utilization target ```math u_{target}=0.9 ``` Example with the interest rate currently at 4% at ```math u_{target}=0.9 ``` - If utilization rate goes to 100% following a market event, the interest rate will instantly go to 16% in this example (x4) - At the opposite, if a market event bring the utilization rate to 0%, the interest rate will instantly go to 1% in this example (/4) 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. 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. Some examples are given below about the target ```math r_{90\%} ``` - If the utilization remains at 45%, it will progressively decrease until it is divided by 2 after 10 days. - If the utilization remains at 95%, it will progressively increase until it doubles after 10 days. - If the utilization remains at 100%, it will progressively increase until it doubles after 5 days. This is the maximum speed at which it can move. Here's a video showing how the two mechanisms combine to adjust interest rates: For more on the AdaptiveCurveIRM, explore the [technical reference](/get-started/resources/contracts/irm). ## [Liquidation on Morpho](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) Before exploring the liquidation mechanisms, it's essential to understand how LTV is calculated and what it represents. ### 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: ```math \text{LTV} = \frac{\text{BORROWED\_AMOUNT}}{\text{COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN}} \times 100\% ``` Where: - **`BORROWED_AMOUNT`**: The amount of borrowed assets of the user (in token base units) - **`COLLATERAL_VALUE_IN_LOAN_TOKEN`**: The value of the collateral in terms of the loan token The collateral value in loan token units is calculated as: ```math \text{COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN} = \frac{\text{COLLATERAL\_AMOUNT } \times \text{ ORACLE\_PRICE}}{\text{ORACLE\_PRICE\_SCALE}} ``` Where: - **`COLLATERAL_AMOUNT`**: The amount of collateral assets provided by the user (in token base units) - **`ORACLE_PRICE`**: The oracle price returned by the oracle of the market (scaled by ORACLE_PRICE_SCALE) - **`ORACLE_PRICE_SCALE`**: A scaling factor of 10^36 used by the protocol for price normalization ### Health Factor The Health Factor is another crucial metric that indicates how close a position is to liquidation: ```math \text{HEALTH\_FACTOR} = \frac{\text{COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN} \times \text{LLTV}}{\text{BORROWED\_AMOUNT}} ``` Where: - **`LLTV`**: The Liquidation Loan-To-Value threshold set for the market (e.g., 0.86 or 86%), expressed as a WAD (10^18 scaled value, like 860000000000000000) 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. - For oracle implementation details, see the [dedicated oracle section](/learn/concepts/oracle/) - WAD represents a common scaling factor in DeFi of 10^18 used for representing decimal numbers in integer arithmetic Let's walk through a concrete example of calculating LTV and Health Factor for a position on Morpho: **Given values (with assumptions):** - Borrowed amount: 150,000 USDC (150,000,000,000 base units with 6 decimals) - Collateral amount: 2 cbBTC (200,000,000 base units with 8 decimals) - Oracle price: 1 × 10^39 (means 1 cbBTC = 100000 USDC). This is supposedly the value returned by the price function in the oracle used in the related market - Oracle price scale: 10^36 - LLTV: 86% (expressed as 0.86 × 10^18 or 860,000,000,000,000,000 in WAD units) #### Calculate the collateral value in loan token units ```typescript // All calculations use BigInt (suffixed with 'n') to handle large numbers precisely const collateralValueInLoanToken = (collateralAmount * oraclePrice) / ORACLE_PRICE_SCALE; // = (200,000,000n * 1,000,000,000,000,000,000,000,000,000,000,000,000,000n) / 10n**36n // = 200,000,000,000 base units of loan token (USDC) ``` #### Calculate the current LTV ```typescript // Constants const WAD = 10n ** 18n; // Standard scaling factor (10^18) // Example values const borrowedAmount = 150_000_000_000n; // 150 billion units (e.g., USDC with 6 decimals) const collateralValueInLoanToken = 200_000_000_000n; // 200 billion units /** * Current LTV Calculation * ---------------------- * * Step 1: Calculate the raw LTV ratio, preserving precision with WAD */ const currentLTV = (borrowedAmount * WAD) / collateralValueInLoanToken; // = (150,000,000,000n * 10n**18n) / 200,000,000,000n // = 750,000,000,000,000,000n (scaled by WAD, representing 0.75 or 75%) /** * Option 1: Theoretical Formula * ---------------------------- * In theory, the conversion to percentage is simply: */ // Theoretical formula (doesn't work directly with BigInt) // currentLTVPercentage = (currentLTV / WAD) * 100 // Implementation of theoretical formula (using Number conversion) const theoreticalLTVPercentage = (Number(currentLTV) / Number(WAD)) * 100; // = 75.0000% /** * Option 2: Practical Display Implementation * ---------------------------------------- * For precise display with 4 decimal places, we: * 1. Scale up by the display factor (percentage * decimal precision) * 2. Divide by WAD to normalize * 3. Convert to Number and adjust for decimal places */ // Scale factor = 100 (for percentage) * 10000 (for 4 decimal places) = 1,000,000 const displayScaleFactor = 1_000_000n; const currentLTVPercentageScaled = (currentLTV * displayScaleFactor) / WAD; // = 750_000n (represents 75.0000%) // Convert the scaled BigInt result to a human-readable number const displayLTVPercentage = Number(currentLTVPercentageScaled) / 10000; // = 75.0000% (when displayed with 4 decimal places) ``` #### Calculate the health factor ```typescript // Since LLTV is stored as a WAD, we need to account for scaling const healthFactor = (collateralValueInLoanToken * lltv) / borrowedAmount; // = (200,000,000,000,000n * 860,000,000,000,000,000n) / 150,000,000,000n // = 1,146,666,666,666,666,666 (scaled by WAD) // Convert to decimal const healthFactorDisplay = Number(healthFactor) / Number(WAD); // = 1.1467 (when converted to a human-readable decimal) ``` Since the Health Factor is greater than 1.0 (1.1467), this position is healthy and has a safety margin before liquidation could occur. #### Summary of Position: - Current LTV: 75.00% - Max LTV (LLTV): 86.00% - Health Factor: 1.1467 - Status: Healthy - Liquidation Buffer: 11.00% (difference between current LTV and max LTV) This shows a position with an LTV of 75%, which is below the LLTV threshold of 86%. The Health Factor of 1.1467 confirms that the position is healthy with a 11% safety margin before liquidation. - For oracle implementation details, see the [dedicated oracle section](/learn/concepts/oracle/) - For examples of LTV calculations in Solidity, refer to [this code](https://github.com/morpho-org/morpho-blue/blob/12b8a453643d5ef9d55abd88b9f8cfa866882aa5/src/Morpho.sol#L532-L536) ## 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? 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 **Example** If a borrower provides $100 of collateral in a market with an LLTV of 86%: - The position is safe when borrowed value ≤ $86 - The position becomes liquidatable when borrowed value > $86 (LTV > 86%) ### 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) The liquidation bonus is determined by the Liquidation Incentive Factor (LIF), which depends on the market's LLTV: ```math \text{LIF} = \min(M, \frac{1}{\beta*\text{LLTV}+(1-\beta)}), \text{ with } \beta = 0.3 \text{ and } M= 1.15. ``` Liquidation Incentive Factor in relation to the Liquidation Loan-To-Value - The entire LIF goes to the liquidator; Morpho protocol doesn't take a fee - For an 86% LLTV market, the LIF is approximately 1.05 (5% bonus) ### Standard Liquidation Step-by-Step #### 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 - 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 - 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 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 - **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 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) 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. If a borrower provides $100 of collateral in a market with LLTV = 80% and preLLTV = 75%: - The position is safe when LTV ≤ 75% - The position is pre-liquidatable when 75% < LTV < 80% - The position is fully liquidatable (following the standard liquidation process) when LTV > 80% ### How Pre-Liquidation Parameters Work Pre-liquidation operates with 6 key parameters: #### Pre-Liquidation Loan-To-Value (preLLTV) The threshold at which pre-liquidation becomes possible #### 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: ```math preLCF = \frac{LLTV - LTV}{LLTV - preLLTV} * preLCF_1 + \frac{LTV - preLLTV}{LLTV - preLLTV} * preLCF_2 ``` #### 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) 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 Let's walk through an example of how pre-liquidation works in practice: #### Step-by-Step Process ##### Case 1: Pre-Liquidation #### Initial Position Setup Alice deposits 1 WBTC as collateral valued at 100k USDC and borrows 70k USDC. Her initial LTV is calculated as: ```math LTV = 70,000 / 100,000 = 0.70 \quad (70\%) ``` #### 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 When the price of 1 WBTC falls to 84k USDC, the new collateral value becomes 84k USDC. Her LTV then becomes: ```math LTV = 70,000 / 84,000 \approx 0.83 \quad (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 The market continues to move and 1 WBTC reaches 83k USDC, so the collateral value now is 83k USDC. Her updated LTV is: ```math LTV = 70,000 / 83,000 \approx 0.84 \quad (84\%) ``` Now the position is clearly in the pre-liquidation range. Under these conditions, the pre-liquidation close factor is recalculated using the formula: ```math preLCF = \frac{LLTV - LTV}{LLTV - preLLTV} \times preLCF_1 + \frac{LTV - preLLTV}{LLTV - preLLTV} \times preLCF_2 \approx 0.12 ``` Under some assumptions, this means that approximately 12% of the debt becomes eligible for liquidation. #### Executing the Pre-Liquidation A liquidator repays 12% of Alice’s outstanding debt: ```math Debt\ Repaid = 0.12 \times 70,000 = 8,400 \, \text{USDC} ``` With a pre-liquidation incentive factor (preLIF) of roughly 1.04, the seized collateral is calculated as: ```math Collateral\ Seized = 8,400 \times 1.04 \approx 8,736 \, \text{USDC} \quad (\approx 8.7k \, \text{USDC}) ``` 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%. -------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | | **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 | ≈73.5k 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 $3.5k 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 | 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 Morpho has different mechanisms for accounting for bad debts depending on the vault version. ### Morpho Vaults V2 - Loss Socialization Morpho Vault V2 implements an automatic loss socialization mechanism where losses — including bad debt from underlying adapters — are detected and distributed proportionally across all shareholders through share price depreciation. #### How It Works 1. **Loss Detection:** Each adapter reports the actual current value of its investments via a `realAssets()` function. When bad debt occurs in an underlying adapter, this reported value automatically decreases. 2. **Loss Realization:** During interest accrual, the vault compares the reported real asset value to its internally tracked total. If `realAssets` has dropped below the previously recorded `totalAssets`, the vault updates its accounting downward to reflect the loss. 3. **Automatic Socialization:** Share value is determined via `convertToAssets()`, which computes `shares × (totalAssets + 1) / (totalSupply + virtualShares)`. When `totalAssets` decreases, every share redeems for fewer assets. No shares are burned — all shareholders absorb the loss proportionally. #### Important Considerations - **Management fee** continue to accrue even during loss periods. - **Morpho Vault V1.1 caveat:** Since Morpho Vaults V1.1 do not realize bad debt internally, a Morpho Vault V2 supplying to a Morpho Vault V1.1 via a `MorphoVaultV1Adapter` will not reflect the corresponding losses from that allocation. - **Flash loan protection:** The vault includes safeguards against share price manipulation around loss realization events, as losses are only accounted for once per transaction. ### Morpho Vaults V1.0 - 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 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 #### 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? 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? 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? 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? 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? 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? 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 #### 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? The capital savings depend on several factors including market volatility and pre-liquidation parameters. #### 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? 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? 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 Some community members have contributed and provided liquidation bots that could be deployed to liquidate positions. - Morpho Association nor authors of these repositories can be held responsible for any losses or damages that may result from the use of this information. - Users are advised to conduct their own research and exercise caution when applying any strategies or methods described herein. If you are comfortable with these conditions, you can explore the liquidation community section [here](/tools/community/liquidations/) --- 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. ## [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 - **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](/learn/concepts/market/#permissionless-market-creation) - **Transparent Rules**: Clear conditions for lending and borrowing ## Market Identification Markets follow this naming format: `CollateralAsset/LoanAsset (LLTV%, OracleAddress, IRMAddress)` For example: `wstETH/WETH (94.5%, ChainlinkOracleV2-wstETHToWETH, AdaptiveCurveIRM)` ## 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 ### 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 The only Interest Rate Model (IRM) that has been governance-approved is the [AdaptiveCurveIRM](/learn/concepts/irm/). ## Market ID Generator Use this tool to generate a unique market ID from your market parameters: ## 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 - **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. ## [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 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 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](/get-started/resources/contracts/oracles#price), which has a single, standardized function: ```solidity 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 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 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 Please refer to this section of the documentation to deploy a new oracle: [Deploy an Oracle](/curate/tutorials-market-v1/deploying-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 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 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](/learn/resources/risks/) ## Oracle community section Some community members contributed to adapters that could be plugged into oracles. - Morpho Association nor author of the repository cannot be held responsible for any losses or damages that may result from the use of this information. - Users are advised to conduct their own research and exercise caution when applying any strategies or methods described herein. If you are fine with it, jump on the liquidation community section [here](/tools/community/oracles/) ## [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: ## 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 **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 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**: Optional fees that curators can set and collect for reallocations (these fees go to the curator, not to Morpho) 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. ## [Rewards on Morpho](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 ### 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 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 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 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 **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](/build/rewards/get-started) - Technical concepts: [Reward Campaigns](/build/rewards/concepts/reward-campaigns) - Distribution details: [Distribution System](/build/rewards/concepts/distribution-system) ## [Morpho Vault V2](https://docs.morpho.org/learn/concepts/vault-v2/) **Morpho Vault V2** is a protocol for permissionless lending vaults built on top of Morpho Markets V1, Morpho Markets V2 and any future versions of Morpho. While retaining the core principle of simplifying yield generation for passive depositors, Morpho Vault V2 is effectively 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**. ## Key Feature Comparison: Morpho Vaults V1 vs. Morpho Vaults V2 | Feature | Morpho Vault V1 | Morpho Vault V2 | | ----------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | **Protocol Support** | Exclusively Morpho Market V1. | **Future-Proof**. Can add support to Morpho yield sources 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. | ## The Evolution from V1 to V2 Morpho Vault V2 is a significant leap forward, designed for maximum flexibility and control. - **From Specific to Universal**: Vaults V1 were tightly coupled to Morpho Market V1. Morpho Vaults V2 can add support to new Morpho yield sources 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 Morpho Vault V2 ### 1. The Adapter Model: A Universal Gateway to Yield The central innovation of Morpho Vault V2 is the **Adapter** system. An adapter is a smart contract that acts as a translator, containing the logic to interact with a specific 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 `MorphoMarketV1AdapterV2` and `MorphoVaultV1Adapter`. ### 2. Granular Risk Curation: The ID & Cap System Morpho Vault V2 introduces 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 `MorphoMarketV1AdapterV2` 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 Curation Morpho Vault V2 separates 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 noncustodial 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. Some gate implementations can affect noncustodiality guarantees by preventing certain users from depositing to or withdrawing from the vault. ## Advanced Role System Morpho Vault V2 refines 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 - **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). ## Is Morpho Vault V2 Non-Custodial? **Yes, Morpho Vault V2 maintains noncustodial guarantees through three fundamental mechanisms: in-kind redemptions, timelocks, and role-based access control.** Some [gate](#gates-optional-access-control) implementations can affect noncustodiality guarantees by preventing certain users from depositing to or withdrawing from the vault. ### Core Non-Custodial Mechanisms #### 1. In-Kind Redemptions with `forceDeallocate` In-kind redemption in Morpho Vault V2 transfers a user’s position from the vault 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 the vault 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 Morpho Vault V2 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 it. They can always exit by effectively swapping their vault shares for direct positions in the underlying protocols. #### 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 `abdicate`, 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 Morpho Vault V2's 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](/curate/concepts/roles/#morpho-vaults-v2-roles). ### Additional Safety Mechanisms #### 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) 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 **Morpho Vaults V2** use the **Morpho Registry**, the official adapter registry maintained by Morpho governance. This registry defines which adapters are approved for use, ensuring that deposits stay within Morpho-reviewed protocols. When the curator locks (abdicates) the registry, it can never be changed—giving users a strong, permanent guarantee about where their funds can be allocated. Morpho Vaults V2 benefit from the full support of Morpho's infrastructure: - **Full app integration**: Listed in the [Morpho app](https://app.morpho.org) (subject to listing process). - **Curation 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](/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/). #### Immutable Contracts All vault contracts are immutable—no upgrades can change the core noncustodial guarantees after deployment. ### 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 Vaults V2 genuinely noncustodial—users retain ultimate control over their assets even when delegating management to curators and allocators. ## [Morpho Vault V1](https://docs.morpho.org/learn/concepts/vault/) **Morpho Vault V1** is a protocol for permissionless lending vaults built on top of the [Morpho Markets V1](/learn/concepts/market/). ## 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 - **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](/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 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 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 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. ## [Morpho Governance](https://docs.morpho.org/learn/governance/) ## [The MORPHO token](https://docs.morpho.org/learn/governance/morpho-token/) 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](/learn/governance/organization/#morpho-dao-governance) to get the exhaustive list of actions. ## 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 You can find MORPHO token contracts, related contracts addresses as well as Github repositories in the [addresses section](/get-started/resources/addresses/#morpho-token). The MORPHO token has a maximum supply of 1,000,000,000 MORPHO. ## Token Distribution & Vesting The overall distribution of MORPHO tokens, including vested and unvested allocations, as of 7 November 2024. ### 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 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 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 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 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 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 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 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: *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 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](/learn/concepts/rewards/#uniform-rate-programs). ## 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 ### Why are there two MORPHO tokens? What’s 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](/learn/governance/morpho-token/#how-to-wrap-the-legacy-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. Clicking on the `Wrap` button will trigger a modal, showing your Legacy MORPHO token balance and proposing you to wrap it. 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 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) - **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). Feel free to get in touch via the chatbox on **[help.morpho.org](https://help.morpho.org)**. ## [Morpho Governance](https://docs.morpho.org/learn/governance/organization/) 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) (capped at a maximum of 25% of interest paid by borrowers) and setting a set a fee recipient address - Whitelisting new [LLTVs and IRMs](/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 [snapshot.org/morpho.eth](https://snapshot.org/#/s:morpho.eth). 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](/learn/governance/organization/#multisig-and-addresses) whose members are decided by the Morpho governance. ## Morpho Association The Morpho Association is a French nonprofit entity whose mission is to grow Morpho's network effects through research, development and promotion of the Morpho protocol. In practice, the Morpho Association: - Supports the development, growth, security and adoption of the Morpho protocol - Hosts a front end to the Morpho protocol to facilitate the access of new users to Morpho: [morpho.org](http://morpho.org/) - Hosts technical documentation to facilitate the work of new Morpho developers - Holds the intellectual property of open-source codebases such as morpho-blue, metamorpho-v1.1 or vault-v2 and hosts it on the morpho-org GitHub under a GPL3 license. ## Multisig and Addresses | Name | Address/Details | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Morpho Contracts** | See the [Addresses](/get-started/resources/addresses/#1) section | | **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 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](https://docs.morpho.org/learn/resources/risks/) 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 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/). The Morpho apps and smart contracts have been audited extensively by a wide range of security firms, with every new app and feature undergoing audits before release. The full list of audits is available in the [Audits](/get-started/resources/audits/) section. ## 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](/get-started/resources/contracts/) that avoids complexities - The code has been audited by multiple auditors, refer to the [security reviews](/get-started/resources/audits/) section - [Formal verification](/learn/resources/risks/#formal-verifications) has been applied using [Certora](https://www.certora.com/) - One ongoing bug bounty program: [Cantina - $2,500,000](https://cantina.xyz/bounties/35a5f0a1-2ffd-432c-8f3b-77d169add8c3) (Morpho & Morpho vaults) ## 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. Markets with a faulty oracle can lead to loss of funds, and a Morpho Vault V1 that lists such a market has an edge case —detailed [here](/curate/concepts/security-considerations/#faulty-oracles)—, that could also lead to loss of funds. ## 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 ### 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) 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](/learn/concepts/liquidation/#bad-debt). ### 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 ### Vault Governance Risks Key [roles](/curate/concepts/roles/) within a Morpho Vault wield significant power, impacting user interests. Governance structures differ between Vaults V1 and Vaults V2. #### Vaults V2 Governance Vaults V2 introduces a refined role system with clear separation of concerns: - The **Owner** appoints and manages key roles (Curator and Sentinels) but does not inherit their powers. A compromised Owner can replace the Curator, who controls the vault's strategy. - The **Curator** acts as the vault's risk officer, managing adapters, caps, fees, allocators, and gates. Most Curator actions are subject to [timelocks](/curate/concepts/timelock/), giving depositors time to react before changes take effect. - The **Allocators** manage capital allocation between enabled adapters within Curator-set limits. They cannot introduce new risks but can influence yield and liquidity by moving funds between approved yield sources. - The **Sentinels** provide emergency de-risking capabilities. They can revoke pending timelocked actions, decrease caps, and deallocate funds without being allocators. **Key governance mechanisms in V2:** - **Timelocks**: Critical configuration changes require a submission followed by a waiting period before execution. This ensures depositors can always withdraw their assets before changes take effect. - **Abdication**: The Curator can permanently disable specific timelocked functions via [abdication](/curate/tutorials-v2/abdicate-gates/), irreversibly locking configurations. While this provides strong guarantees against future changes, it also removes flexibility. - **Gates**: [Gate contracts](/curate/concepts/gates/) can restrict share and asset transfers. A misconfigured gate could lock users out of deposits or withdrawals. - **Adapter Registry**: Vaults can be restricted to adapters from a specific [registry](/curate/concepts/adapter-registry/). This limits what yield sources the Curator can enable but relies on the registry's governance. - **Fee Caps**: Performance fees are capped at 50% of interest, and management fees at 5% annually, providing depositor protection against excessive fees. #### Vaults V1 Governance - 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 Owner inherits the capabilities of all other roles. - 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. # --- Build --- ## [Build Earn & Borrow Products on Morpho](https://docs.morpho.org/build/) 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 → Earn on App ↗︎ Borrow - Morpho Markets Provide collateral to borrow any asset + Low costs + Higher collateralization factors + Per market rates + Zero fees Build → Borrow on App ↗︎ ## Get Started 1. **Choose your product**: Start with [Earn](/build/earn/get-started) or [Borrow](/build/borrow/get-started) 2. **Select your tools**: Review our [development tools](/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)** ## [Interest Rates](https://docs.morpho.org/build/borrow/concepts/interest-rates/) Understanding how interest rates are determined and how they affect a borrower's position is fundamental to building a safe and transparent borrow integration. In Morpho, the interest a borrower pays is dictated by the market's **Interest Rate Model (IRM)**. ## The Role of the Interest Rate Model (IRM) Each Morpho Market is created with a specific, immutable IRM. This smart contract contains the logic that dynamically calculates the borrow interest rate based on market conditions, primarily the **utilization rate**. - **Utilization Rate:** The ratio of total borrowed assets to total supplied assets in a market. ```math \text{Utilization} = \frac{\text{Total Borrows}}{\text{Total Supply}} ``` - **Governance-Approved IRMs:** Only IRMs that have been approved by Morpho Governance can be used to create new markets. Currently, the primary model is the `AdaptiveCurveIRM`. ### The AdaptiveCurveIRM The `AdaptiveCurveIRM` is designed to maintain market utilization around a target of **90%**. - **When utilization < 90%:** The borrow rate gradually decreases to incentivize more borrowing. - **When utilization > 90%:** The borrow rate rapidly increases to encourage repayments and attract more supply. This mechanism ensures that markets remain capital-efficient while having enough liquidity for withdrawals. For a deeper dive into the mathematical formulas and adaptive mechanics, see the **[IRM Concept Page](/learn/concepts/irm/)**. ## How Interest Accrues on Debt For a borrower, the most important takeaway is that **interest is constantly accruing**, increasing their total debt over time. This directly impacts their position's health. The process is as follows: #### 1. Rate Calculation The IRM calculates the instantaneous `borrowRate` based on the market's current utilization. #### 2. Interest Accrual This rate is applied to the borrower's debt continuously. The amount of interest accrued increases the `totalBorrowAssets` in the market and, proportionally, the asset value of each borrower's `borrowShares`. #### 3. Impact on Health Factor As the debt value increases due to accrued interest, the user's **LTV rises** and their **Health Factor falls**, even if collateral and asset prices remain stable. ```math \text{Health Factor} = \frac{\text{Collateral Value} \times \text{LLTV}}{\text{Initial Debt} + \text{Accrued Interest}} ``` This is a critical concept to communicate to users: their position can become riskier over time simply from interest accrual. ## Onchain State and `accrueInterest` The Morpho contract does not update interest for every block to save gas. Instead, interest is calculated and applied only when a market interaction occurs via the `_accrueInterest` internal function. This function is triggered by actions like `borrow`, `repay`, `supply`, and `withdraw`. **What this means for your integration:** When you fetch a user's position from the contract, the `totalBorrowAssets` value reflects the state at the *last interaction*. To get the up-to-the-second debt value, you must account for the interest accrued since the `lastUpdate` timestamp. Jump on the tutorials to learn how to accrue the interests up to the last block. See the [Get Data Tutorial](/build/borrow/tutorials/get-data#onchain--sdk-required-for-real-time-accuracy) for a practical example. ## Integration Best Practices - **Display Real-Time APY:** Don't just show the instantaneous borrow APY, which can be volatile. Provide users with a time-averaged APY (e.g., 6-hour average) to give a more realistic view of their borrowing costs. - **Educate Users on Accruing Debt:** Your UI should make it clear that the user's debt amount is continuously increasing and that this affects their Health Factor. - **Simulate Interest Impact:** When users are opening a position, provide them with projections of how their Health Factor might change over time due to interest accrual, especially in volatile rate environments. By correctly implementing and displaying interest rate mechanics, you empower users to manage their borrow positions effectively and safely. ## [Liquidation](https://docs.morpho.org/build/borrow/concepts/liquidation/) Liquidation is one of the core mechanism in Morpho. It protects lenders' capital by ensuring that undercollateralized loans are repaid, thereby maintaining the solvency of each market. For any developer integrating a borrowing feature, understanding and clearly communicating how liquidation works is paramount. When a borrower's position becomes too risky, the protocol allows a third party—a **liquidator**—to step in, repay the debt, and seize the borrower's collateral at a discount. ## When Does Liquidation Occur? A position becomes eligible for liquidation the moment its **Health Factor drops to 1 or below**. As a reminder, this happens when the Loan-to-Value (LTV) of a position meets or exceeds the market's immutable Liquidation Loan-to-Value (LLTV) threshold. ```math \text{If} \quad \frac{\text{Debt Value}}{\text{Collateral Value}} \ge \text{LLTV} \quad \implies \quad \text{Position is Liquidatable} ``` This can be caused by: - A decrease in the price of the collateral asset. - An increase in the value of the debt due to accrued interest. ## The Liquidation Process Liquidation on Morpho is a straightforward, economically-driven process. It is not an auction; it's a direct transaction executed by the first liquidator to act. #### 1. An Unhealthy Position is Identified A liquidator (typically an automated bot) detects a position where the Health Factor is ≤ 1. #### 2. Liquidator Repays the Debt The liquidator calls the `liquidate` function on the Morpho contract, repaying a portion or all of the borrower's debt using the loan asset. #### 3. Liquidator Seizes Collateral at a Discount In return for repaying the debt, the liquidator is allowed to seize an equivalent value of the borrower's collateral, plus a bonus. This bonus is the liquidator's incentive and profit. #### 4. The Borrower's Position is Updated The borrower's debt is reduced or eliminated, and their collateral is reduced by the amount seized. ### The Liquidation Incentive Factor (LIF) The "discount" or "bonus" a liquidator receives is determined by the **Liquidation Incentive Factor (LIF)**. This factor is calculated based on the market's LLTV, ensuring that riskier markets (with higher LLTVs) offer a smaller bonus to prevent cascading liquidations. For a market with an **LLTV of 86%**, the **LIF is approximately 1.05**, meaning the liquidator receives a **5% bonus** on the collateral they seize. This entire incentive goes to the liquidator; the Morpho protocol takes no fee. ### Example: A Liquidation Scenario - **Initial State**: A user has a position in a market with an LLTV of 86%. Their debt has grown to **$87,000**, while their collateral value has dropped to **$100,000**. - **Health Check**: The LTV is 87% (`87k / 100k`), which is greater than the 86% LLTV. The position is liquidatable. - **Liquidation**: A liquidator repays the full **$87,000** debt. - **Collateral Seized**: The liquidator seizes `$87,000 * 1.05` (LIF) = **$91,350** worth of the borrower's collateral. - **Outcome**: - **Borrower**: Their debt is cleared, but they lose $91,350 of their $100,000 collateral, incurring a loss of **$4,350**. - **Liquidator**: Profits by **$4,350** (minus gas and transaction costs). ### Bad Debt In extreme cases where the collateral's value drops so fast that it becomes less than the debt (`LTV > 100%`), a liquidation might not cover the full loan. The remaining unpaid debt is known as **bad debt**. This represents a loss for lenders in that market. Morpho's design, including its risk-isolated markets and conservative LLTVs, aims to make this a rare event. ## Integration Best Practices for Developers Your primary goal as an integrator is to help your users avoid liquidation. 1. **Prioritize Health Factor Display:** The Health Factor should be the most prominent metric for any user with an open borrow position. Use clear visual cues (colors, gauges) to communicate risk. 2. **Educate About the "Point of No Return":** Clearly display the market's LLTV and the user's current LTV. The user must understand that crossing the LLTV threshold is the trigger for liquidation. 3. **Implement Proactive Alerts:** Build notifications within your application to warn users when their Health Factor drops to a cautionary level (e.g., below 1.1). 4. **Simulate Transactions:** Before a user confirms a `borrow` or `withdrawCollateral` transaction, show them the resulting Health Factor. This prevents them from unknowingly putting their position at risk. By treating liquidation as a core part of the user experience, you can build a safer and more trustworthy borrowing platform. ## Protection Options for Borrowers Jump to the following section to understand how you can protect your users when offering a borrow product by integrating the pre-liquidation mechanism. ## [Collateral, LTV & Health](https://docs.morpho.org/build/borrow/concepts/ltv/) When a user borrows from a Morpho Market, their position's safety is determined by the relationship between their collateral, their debt, and the market's risk parameters. Understanding and clearly displaying these metrics is one of the most critical responsibilities when building a borrow integration. This page explains the core concepts of Collateral, Loan-to-Value (LTV), and Health Factor. ## Collateral In Morpho, **collateral** is the asset a user supplies to a market to secure their loan. For example, in a `wstETH/WETH` market, `wstETH` is the collateral. This collateral acts as a guarantee for lenders that the protocol can recover funds if the borrower defaults. A user's collateral is specific to each market; it is not cross-margined at the market level. Also, the action to supply collateral does not generate yield. ## Understanding Loan-To-Value (LTV) It's essential to understand how LTV is calculated and what it represents. ### 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: ```math \text{LTV} = \frac{\text{BORROWED\_AMOUNT}}{\text{COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN}} \times 100\% ``` Where: - **`BORROWED_AMOUNT`**: The amount of borrowed assets of the user (in token base units) - **`COLLATERAL_VALUE_IN_LOAN_TOKEN`**: The value of the collateral in terms of the loan token The collateral value in loan token units is calculated as: ```math \text{COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN} = \frac{\text{COLLATERAL\_AMOUNT } \times \text{ ORACLE\_PRICE}}{\text{ORACLE\_PRICE\_SCALE}} ``` Where: - **`COLLATERAL_AMOUNT`**: The amount of collateral assets provided by the user (in token base units) - **`ORACLE_PRICE`**: The oracle price returned by the oracle of the market (scaled by ORACLE_PRICE_SCALE) - **`ORACLE_PRICE_SCALE`**: A scaling factor of 10^36 used by the protocol for price normalization ### Liquidation Loan-to-Value (LLTV) The **Liquidation Loan-to-Value (LLTV)** is the maximum LTV a position can reach before it becomes eligible for liquidation. It is a fixed, immutable parameter for each market, chosen from a governance-approved list at the time of creation. The rule is simple and absolute: **If `LTV` ≥ `LLTV`, the position can be liquidated.** For example, if a market's LLTV is 86%, a user's position is at risk of liquidation as soon as their LTV reaches or exceeds 86%. ### Health Factor The Health Factor is another crucial metric that indicates how close a position is to liquidation: ```math \text{HEALTH\_FACTOR} = \frac{\text{COLLATERAL\_VALUE\_IN\_LOAN\_TOKEN} \times \text{LLTV}}{\text{BORROWED\_AMOUNT}} ``` Where: - **`LLTV`**: The Liquidation Loan-To-Value threshold set for the market (e.g., 0.86 or 86%), expressed as a WAD (10^18 scaled value, like 860000000000000000) 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. - For oracle implementation details, see the [dedicated oracle section](/curate/tutorials-market-v1/deploying-oracle/) - WAD represents a common scaling factor in DeFi of 10^18 used for representing decimal numbers in integer arithmetic Let's walk through a concrete example of calculating LTV and Health Factor for a position on Morpho: **Given values (with assumptions):** - Borrowed amount: 150,000 USDC (150,000,000,000 base units with 6 decimals) - Collateral amount: 2 cbBTC (200,000,000 base units with 8 decimals) - Oracle price: 1 × 10^39 (means 1 cbBTC = 100000 USDC). This is supposedly the value returned by the price function in the oracle used in the related market - Oracle price scale: 10^36 - LLTV: 86% (expressed as 0.86 × 10^18 or 860,000,000,000,000,000 in WAD units) #### Calculate the collateral value in loan token units ```typescript // All calculations use BigInt (suffixed with 'n') to handle large numbers precisely const collateralValueInLoanToken = (collateralAmount * oraclePrice) / ORACLE_PRICE_SCALE; // = (200,000,000n * 1,000,000,000,000,000,000,000,000,000,000,000,000,000n) / 10n**36n // = 200,000,000,000 base units of loan token (USDC) ``` #### Calculate the current LTV ```typescript // Constants const WAD = 10n ** 18n; // Standard scaling factor (10^18) // Example values const borrowedAmount = 150_000_000_000n; // 150 billion units (e.g., USDC with 6 decimals) const collateralValueInLoanToken = 200_000_000_000n; // 200 billion units /** * Current LTV Calculation * ---------------------- * * Step 1: Calculate the raw LTV ratio, preserving precision with WAD */ const currentLTV = (borrowedAmount * WAD) / collateralValueInLoanToken; // = (150,000,000,000n * 10n**18n) / 200,000,000,000n // = 750,000,000,000,000,000n (scaled by WAD, representing 0.75 or 75%) /** * Option 1: Theoretical Formula * ---------------------------- * In theory, the conversion to percentage is simply: */ // Theoretical formula (doesn't work directly with BigInt) // currentLTVPercentage = (currentLTV / WAD) * 100 // Implementation of theoretical formula (using Number conversion) const theoreticalLTVPercentage = (Number(currentLTV) / Number(WAD)) * 100; // = 75.0000% /** * Option 2: Practical Display Implementation * ---------------------------------------- * For precise display with 4 decimal places, we: * 1. Scale up by the display factor (percentage * decimal precision) * 2. Divide by WAD to normalize * 3. Convert to Number and adjust for decimal places */ // Scale factor = 100 (for percentage) * 10000 (for 4 decimal places) = 1,000,000 const displayScaleFactor = 1_000_000n; const currentLTVPercentageScaled = (currentLTV * displayScaleFactor) / WAD; // = 750_000n (represents 75.0000%) // Convert the scaled BigInt result to a human-readable number const displayLTVPercentage = Number(currentLTVPercentageScaled) / 10000; // = 75.0000% (when displayed with 4 decimal places) ``` #### Calculate the health factor ```typescript // Since LLTV is stored as a WAD, we need to account for scaling const healthFactor = (collateralValueInLoanToken * lltv) / borrowedAmount; // = (200,000,000,000,000n * 860,000,000,000,000,000n) / 150,000,000,000n // = 1,146,666,666,666,666,666 (scaled by WAD) // Convert to decimal const healthFactorDisplay = Number(healthFactor) / Number(WAD); // = 1.1467 (when converted to a human-readable decimal) ``` Since the Health Factor is greater than 1.0 (1.1467), this position is healthy and has a safety margin before liquidation could occur. #### Summary of Position: - Current LTV: 75.00% - Max LTV (LLTV): 86.00% - Health Factor: 1.1467 - Status: Healthy - Liquidation Buffer: 11.00% (difference between current LTV and max LTV) This shows a position with an LTV of 75%, which is below the LLTV threshold of 86%. The Health Factor of 1.1467 confirms that the position is healthy with a 11% safety margin before liquidation. - For oracle implementation details, see the [dedicated oracle section](/curate/tutorials-market-v1/deploying-oracle/) - For examples of LTV calculations in Solidity, refer to [this code](https://github.com/morpho-org/morpho-blue/blob/12b8a453643d5ef9d55abd88b9f8cfa866882aa5/src/Morpho.sol#L532-L536) ## The Role of Oracles The accuracy of LTV and Health Factor calculations depends on the **Oracle Price**. - **Dynamic Pricing:** The oracle provides the real-time exchange rate between the collateral and loan assets. This price is the most dynamic variable in the health calculation. - **Oracle Complexity:** The oracle for a market might not be a single price feed. It could be a combination of feeds (e.g., `wstETH -> stETH` and `stETH -> ETH`) or rely on other onchain data. - **Risk Exposure:** The reliability of your LTV and Health Factor display is a direct reflection of the oracle's reliability. Any latency, inaccuracy, or manipulation of the oracle's price can directly impact user positions. When displaying market information, it is crucial to also provide transparency about the oracle being used. ## Integration Best Practices For any application with a borrow interface, a primary goal should be to help users avoid liquidation. 1. **Display Health Factor Prominently:** This should be the most visible metric on any position management dashboard. Use visual aids like colors (green, yellow, red) or progress bars to indicate safety levels. 2. **Clearly State the LLTV:** Users must know the exact "point of no return" for their position. Display the market's `LLTV` alongside the user's current `LTV`. 3. **Implement Proactive Alerts:** When a user's Health Factor drops below a certain safe threshold (e.g., `1.1`), trigger notifications in your UI or via other channels to prompt them to add more collateral or repay part of their loan. 4. **Incorporate Safety Buffers:** Do not allow users to borrow the maximum amount that would place their Health Factor exactly at `1.0`. Your interface should enforce a safety margin, for example, by limiting borrows to a Health Factor of `1.05` or higher. 5. **Simulate Transactions:** Before submitting a `borrow` or `withdrawCollateral` transaction, simulate its effect on the user's Health Factor. Show the user what their new Health Factor will be *before* they sign the transaction. By following these best practices, you can build a borrow experience that is not only functional but also safe and transparent for your users. **Next Up:** Learn what happens when the Health Factor drops below 1.0 in the **[Liquidation concept page](/learn/concepts/liquidation/)**. ## [Market Mechanics](https://docs.morpho.org/build/borrow/concepts/market-mechanics/) 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 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 This struct tracks the overall state of a single, isolated market. ```solidity 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 This struct tracks an individual user's position within a specific market. ```solidity 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 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 - **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 - **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 The "price" of a share is its exchange rate to the underlying asset. This price is dynamic and increases as interest accrues. ```solidity // 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 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` ```solidity 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` ```solidity 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 - **`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`. To learn more about how position health is calculated and managed, see the **[Collateral, LTV & Health concept page](/build/borrow/concepts/ltv/)**. ## Practical Implementation Snippets ### Supplying Collateral & Borrowing (Asset-First) ```typescript // 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) ```typescript // 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 - **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. - **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. ## [Pre-Liquidation (Auto-Deleveraging)](https://docs.morpho.org/build/borrow/concepts/preliquidation/) **Pre-Liquidation**, also known as Auto-Deleveraging, is an optional, opt-in mechanism that offers an additional layer of safety for borrowers on Morpho. It allows for small, partial liquidations to occur *before* a position reaches the standard liquidation threshold, helping to automatically reduce risk and prevent a full, more costly liquidation. Think of it as a "safety zone" where a position can be gently corrected instead of falling off a cliff. ## How Pre-Liquidation Works Standard liquidation is an all-or-nothing event triggered when a position's Health Factor hits 1.0. Pre-liquidation introduces a buffer zone. - **Standard Liquidation**: Triggers when `LTV >= LLTV`. - **Pre-Liquidation**: Triggers when `preLLTV <= LTV < LLTV`. A borrower can opt-in to a pre-liquidation contract, defining a `preLLTV` (Pre-Liquidation Loan-to-Value) that is lower than the market's `LLTV`. If their LTV enters this zone, a portion of their debt can be liquidated early. ### Key Benefits for the Borrower 1. **Avoids Full Liquidation:** The primary benefit is preventing a single, large liquidation event. Instead of losing a significant chunk of their collateral at once, the user experiences smaller, incremental deleveraging. 2. **Reduced Losses:** The incentive (bonus) for pre-liquidators is typically lower than the standard Liquidation Incentive Factor (LIF). This means the penalty paid by the borrower during a partial, pre-liquidation is smaller. 3. **Automatic Risk Management:** It acts as an automated safety net. If a user is away from their screen and their position becomes risky, the pre-liquidation mechanism can help bring their position back to a healthier LTV without their manual intervention. ### The Pre-Liquidation Mechanism When a position enters the pre-liquidation zone, the mechanism works as follows: - **Partial Repayment:** A pre-liquidator repays a small percentage of the user's debt. The exact percentage is dynamic and increases as the LTV gets closer to the `LLTV`. This is controlled by the **preLCF (Pre-Liquidation Close Factor)**. - **Smaller Incentive:** The pre-liquidator receives a smaller bonus, defined by the **preLIF (Pre-Liquidation Incentive Factor)**. - **Position Deleveraged:** After the pre-liquidation, the borrower's debt is lower, and their LTV is brought back down toward the `preLLTV`, returning them to a safer state. ### Example: Standard vs. Pre-Liquidation Consider a user with a position in a market where `LLTV` is 86% and they've opted into pre-liquidation with a `preLLTV` of 83%. | Scenario | Standard Liquidation (No Pre-liquidation) | With Pre-Liquidation | | --------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | **Trigger** | The collateral price drops until LTV hits 86%. | The collateral price drops until LTV hits 84%. | | **Liquidation Event** | A liquidator repays **100%** of the debt. | A pre-liquidator repays **~12%** of the debt. | | **Penalty (Incentive)** | The liquidator receives a **~5%** bonus (LIF). | The pre-liquidator receives a **~4%** bonus (preLIF). | | **Outcome for Borrower** | Position is fully closed. The borrower incurs a significant one-time loss. | Position remains open, but with less debt and collateral. The loss is much smaller. | In this case, pre-liquidation acted as a circuit breaker, preventing a more damaging full liquidation. ### Integration Considerations While pre-liquidation is a powerful safety feature, it is an advanced concept. - **Opt-In Nature:** As an integrator, you can choose whether to offer this feature to your users. Because it is opt-in, it requires user authorization. - **Parameter Complexity:** Pre-liquidation introduces additional parameters (`preLLTV`, `preLCF`, etc.) that need to be managed and clearly explained. - **User Education:** If you integrate this feature, it's essential to educate users on how it works, why it's beneficial, and what they are authorizing. For most integrations, focusing on a robust and clear implementation of the **standard liquidation** warnings and user flows is the highest priority. Offering pre-liquidation can be a valuable addition for more sophisticated users or as a distinguishing feature of your application. ## [Public Allocator: Just-in-Time Liquidity](https://docs.morpho.org/build/borrow/concepts/public-allocator/) Morpho's design of isolated markets provides unparalleled risk containment. However, it can also lead to **fragmented liquidity**, where capital is spread across multiple markets instead of being concentrated in a single pool. For a borrower, this could mean a market they want to use doesn't have enough liquidity for their desired loan size. The **Public Allocator** is the elegant solution to this problem. It is a smart contract that functions as a liquidity router, providing **just-in-time liquidity** by reallocating assets between markets on demand. ## What is the Public Allocator? The Public Allocator is a publicly callable contract that can move a vault's idle or under-utilized assets into a market where a borrower needs them, right at the moment they need them. From a borrower's perspective, this transforms a series of isolated, smaller pools into a single, deep source of liquidity, combining the safety of isolated risk with the convenience of a pooled lending model. ## How It Works for a Borrower Imagine a user wants to borrow 1,000 WETH from the `wstETH/WETH` market, but that specific market only has 200 WETH available. #### 1. Liquidity Request The user (or your application on their behalf) initiates the borrow. The system detects the 800 WETH shortfall. #### 2. Public Allocator Triggered Instead of failing, a call is made to the `Public Allocator`. It instantly finds the 800 WETH from other markets where the same lending vault has capital (e.g., from an idle pool or an under-utilized `rETH/WETH` market). #### 3. Liquidity Reallocated The Public Allocator executes a `reallocate` function, moving the 800 WETH into the target `wstETH/WETH` market. #### 4. Borrow Executed The `wstETH/WETH` market now has 1,000 WETH available. The user's borrow transaction succeeds seamlessly. When integrated with a **Bundler**, this entire process—reallocation and borrowing—happens **atomically within a single transaction**. The user experience is simple: they see deep liquidity and execute one transaction. ## Curator Controls: Flow Caps This on-demand reallocation is not a free-for-all. Vault curators retain full control over how their liquidity can be moved by setting **Flow Caps** on the Public Allocator for each market. - `maxIn`: The maximum amount of assets that can be moved *into* a market by the Public Allocator. - `maxOut`: The maximum amount that can be moved *out of* a market. These guardrails ensure that while liquidity is flexible, it always operates within the risk parameters defined by the vault's curator. ## Benefits for Your Integration - **Offer Deeper Liquidity:** Allow your users to execute large borrows without worrying about the liquidity of a single market. - **Improve User Experience:** Abstract away the complexity of fragmented liquidity. Users interact with one market and get the liquidity of many. - **Maintain Security:** Benefit from a pool-like experience while retaining the underlying risk isolation of Morpho's core architecture. Now that you understand what the Public Allocator does, learn how to integrate it into your borrowing flow. ➡️ **Next: [Triggering the Public Allocator Tutorial](/build/borrow/tutorials/public-allocator)** ## [Rewards for Borrowers](https://docs.morpho.org/build/borrow/concepts/rewards/) Borrowers on Morpho Markets can earn rewards that offset borrowing costs or even generate net positive yields. These incentives are designed to bootstrap markets, attract liquidity, and encourage specific borrowing behaviors. ## Overview As a borrower on Morpho, you can earn rewards for borrowing an asset from a market. **Net Cost Calculation:** ``` Net Borrow APY = Borrow APY - Borrow Rewards APR ``` It is also possible to incentivize a simple collateral deposit (without the borrow action required). In favorable conditions, rewards can exceed borrow costs, resulting in **negative net APY** (borrowers earn while borrowing). Rewards are claimable on the side via the Merkl distribution system and do not impact user LTV. Even though the Net Borrow APY can be negative, user loan will increase and so its LTV. **Borrow Rewards:** - Incentives for borrowing an asset - Accrue based on outstanding borrow balance - Offset borrowing costs directly ### Net Cost Display Priority For borrow products, users care most about **net cost after all rewards**: - Display net APY prominently - Highlight when borrowing becomes profitable (negative net APY) - Show breakdown: borrow cost - borrow rewards ## Distribution System Rewards distribution has migrated from the Morpho URD system to Merkl. New campaigns use Merkl, while historical rewards may still be claimable via the legacy URD system. The claiming process is **identical** for all Morpho users, regardless of whether they're depositors, borrowers, or collateral suppliers. **For complete details on distribution systems, see:** - [Distribution System](/build/rewards/concepts/distribution-system) - [Reward Campaigns](/build/rewards/concepts/reward-campaigns) ## Learn More For comprehensive information about integrating rewards: - **[Rewards Integration Guide](/build/rewards/get-started)**: Complete overview and integration paths - **[Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)**: Complete API queries and calculations - **[Claim Rewards](/build/rewards/tutorials/claim-rewards)**: Implementation for both Merkl and URD - **[Integrate Display](/build/rewards/tutorials/integrate-display)**: UI/UX best practices ## Implementation For practical implementation guidance specific to borrow products, see: - [Integrate Rewards for Borrow Products](/build/borrow/tutorials/rewards) ## [Morpho Markets for Borrow products](https://docs.morpho.org/build/borrow/get-started/) 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 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](/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 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 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](/build/rewards/get-started). ## Assets Flow - Borrow Understanding the complete flow of assets is crucial for a proper integration: ### 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 - 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 - 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 - 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 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 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. ## [Guide: Integrating Gasless Crypto-Backed Loans with Gelato](https://docs.morpho.org/build/borrow/guides/gelato/) This tutorial provides a complete guide for developers to integrate noncustodial, 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 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: ``` ┌─────────────────┐ │ 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 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 First, install all necessary packages from Gelato, Dynamic, and other required libraries. ```bash npm install @gelatonetwork/smartwallet @dynamic-labs/sdk-react-core @dynamic-labs/wagmi-connector @tanstack/react-query viem wagmi ``` #### 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. Never hardcode API keys or sensitive IDs in your client-side code. Use environment variables with a framework-specific prefix (e.g., `NEXT_PUBLIC_` or `VITE_`). #### Step 3: Define Constants and ABIs For a clean implementation, define your contract addresses, ABIs, and market parameters in a separate constants file. ```typescript // 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 Wrap your application's root with the `GelatoSmartWalletContextProvider` and `QueryClientProvider`. This makes the smart wallet client and user session available throughout your component tree. ```tsx // 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 3: Production Considerations #### 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 | 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 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 ↗ Gelato Smart Wallet SDK Docs Dive deeper into the Gelato SDK's features, including different account types and payment options. Read Docs ↗ Morpho Borrow Concepts Understand the core concepts of Morpho Markets, including LTV, health factor, and liquidations. Learn More → Community Support Use the Morpho Help Page to ask questions and get help from Morpho. Reach out ↗ ## [Borrow: Developer Resources](https://docs.morpho.org/build/borrow/resources/all/) 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 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](/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](/get-started/resources/contracts/morpho/) - [Public Allocator](/get-started/resources/contracts/public-allocator/) - [Bundlers](/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. ## 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](/build/borrow/tutorials/get-data#get-data) - **Morpho Subgraphs**: For developers who prefer querying via The Graph protocol. - **Tutorial**: [Using Subgraphs for Markets](/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. - **Learn more**: [Introduction to Morpho SDKs](/tools/offchain/sdks/get-started/) ## Code & Examples - **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](/tools/community/liquidations/) ## [Supply Collateral, Borrow, Repay & Withdraw Collateral](https://docs.morpho.org/build/borrow/tutorials/assets-flow/) 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 two primary methods of interaction: 1. **Direct Smart Contract Integration** using Solidity. 2. **Offchain Integration** using the Morpho SDK with TypeScript and Viem. ## 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 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](/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) 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 First, the user must supply a collateral asset to the market. This requires approving the Morpho contract to spend the collateral token. ```solidity 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 Once collateral is supplied, the user can borrow the loan asset against it. ```solidity // 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); ``` Your contract must check that the borrow amount does not exceed the user's borrowing capacity, which is determined by their collateral value and the market's LLTV. See the [LTV & Health Concept Page](/build/borrow/concepts/ltv/). ### Step 3: Repay Debt To repay the loan, the user must approve the Morpho contract to spend the loan token. ```solidity [Partial Repay] // 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, ""); ``` ```solidity [Full Repay] // Shares-first approach (Recommended for full repayment) ( , uint128 borrowShares, ) = morpho.position(marketParams.id(), msg.sender); // Note: You need to approve a sufficient amount of the loan token first. // The exact asset amount can be calculated offchain or via a helper contract. IERC20(marketParams.loanToken).approve(address(morpho), type(uint256).max); morpho.repay(marketParams, 0, borrowShares, msg.sender, ""); ``` ### Step 4: Withdraw Collateral After the debt is fully or partially repaid, the user can withdraw their collateral, provided their position remains healthy. ```solidity 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 Here is a complete example contract demonstrating the full borrow-repay cycle. The following contract has not been audited and is for educational purposes only. Refer to the [full snippets repository](https://github.com/morpho-org/morpho-blue-snippets) for more details. ```solidity // 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) This method is ideal for dApp frontends or backend services. We'll use TypeScript with **Viem**. ### Step 1: Setup Install dependencies and set up your Viem client. ```bash npm install viem @morpho-org/blue-sdk @morpho-org/morpho-ts ``` ```typescript 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 This example combines supplying collateral and borrowing. In a real app, these would likely be separate user actions. ```typescript 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 This example shows a full repayment using the `shares` parameter. ```typescript // 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], }); } ``` ## [Get Data](https://docs.morpho.org/build/borrow/tutorials/get-data/) ## Before Starting In this tutorial, you'll see three main ways to fetch data for Morpho Markets: - **API**: Using the Morpho public API. This is the easiest and most direct way to get comprehensive, indexed data for most applications. - **Smart Contract**: Fetching data directly onchain using read functions (or offchain via libraries like Viem). This is best for real-time, trustless data needed within other smart contracts or sensitive applications. - **SDK**: Using the Morpho SDKs for pre-built abstractions that handle complex calculations (like interest accrual) and simplify development. API Endpoint: [api.morpho.org/graphql](https://api.morpho.org/graphql) For each topic below, you'll find guides for each method where applicable. This structure helps you choose the best approach for your specific use case. ## Discovery and Listing ### Markets List Quickly retrieve a list of all markets or filter for specific ones, like those whitelisted for incentives. ```graphql [Whitelisted Markets] // [!include ~/snippets/api/all-queries.graphql:markets-list-whitelisted-markets] ``` {" "} This example demonstrates how to discover new markets by listening to `CreateMarket` events from the Morpho V1 contract. The script shows how to: - Monitor market creation events within a specific block range - Parse market parameters including loan/collateral tokens, oracle, IRM, and LLTV - Extract and format market IDs and configuration details - Display results in both detailed and table formats for easy analysis - Handle LLTV conversion from WAD format to percentage ```typescript // [!include ~/snippets/typescript/50-markets-list.ts:imports] // [!include ~/snippets/typescript/50-markets-list.ts:client-setup] // [!include ~/snippets/typescript/50-markets-list.ts:constants] // [!include ~/snippets/typescript/50-markets-list.ts:market-creation-types] // [!include ~/snippets/typescript/50-markets-list.ts:helper-functions] // [!include ~/snippets/typescript/50-markets-list.ts:fetch-market-creations] // [!include ~/snippets/typescript/50-markets-list.ts:display-results] // [!include ~/snippets/typescript/50-markets-list.ts:main-execution] ``` **Example Output:** ``` Fetching market creations from block 22867292 to 22867298... Found 1 market creation(s) ✅ --- New Morpho Markets Created --- ✅ --- Market Summary --- Total Markets Created: 1 --- Market Details --- 1. Market ID: 0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540 Loan Token: 0xdAC17F958D2ee523a2206206994597C13D831ec7 Collateral Token: 0x8ddac7aa85Ce324AF75a3bFcB876375555d43BB8 Oracle: 0xF470...66e0 IRM: 0x870a...00BC LLTV: 91.50% Block: 22867295 Transaction: 0x4c9e1efb7e86f8bb15c01f3f109d88ec0a0e0d553140628dfc9d852dcc902d51 --- Markets Table --- ID | Loan Token | Collateral | LLTV | Block -------------------------------------------------------------------+---------------+--------------+----------+---------- 0x9a3320...03c3d540 | 0xdAC1...1ec7 | 0x8dda...3BB8 | 91.50% | 22867295 ---------------------------------------- ``` This example demonstrates real-time market discovery by monitoring blockchain events, which is essential for tracking new lending opportunities and market configurations as they're created. {" "} You can discover markets by listening for the `CreateMarket` event emitted from the core `Morpho` contract: ```solidity // Listen to CreateMarket events event CreateMarket( bytes32 indexed id, MarketParams marketParams ); // Market parameters structure struct MarketParams { address loanToken; address collateralToken; address oracle; address irm; uint256 lltv; } // Get market details by ID function idToMarketParams(bytes32 id) external view returns (MarketParams memory); // Check if market exists function market(bytes32 id) external view returns ( uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee ); ``` **Key Functions:** - **Event Monitoring**: Listen to `CreateMarket` events for new markets - **Market Resolution**: `idToMarketParams(id)` returns full market configuration - **Market State**: `market(id)` returns current market liquidity and state - **Market ID**: Computed as `keccak256(abi.encode(marketParams))` **Event Logs**: See the [Etherscan events log](https://etherscan.io/address/0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb#events) for real examples. ### Market Parameters Fetch the core, immutable parameters for one or more markets. --- ```graphql [All Markets] // [!include ~/snippets/api/all-queries.graphql:market-parameters-all-markets] ``` --- ```graphql [Unique Market] // [!include ~/snippets/api/all-queries.graphql:market-parameters-unique-market] ``` {" "} This example demonstrates comprehensive market parameter operations including: - Decoding market IDs to parameters using `idToMarketParams` - Encoding market parameters to generate market IDs using keccak256 - Validating market ID integrity by round-trip encoding/decoding - Checking market existence and fetching token information - Understanding the relationship between market parameters and their unique identifiers ```typescript // [!include ~/snippets/typescript/51-market-params.ts:imports] // [!include ~/snippets/typescript/51-market-params.ts:client-setup] // [!include ~/snippets/typescript/51-market-params.ts:abis-and-constants] // [!include ~/snippets/typescript/51-market-params.ts:types] // [!include ~/snippets/typescript/51-market-params.ts:helper-functions] // [!include ~/snippets/typescript/51-market-params.ts:core-logic] // [!include ~/snippets/typescript/51-market-params.ts:display-results] // [!include ~/snippets/typescript/51-market-params.ts:main-execution] ``` **Example Output:** ``` === Market ID Operations Demo === 1. Decoding market ID to parameters... ✅ Market parameters decoded successfully: Loan Token: 0xdAC17F958D2ee523a2206206994597C13D831ec7 Collateral Token: 0x8ddac7aa85Ce324AF75a3bFcB876375555d43BB8 Oracle: 0xF47020f01e77257Fe86B9ECb36552486E0Ae66e0 IRM: 0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC LLTV: 91.5% 2. Re-encoding parameters to market ID... Original ID: 0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540 Computed ID: 0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540 3. Validation result: ✅ Market ID validation: PASS 4. Checking market existence... ✅ Market exists onchain: YES Fetching market information for ID: 0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540 ✅ --- Morpho Market Parameters --- ✅ --- Market Overview --- Market ID: 0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540 Exists: ✅ Yes --- Market Parameters --- Loan Token: Tether USD (USDT) Address: 0xdAC17F958D2ee523a2206206994597C13D831ec7 Decimals: 6 Collateral Token: Pendle Market Wrapped (PENDLE-LPT-WRAPPED) Address: 0x8ddac7aa85Ce324AF75a3bFcB876375555d43BB8 Decimals: 18 Oracle: 0xF47020f01e77257Fe86B9ECb36552486E0Ae66e0 IRM (Interest Rate Model): 0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC LLTV (Loan-to-Value): 91.50% --- Encoded Parameters --- LLTV (Raw): 915000000000000000 Market ID Validation: ✅ Valid ---------------------------------------- ``` This example demonstrates the bidirectional relationship between market parameters and market IDs, essential for understanding how Morpho Markets are uniquely identified and accessed. {" "} You can retrieve market parameters by using the `idToMarketParams` view function on the `Morpho` contract, passing the `marketId`. ```solidity // Get market parameters from market ID ( address loanToken, address collateralToken, address oracle, address irm, uint256 lltv ) = IMorpho(morpho).idToMarketParams(marketId); // Generate market ID from parameters struct MarketParams { address loanToken; address collateralToken; address oracle; address irm; uint256 lltv; } // Market ID is the keccak256 hash of encoded parameters bytes32 marketId = keccak256(abi.encode(marketParams)); // Check if market exists ( uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee ) = IMorpho(morpho).market(marketId); // Market exists if any state value > 0 bool marketExists = totalSupplyAssets > 0 || totalSupplyShares > 0 || totalBorrowAssets > 0 || totalBorrowShares > 0; ``` **Key Functions:** - **Parameter Lookup**: `idToMarketParams(marketId)` returns all market configuration - **Market ID Generation**: `keccak256(abi.encode(marketParams))` creates unique identifier - **Existence Check**: `market(marketId)` returns state (non-zero values indicate existence) - **Parameter Validation**: Re-encode parameters to verify market ID integrity **Important Notes:** - Market IDs are deterministic based on parameters - Non-existent markets return zero values from `idToMarketParams` - LLTV is stored in WAD format (18 decimals) ## Market Metrics ### Total Collateral, Borrow & Supply Get the real-time state of liquidity and debt in a market. --- ```graphql [All Markets] // [!include ~/snippets/api/all-queries.graphql:market-totals-all-markets] ``` --- ```graphql [Unique Market] // [!include ~/snippets/api/all-queries.graphql:market-totals-unique-market] ``` {" "} This example demonstrates comprehensive market liquidity analysis including: - Real-time interest accrual for supply and borrow assets - Collateral tracking (which doesn't accrue interest) - Market utilization and available liquidity calculations - Comparison between stale (last update) and current (accrued) values - Efficient batch processing for multiple markets - Important distinction: only loan token amounts (supply/borrow) accrue interest, collateral remains static The `market()` view function returns values that **do not include** interest accrued since the last onchain interaction. For accurate, up-to-the-second data, you must use the SDK or manually calculate the accrued interest. ```typescript // [!include ~/snippets/typescript/53-market-liquidity.ts:imports] // [!include ~/snippets/typescript/53-market-liquidity.ts:client-setup] // [!include ~/snippets/typescript/53-market-liquidity.ts:abis-and-constants] // [!include ~/snippets/typescript/53-market-liquidity.ts:types] // [!include ~/snippets/typescript/53-market-liquidity.ts:math-helpers] // [!include ~/snippets/typescript/53-market-liquidity.ts:core-logic] // [!include ~/snippets/typescript/53-market-liquidity.ts:display-results] // [!include ~/snippets/typescript/53-market-liquidity.ts:main-execution] ``` **Example Output:** ``` Fetching liquidity information for market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 Note: Total collateral calculation requires tracking all position holders ✅ --- Morpho Market Liquidity Information --- ✅ --- Market Overview --- Market ID: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 Loan Token: USD Coin (USDC) Collateral Token: Coinbase Wrapped BTC (cbBTC) LLTV: 86.00% --- Current Liquidity (Real-time) --- Total Supply: 522083875.989369 USDC Total Borrow: 481268818.125629 USDC Total Collateral: 0 cbBTC Available Liquidity: 40815057.86374 USDC Utilization: 92.18% --- Interest Accrual --- Last Update: 2025-11-07T10:57:35.000Z Interest Accrued: 0 USDC --- Stale vs Current Comparison --- Stale Total Supply: 522083875.989369 USDC Current Total Supply: 522083875.989369 USDC Stale Total Borrow: 481268818.125629 USDC Current Total Borrow: 481268818.125629 USDC --- Raw Values --- Total Supply Assets: 522083875989369 Total Borrow Assets: 481268818125629 Total Collateral Assets: 0 Utilization (WAD): 921822795644868562 ---------------------------------------- Fetching liquidity information for 1 markets... Fetching liquidity information for market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 Note: Total collateral calculation requires tracking all position holders ✅ --- Markets Liquidity Summary --- ✅ Market ID | Loan/Collateral | Total Supply | Total Borrow | Utilization | Available -----------------------------+---------------------+--------------+--------------+-------------+---------- 0x64d65c...883fcc64 | USDC/cbBTC | 522,083,876 | 481,268,818 | 92.2% | 40,815,058 ---------------------------------------- ``` This example shows the crucial difference between stale market data (from last onchain update) and current real-time data (with interest accrued), essential for accurate liquidity analysis. {" "} - As it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain. Feel free to refer to the [Morpho Market Snippets](https://github.com/morpho-org/morpho-blue-snippets/blob/main/src/morpho-blue/MorphoBlueSnippets.sol) for extensive example. ```solidity // [!include ~/snippets/solidity/morpho-market-snippets.sol:marketTotalSupply] // [!include ~/snippets/solidity/morpho-market-snippets.sol:marketTotalBorrow] ``` The total collateral on a given market is not easily retrievable onchain. One has to index all positions, and sum through the morpho.position(market, user) calls. ### Market APY (Native & Rewards) Get the real-time APY, interest rates, and accrual information for markets. The API provides both the native APY from borrowing/lending and the additional APR from reward incentives. ###### Important UI Reference one might find on apps: 1. `avgApy` represents the Native APY (6h average vault APY excluding rewards, before deducting the performance fee) 2. `avgNetApy` represents the complete APY (6h average vault APY including rewards, after deducting the performance fee) --- ```graphql [All Markets] // [!include ~/snippets/api/all-queries.graphql:market-apy-all-markets] ``` --- ```graphql [Unique Market] // [!include ~/snippets/api/all-queries.graphql:market-apy-unique-market] ``` {" "} This example demonstrates comprehensive market APY calculations including: - Real-time interest accrual from last update to current block - Borrow and supply APY calculations using Interest Rate Models (IRM) - Market utilization and fee impact on supply rates - Interest compounding using Taylor expansion for precision - Comparison between stale and accrued market states - Efficient batch processing for multiple markets ```typescript // [!include ~/snippets/typescript/52-market-apys.ts:imports] // [!include ~/snippets/typescript/52-market-apys.ts:client-setup] // [!include ~/snippets/typescript/52-market-apys.ts:abis-and-constants] // [!include ~/snippets/typescript/52-market-apys.ts:types] // [!include ~/snippets/typescript/52-market-apys.ts:math-helpers] // [!include ~/snippets/typescript/52-market-apys.ts:core-logic] // [!include ~/snippets/typescript/52-market-apys.ts:display-results] // [!include ~/snippets/typescript/52-market-apys.ts:main-execution] ``` **Example Output:** ``` Fetching APY information for market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 ✅ --- Morpho Market APY Information --- ✅ --- Market Overview --- Market ID: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 Loan Token: USD Coin (USDC) Collateral Token: Coinbase Wrapped BTC (cbBTC) LLTV: 86.00% --- Market Liquidity (Real-time) --- Total Supply: 522363906.351897 USDC Total Borrow: 481268778.178246 USDC Utilization: 92.13% --- Interest Rates --- Borrow APY: 7.5419% Supply APY: 6.9486% Borrow Rate (per second): 0.000000002305661164 --- Interest Accrual --- Last Update: 2025-11-07T10:56:59.000Z Interest Accrued: 0 USDC Market Fee: 0.0000% --- Raw Values (WAD) --- Borrow APY: 75418869301348230 Supply APY: 69485557173609405 Utilization: 921328545724660480 ---------------------------------------- Fetching APY information for 1 markets... Fetching APY information for market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 ✅ --- Markets APY Summary --- ✅ Market ID | Loan/Collateral | Borrow APY | Supply APY | Utilization -----------------------------+---------------------+------------+------------+------------ 0x64d65c...883fcc64 | USDC/cbBTC | 7.54% | 6.95% | 92.13% ---------------------------------------- ``` This example shows how to calculate real-time market rates, including the crucial interest accrual step that updates market state from the last onchain update to the current block timestamp. {" "} As it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain. Feel free to refer to the [Morpho Market Snippets](https://github.com/morpho-org/morpho-blue-snippets/blob/main/src/morpho-blue/MorphoBlueSnippets.sol) for extensive example. ```solidity // [!include ~/snippets/solidity/morpho-market-snippets.sol:supplyAPY] // [!include ~/snippets/solidity/morpho-market-snippets.sol:borrowAPY] ``` ### Interactive Interest Rate Visualization Understanding how the [AdaptiveCurveIRM](/learn/concepts/irm/#the-adaptivecurveirm) works in practice is crucial for developers integrating with Morpho Markets. This section provides a hands-on guide to implementing and visualizing the interest rate model calculations. The Morpho protocol uses a kinked interest rate model (IRM) with a target utilization of 90%. Below you'll find three approaches to working with this model: using the API, implementing it yourself, or understanding the mathematical foundation. **Fetch Pre-Calculated Curve Data** The easiest way to display the interest rate model is to use the Morpho API, which provides pre-calculated curve data with 101 data points (0% to 100% utilization). --- **Step 1: Query the GraphQL Endpoint** ```graphql query GetMarketIrmCurve($uniqueKey: String!, $chainId: Int!) { marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) { id irmAddress state { id utilization } currentIrmCurve { utilization supplyApy borrowApy } } } ``` API Endpoint: [api.morpho.org/graphql](https://api.morpho.org/graphql?explorerURLState=N4IgJg9gxgrgtgUwHYBcQC4QEcYIE4CeABAOIIoCyAhngNbkCSecAwjHgG4IAUAJDEgCWOBAGkEBdEQDKKPIKQBzAIQAaIrygALKgoZgpDVGo1J4AI3wB5AGYAFCApQBnQ6gCURYAB083pEREcDT0KABCBACqQiLiBNwCwrhxUvwxyRLq2rpI%2BqnZemCePn4BgUSCYL7%2B5RXMAIJgYHgIzs7VZYHOKFQoCF4dtYGVg0MwKIIANoIAXr2CEEijgQC%2By0SweC2oTKzsXAOlQ0TmEFsQAO71AA4E610w19eTBDd3R2MT03MTi%2BtrHwB-iBSBAqhAHBogio5kmrQwIBKNSI3hABVyVQwRAAjKpRgB6fEbcxhAAqLHxkWkABEWEEQuRRqjErEJKipKiAAwADwAbAAWMC8gCsUAAnFQAExgMXYqAAZl5YGFvJs5ig-OlvLFCDFAHYxfL5cL5ZLOdjteZ5WAbLz5eYbGLJXqABw6yVQF1e%2BU2KBQAWovEfVFmOCWPC2BxOdpYsyTSYdFYgFZAA) This endpoint returns: - Market identification data - Current utilization state - Pre-calculated interest rate curve with 101 data points --- **Step 2: Integrate with Frontend Component** ```typescript const ChartInterestRateModelClient = ({ queryResult }) => { const marketData = queryResult?.data?.marketByUniqueKey; const shouldShowNoDataError = useMemo( () => marketData?.currentIrmCurve?.length === 0 || marketData?.irmAddress === undefined, [marketData?.currentIrmCurve?.length, marketData?.irmAddress] ); return ( ); }; ``` **Benefits of API Approach:** - No need to implement rate calculations - Pre-calculated data optimized for visualization - Always up-to-date with latest protocol parameters - Minimal code required for integration {" "} **Build Your Own Rate Calculator** For developers who need to calculate rates independently or integrate calculations into backend systems, you can implement the algorithm directly. --- **Step 1: Core Algorithm** The interest rate calculation formula: ```typescript function rateAtUtilization(apyAtTarget, utilization, fee) { let borrowApy; const minApy = Math.expm1(Math.log1p(apyAtTarget) / 4); const maxApy = Math.expm1(Math.log1p(apyAtTarget) * 4); if (utilization <= 0.9) { borrowApy = minApy + (apyAtTarget - minApy) * (utilization / 0.9); } else { borrowApy = ((maxApy - apyAtTarget) / 0.1) * (utilization - 0.9) + apyAtTarget; } const supplyApy = borrowApy * (1 - fee) * utilization; return { borrowApy, supplyApy, }; } ``` --- **Step 2: Required Parameters** To use this function, you need: 1. **`apyAtTarget`**: The target borrow APY at 90% utilization - This is derived from the `rateAtTarget` value stored in the [AdaptiveCurveIRM contract](https://docs.morpho.org/get-started/resources/contracts/irm/#mappings) - Retrieve `rateAtTarget` for your market's IRM from the contract - Convert to APY using: `apyAtTarget = (e^(rateAtTarget × secondsPerYear) - 1)` - Example: If `rateAtTarget = 1512768697` (per second rate), this converts to approximately 4.9% APY 2. **`utilization`**: Current utilization ratio (0 to 1) - Calculate as: `totalBorrow / totalSupply` - Use for calculating rates at specific points 3. **`fee`**: Protocol fee percentage (e.g., 0.1 for 10%) - Check [market state](/get-started/resources/contracts/morpho/#market-struct) for the exact fee - This affects the supply APY calculation --- **Step 3: Generate Curve Data** ```typescript // Generate 101 data points for visualization const generateCurveData = (apyAtTarget, fee) => { const dataPoints = []; for (let i = 0; i <= 100; i++) { const utilization = i / 100; const { borrowApy, supplyApy } = rateAtUtilization( apyAtTarget, utilization, fee ); dataPoints.push({ utilization, borrowApy, supplyApy }); } return dataPoints; }; ``` **Use Cases for Direct Implementation:** - Real-time rate calculations in smart contracts - Custom analytics and modeling - Integration with proprietary systems - Independent verification of API data {" "} **Understanding the Kinked Interest Rate Model** The AdaptiveCurveIRM uses a two-slope (kinked) model with distinct behavior before and after the target utilization. --- **Key Parameters** 1. **Target Utilization**: 90% (the kink point) 2. **APY Range**: From minApy (~1/4 target) to maxApy (~4x target) 3. **Formula Elements**: - `minApy = Math.expm1(Math.log1p(apyAtTarget) / 4)` - `maxApy = Math.expm1(Math.log1p(apyAtTarget) * 4)` --- **Two-Slope Behavior** **Below Target (0% - 90% utilization):** ``` borrowApy = minApy + (apyAtTarget - minApy) * (utilization / 0.9) ``` - Linear increase from minApy to apyAtTarget - Gentle slope to encourage borrowing - Supply rates gradually increase with utilization **Above Target (90% - 100% utilization):** ``` borrowApy = ((maxApy - apyAtTarget) / 0.1) * (utilization - 0.9) + apyAtTarget ``` - Steeper linear increase to maxApy - Discourages over-utilization - Incentivizes suppliers at high utilization --- **Mathematical Properties at Key Points** **At 0% utilization:** - Borrow APY = minApy (~1/4 of target APY) - Supply APY = 0 (as utilization is 0) - Lowest rates to attract initial borrowers **At 90% utilization (target):** - Borrow APY = apyAtTarget - Supply APY = apyAtTarget × (1 - fee) × 0.9 - Optimal balance point for the market **At 100% utilization:** - Borrow APY = maxApy (~4x target APY) - Supply APY = maxApy × (1 - fee) - Maximum rates to incentivize supply **Supply APY Formula:** ``` supplyApy = borrowApy × (1 - fee) × utilization ``` - Protocol fee is deducted from borrow interest - Supply APY scales with utilization For more on the AdaptiveCurveIRM, explore the [technical reference](/get-started/resources/contracts/irm/). ## Asset Information ### Assets Get metadata and pricing for specific tokens. --- ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:assets-with-price] ``` {" "} This example demonstrates comprehensive asset information retrieval including: - Basic ERC20 metadata (name, symbol, decimals, total supply) - Asset validation and error handling for invalid tokens - EIP-2612 permit support detection for gasless approvals - User balance and allowance tracking - Portfolio analysis across multiple assets - Efficient batch processing using multicall - Formatted display with large number abbreviations (K, M, B, T) ```typescript // [!include ~/snippets/typescript/54-assets.ts:imports] // [!include ~/snippets/typescript/54-assets.ts:client-setup] // [!include ~/snippets/typescript/54-assets.ts:abis-and-constants] // [!include ~/snippets/typescript/54-assets.ts:types] // [!include ~/snippets/typescript/54-assets.ts:helper-functions] // [!include ~/snippets/typescript/54-assets.ts:core-logic] // [!include ~/snippets/typescript/54-assets.ts:display-results] // [!include ~/snippets/typescript/54-assets.ts:main-execution] ``` **Example Output:** ``` === Asset Information Demo === 1. Single Asset Info (USDC): ✅ --- Asset Information --- ✅ --- Basic Info --- Address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 Name: USD Coin Symbol: USDC Decimals: 6 Valid ERC20: ✅ Yes --- Supply Info --- Total Supply: 41233587998.984993 USDC Total Supply (formatted): 41.23B USDC Total Supply (raw): 41233587998984993 --- Extended Features --- Supports Permit (EIP-2612): ✅ Yes Version: 2 Domain Separator: 0x06c37168a7db5138defc7866392bb87a741f9b3d104deb5094588ce041cae335 ---------------------------------------- 2. Multiple Assets Info: Fetching information for 5 assets... ✅ --- Assets Summary Table --- ✅ Valid Assets: 5 | Invalid Assets: 0 --- Valid Assets --- Symbol | Name | Decimals | Total Supply | Permit -------------+-------------------------+----------+--------------------+------- USDC | USD Coin | 6 | 41.23B | ✅ WETH | Wrapped Ether | 18 | 2.54M | ❌ USDT | Tether USD | 6 | 74.81B | ❌ DAI | Dai Stablecoin | 18 | 3.64B | ✅ WBTC | Wrapped BTC | 8 | 128.85K | ❌ ---------------------------------------- 3. User Portfolio (Zero Address - for demo): Fetching asset portfolio for user: 0x0000000000000000000000000000000000000000 ✅ --- User Asset Portfolio --- ✅ --- Portfolio Overview --- User Address: 0x0000000000000000000000000000000000000000 Total Assets: 3 Valid Assets: 3 Invalid Assets: 0 --- Assets with Balance --- Symbol | Balance | Allowance (if set) -------------+----------------------+------------------- WETH | 1,086.556748 | Not checked USDT | 201,290.112228 | Not checked ---------------------------------------- === Demo Complete === ``` This example provides complete asset analysis capabilities essential for DeFi applications, including validation, metadata extraction, and portfolio management. ## Position Tracking ### User Position on Market ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:user-positions] ``` {" "} This example demonstrates comprehensive user position analysis including: - Real-time interest accrual for accurate borrow/supply amounts - Health factor calculation with liquidation risk assessment - Collateral valuation using oracle prices - Position safety metrics (LTV, liquidation buffer, liquidation price) - Multiple market position tracking and portfolio analysis - Conversion between shares and assets with proper rounding - Risk assessment and liquidation threshold calculations User positions require real-time interest accrual to show accurate debt amounts. The raw `position()` function returns shares, which must be converted to assets using current market state for precise calculations. ```typescript // [!include ~/snippets/typescript/55-user-position.ts:imports] // [!include ~/snippets/typescript/55-user-position.ts:client-setup] // [!include ~/snippets/typescript/55-user-position.ts:abis-and-constants] // [!include ~/snippets/typescript/55-user-position.ts:types] // [!include ~/snippets/typescript/55-user-position.ts:math-helpers] // [!include ~/snippets/typescript/55-user-position.ts:core-logic] // [!include ~/snippets/typescript/55-user-position.ts:display-results] // [!include ~/snippets/typescript/55-user-position.ts:main-execution] ``` **Example Output:** ``` === User Position Analysis Demo === User has position in market: ✅ Yes Fetching position for user: 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f in market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 ✅ --- User Position Analysis --- ✅ --- User & Market Info --- User: 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f Market ID: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 Loan Token: USD Coin (USDC) Collateral Token: Coinbase Wrapped BTC (cbBTC) Max LTV: 86.00% --- Position Assets (Real-time) --- Supply: 0 USDC Borrow: 75883503.679379 USDC Collateral: 1291.00894824 cbBTC --- Health Metrics --- Health Factor: 1.472724337032200696 Is Healthy: ✅ Yes Current LTV: 58.40% LTV Utilization: 67.90% Liquidation Buffer: 35871978.968515 USDC --- Price & Risk Info --- Collateral Price: 1006.5634 USDC per cbBTC Liquidation Price: 683470337724024509145.488769364009452427844856671826760481 USDC per cbBTC Price Drop to Liquidation: 32.10% --- Interest Accrual --- Last Update: 2025-11-07T10:55:11.000Z Interest Accrued: 66.30546 USDC --- Raw Position Data --- Supply Shares: 0 Borrow Shares: 71029026727778728163 Collateral (raw): 129100894824 ---------------------------------------- Fetching positions for user 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f across 1 markets... Fetching position for user: 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f in market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 ✅ --- User Positions Summary --- ✅ User: 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f Total Positions: 1 Market | Loan/Collateral | Borrowed | Collateral | Health Factor | Status -----------------------------+---------------------+-------------+-------------+---------------+-------- 0x64d65c...883fcc64 | USDC/cbBTC | 75,883,503.68 | 1,291.01 | 1.473 | ✅ Healthy ---------------------------------------- === Demo Complete === ``` This example shows a real borrower position with high LTV utilization (99.95%) but still healthy due to the high maximum LTV (98%) of this particular market. The position demonstrates the importance of real-time interest accrual for accurate risk assessment. ### All Market Positions ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:positions] ``` {" "} ## Risk & Oracle Data ### Oracle Data ```graphql [All Markets] // [!include ~/snippets/api/all-queries.graphql:oracle-data-all-markets] ``` --- ```graphql [Unique Market] // [!include ~/snippets/api/all-queries.graphql:oracle-data-unique-market] ``` {" "} ### Liquidations ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:liquidations] ``` {" "} ### Market Warnings Warning `type` can be: - `unrecognized_collateral_asset`: The collateral asset used in the market is not a part of the recognized token list - `unrecognized_oracle` : The oracle used in the market is not recognized - `unrecognized_loan_asset`: The loan asset used in the market is not a part of our recognized token list - `bad_debt_unrealized` & RED level: This market has significant unrealized bad debt (>25 BPS total supply) - `bad_debt_unrealized` & YELLOW level: This market has some unrealized bad debt (>$10k) - `bad_debt_realized`: This market has some realized bad debt (>10 BPS of total supply) Warning `level` is either: - YELLOW - RED --- ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:markets-warnings] ``` {" "} ## Integration ### Vault Listing The following query corresponds to which vault has this market in its supply queue --- ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:vault-listing] ``` {" "} ## 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). Available options 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 options is not mandatory but it is advised to specify them to control the specific data returned. If no options 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. `historicalState` field is not accessible through the markets list queries. Historical data is only available through individual market queries like `market(id: "")` or `marketByUniqueKey(uniqueKey: "")`. ### Historical APYs The example below mirrors the structure shown in the Morpho API sandbox, so you can copy/paste it directly when testing queries. ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:historical-apys] ``` --- with the following variables ```json { "uniqueKey": "0x608929d6de2a10bacf1046ff157ae38df5b9f466fb89413211efb8f63c63833a", "options": { "startTimestamp": 1707749700, "endTimestamp": 1708354500, "interval": "HOUR" } } ``` {" "} ### Historical Market States ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:historical-market-states] ``` {" "} ### Historical Asset Price ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:historical-asset-price] ``` {" "} ## [Triggering the Public Allocator](https://docs.morpho.org/build/borrow/tutorials/public-allocator/) This tutorial explains how to trigger a reallocation using the Public Allocator to provide just-in-time liquidity for a borrow transaction. Before you begin, make sure you understand the core concepts behind the Public Allocator and why it's a powerful tool for enhancing liquidity. **Review the [Public Allocator Concept Page](/build/borrow/concepts/public-allocator) first.** ## The Core Action: `reallocateTo` The central function of the Public Allocator is `reallocateTo`. This function pulls liquidity from a specified list of source markets within a vault and supplies it to a single destination market. ```solidity function reallocateTo( address vault, Withdrawal[] calldata withdrawals, MarketParams calldata supplyMarketParams ) external payable; ``` - **`vault`**: The vault whose funds are being reallocated. - **`withdrawals`**: An array of structs, each specifying a source market and the amount to withdraw. - **`supplyMarketParams`**: The destination market where all withdrawn funds will be deposited. ## Method 1: Manual Trigger via Etherscan (For Learning) Manually triggering the `reallocateTo` function on a block explorer is a great way to understand its inputs. #### 1. Check Prerequisites Before sending a transaction, verify: - The Public Allocator has the **allocator role** for the target vault. - The source markets have sufficient **`maxOut`** capacity and the destination market has sufficient **`maxIn`** capacity. - You have the correct `marketId` for all source markets and the `marketParams` for the destination market. - You know the `fee` required for the transaction, which can be read from the `fee(vaultAddress)` view function on the Public Allocator contract. #### 2. Structure the `withdrawals` Array The `withdrawals` array must be **sorted in ascending order by market ID**. #### 3. Execute the Transaction On a block explorer like Etherscan, navigate to the Public Allocator contract, connect your wallet, and call `reallocateTo`. You must send the required `fee` as the `value` of the transaction. **Example Input:** This example reallocates 70 WETH from an Idle Market and 800 WETH from a wstETH market, supplying a total of 870 WETH to an rETH market. ```json // Payable Amount (Value): [Fee in ETH, e.g., 0.001] { "vault": "0x38989bba00bdf8181f4082995b3deae96163ac5d", "withdrawals": [ // Withdrawal from Idle Market (assuming it has the lower marketId) { "marketParams": { "loanToken": "0xc02...", "collateralToken": "0x000...", ... }, "amount": "70000000000000000000" }, // Withdrawal from wstETH/WETH market { "marketParams": { "loanToken": "0xc02...", "collateralToken": "0x7f3...", ... }, "amount": "800000000000000000000" } ], "supplyMarketParams": { "loanToken": "0xc02...", "collateralToken": "0xae7...", ... } } ``` After this transaction, the rETH market will have an additional 870 WETH of liquidity available to borrow. ## Method 2: Programmatic Trigger (SDK & API) For a dApp integration, you will programmatically construct and send this transaction. The recommended flow is to use the Morpho API to find available liquidity and the SDK to simulate and execute. The general logic is: 1. **Check Target Market Liquidity**: See if the user's borrow can be fulfilled without reallocation. 2. **Query Available Liquidity**: If not, use the Morpho API to query the `publicAllocatorSharedLiquidity` for the target market. This returns a list of all markets in all vaults that can reallocate funds to your target. 3. **Simulate and Build**: Select the necessary source markets from the API response and construct the `withdrawals` array. The Morpho SDKs are ideal for simulating the transaction to ensure it will succeed and to calculate the precise inputs. **Example Implementation: Bundle Reallocation and Borrow** This tutorial assumes you are already familiar with Morpho’s core packages (such as [blue-sdk](/tools/offchain/sdks/blue-sdk/) and [blue-sdk-viem](/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 [earn-basic-app](https://github.com/morpho-org/earn-basic-app) repositories. ### 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 Install the bundler package along with its required peer dependencies: ```bash yarn add @morpho-org/bundler-sdk-viem @morpho-org/blue-sdk @morpho-org/morpho-ts viem ``` #### 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: ```typescript 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 #### 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. You'll need the following input operation: - 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 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. ### Key Functions #### 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. ```typescript const { operations, steps } = populateBundle( inputOperations, simulationState, bundlingOptions ); ``` #### 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. ```typescript const optimizedOperations = finalizeBundle( operations, simulationState, receiverAddress, unwrapTokensSet, unwrapSlippage ); ``` #### 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 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 You can enable public reallocation via the BundlingOptions parameter: ```typescript const bundlingOptions: BundlingOptions = { withSimplePermit: new Set(["0xTokenAddress1", "0xTokenAddress2"]), publicAllocatorOptions: { enabled: true, supplyTargetUtilization: { [marketId]: 905000000000000000n, // For a specific market }, defaultSupplyTargetUtilization: 905000000000000000n, }, }; ``` These options allow you to: - Force simple permit flows on certain tokens - Trigger liquidity reallocation when the market’s utilization exceeds a target threshold ### 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 Let's walk through a practical example that demonstrates how to bundle a borrow action with public reallocation enabled, if needed. You can find a complete working implementation in our [bundler-basic-app](https://github.com/morpho-org/bundler-basic-app) repository. ```typescript 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 borrow Morpho operation, via the Bundler * @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 Borrow = 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_Borrow", sender: user, address: morpho, args: { id: marketId, assets: amountBorrow, onBehalf: user, receiver: user, slippage: DEFAULT_SLIPPAGE_TOLERANCE, }, }, ]); }; ``` #### 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. For a detailed, working example of how to implement this logic using TypeScript, Viem, and the Morpho API, refer to the **public-allocator-scripts** repository. **[View the Public Allocator Simulation Script on GitHub](https://github.com/morpho-org/public-allocator-scripts/blob/main/scripts/api/apiPublicAllocatorSimulated.ts)** ## [Integrate Rewards for Borrow Products](https://docs.morpho.org/build/borrow/tutorials/rewards/) Borrowers on Morpho Markets can earn rewards that offset borrowing costs or even generate net positive yields. Integrating rewards display and claiming is essential for showing users their true cost of borrowing. ## What's Unique for Borrow Products When building borrow products, understand that borrowers earn rewards for borrowing an asset from a market **Critical integration requirement:** ``` Net Borrow APY = Borrow APY - Borrow Rewards APR ``` It is also possible to incentivize a simple collateral deposit (without the borrow action required). When rewards exceed costs, net APY becomes negative (profitable borrowing). Rewards are claimable on the side via the Merkl distribution system and do not impact user LTV. Even though the Net Borrow APY can be negative, user loan will increase and so its LTV. ## Integration Steps Follow the centralized rewards tutorials with borrow-specific considerations: ### Step 1: Fetch Market Rewards Data **Follow:** [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) **Borrow-specific notes:** - Query `state.rewards` on market object - Look for `borrowApr` (rewards for borrowing) - No weighted averaging needed (unlike vaults) ### Step 2: Display Rewards in Your UI **Follow:** [Integrate Rewards Display](/build/rewards/tutorials/integrate-display) **Borrow-specific notes:** - Show **net cost** prominently (borrow cost - all rewards) - Highlight when borrowing becomes profitable (negative net APY) - Break down: borrow cost, borrow rewards - List reward tokens with their respective APRs - Calculate per-position rewards based on user amounts ### Step 3: Enable Reward Claiming **Follow:** [Claim Rewards](/build/rewards/tutorials/claim-rewards) **Important:** The claiming process is **identical** for all Morpho users (borrowers, vault depositors, market suppliers). Both Merkl and URD use the same claiming flow regardless of how rewards were earned. ## Complete Integration Example For a full working reference implementation: **See:** [Complete Rewards Integration Guide](/build/rewards/guides/complete-integration) This guide includes production-ready code using the [morpho-merkl-recipe](https://github.com/morpho-org/merkl-morpho-recipe). ## Quick Reference | Task | Main Tutorial | Borrow-Specific Consideration | |---------------------------|--------------------------------------------------------------------|---------------------------------------| | **Understanding rewards** | [Reward Campaigns](/build/rewards/concepts/reward-campaigns) | Understand dual eligibility | | **Distribution system** | [Distribution System](/build/rewards/concepts/distribution-system) | Same Merkl/URD for all users | | **Fetch rewards** | [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) | Query single location, no aggregation | | **Display rewards** | [Integrate Display](/build/rewards/tutorials/integrate-display) | Show net cost after rewards | | **Claim rewards** | [Claim Rewards](/build/rewards/tutorials/claim-rewards) | Same process for all users | ## Need Help? - **Conceptual questions**: [Rewards for Borrowers Concept](/build/borrow/concepts/rewards) - **Main rewards guide**: [Rewards Integration Guide](/build/rewards/get-started) - **Technical support**: [help.morpho.org](https://help.morpho.org) - **Example code**: [morpho-merkl-recipe](https://github.com/morpho-org/merkl-morpho-recipe) ## [How can distributors generate revenue on Morpho?](https://docs.morpho.org/build/earn/concepts/generate-revenue/) **There are different ways to generate revenue on Morpho.** Curators and distributor channels have different ways to charge fees. A distributor channel is any platform, application, or service that integrates Morpho's functionality to offer it to their own users. This includes wallets, DeFi aggregators, portfolio management apps, or custom interfaces that embed Morpho vaults. These distributors make Morpho accessible to users who might not otherwise directly interact with the Morpho protocol, and they can earn fees by facilitating these interactions. To generate revenue, a distributor has several possibilities developed below: - Own its own revenue layer (a Fee Wrapper or a Vault V2 Wrapper) - Have an agreement with a curator (onchain or offchain) ## Fees Morpho Vault V2 can charge 2 types of fees, while Morpho Vault V1 has only one: | Fees | Vault V2 | Vault V1 | | ----------------------------------------------------- | -------------- | ------------- | | Performance fee (taken on the native yield) | ✅  0% → 50% | ✅  0% → 50% | | Management fee (taken on the Assets Under Curation) | ✅  0% → 5% | ❌ | ## Architecture Here is the setup of the current Earn architecture with USDC as an example Here is the vault model illustrating asset flow in terms of allocation ## Examples of possible configurations ## Selection Guide | Model | Control | Trust Required | Complexity | Best For | | --- | --- | --- | --- | --- | | **Fee Wrapper** | High | None | Low | B2B distribution, per-customer vaults | | **V2 Wrapper** | High | None | Low | Independent distributors | | **Offchain Agreement** | Shared | High | Medium | Strategic partnerships | | **Onchain Splitter** | Shared | None | High | Formal trustless partnerships | ------------------------- | ------------------------------------------------------------------------------- | | **ERC-4626 Compliant** | All standard vault functions work as expected | | **Immutably Bound** | Bound to a single Morpho Vault V2 at deployment. Can **not** be changed | | **Fee Flexibility** | Owner can configure performance fees (up to 50%) and management fees (up to 5%) | | **Simplified Configuration** | Risk management functions are abdicated, making operation simpler | | **Shared Liquidity** | Users share the liquidity of the underlying Morpho Vault V2 | #### Use Cases - **B2B Distribution**: Distributors can deploy one Fee Wrapper per customer, each with custom fee configurations - **Revenue Sharing**: Split native yield between the distribution channel and end users (e.g., 50/50 split via fee configuration) - **White-Label Products**: Distributor can offer Morpho yield under their own brand with their own fee structure
**Fee Wrapper details** #### Yield and Rewards **Native Yield (Inside ERC-4626 Flow)** Native yield comes from interest paid by borrowers on underlying Morpho Markets. It accrues automatically to shares over time, requiring no separate claim, shares simply appreciate in value. Users withdraw the same token they deposited (e.g., USDC) plus accrued interest. Performance and management fees are applied to this yield. **External Rewards (Outside ERC-4626 Flow)** External rewards (e.g., MORPHO tokens) come from incentives provided by Morpho governance, market creators, or token issuers, and are distributed via Merkl (updated every 8 hours). These rewards require a separate claim action through Merkl and are automatically forwarded to end depositors by default. It is possible to implement custom distribution, for this specific reward routing (e.g., distributor claims rewards instead of users), coordinate with the Merkl team for address remapping configuration. #### Integration Guide Exact calls and formulas so partners can integrate the same post-fee APY logic directly. **1) Onchain reads** ``` feeWrapper.adapters(0) → adapter address adapter.morphoVaultV1() → underlying Morpho vault address (Vault V2) feeWrapper.performanceFee() → wrapper perf fee (WAD) feeWrapper.managementFee() → wrapper mgmt fee per second (WAD) ``` > The on-chain `managementFee()` returns a **per-second** rate. Multiply by `365 × 24 × 3600` to get the annual rate. The API `managementFee` field is already annualized. **2) Morpho API call** Endpoint: `POST https://api.morpho.org/graphql` Supported chain IDs on the Morpho API are available [here](/tools/offchain/api/get-started/#supported-networks). ```graphql query FeeWrapperAPY($underlyingVault: String!, $chainId: Int!) { underlying: vaultV2ByAddress(address: $underlyingVault, chainId: $chainId) { avgApy performanceFee managementFee rewards { asset { address, symbol } supplyApr } } } ``` with variables: ```graphql { "underlyingVault": "underlyingVault_address", "chainId": 1 } ``` | Field | Description | | --------------------- | ----------------------------------------------------------------------------------------- | | `avgApy` | Realized average APY from share price, **before** the vault's own fees, excluding rewards. We use `avgApy` instead of `avgNetApy` because `avgNetApy` is already net of the underlying vault's fees and includes rewards, which makes the two-layer fee math confusing | | `performanceFee` | Fraction (e.g., 0.10 for 10%) | | `managementFee` | Annual fraction (e.g., 0.02 for 2%) | | `rewards[].supplyApr` | Individual external reward APRs | **3) APY computation** ``` adapterYield = avgApy × (1 − underlyingPerfFee) − underlyingMgmtFee wrapperPerfFeeDeduction = max(adapterYield, 0) × wrapperPerfFee nativeYield = adapterYield − wrapperPerfFeeDeduction − wrapperMgmtFee rewardsApr = sum(rewards[].supplyApr) netApy = nativeYield + rewardsApr // when rewards pass through to depositors ``` > If rewards are redirected via Merkl address remapping, omit `rewardsApr` from the final sum (end users do not receive them). #### Deployment The simplest deployment method uses the FeeWrapperDeployer periphery contract: - [FeeWrapperDeployer source code](https://github.com/morpho-org/vault-v2/blob/main/src/periphery/FeeWrapperDeployer.sol) - [Fee Wrapper Demo App](https://fee-wrapper-demo.vercel.app/) - Educational tool to help with deployment Find the factory addresses in [addresses section](/get-started/resources/addresses/). #### Security Considerations **What the Owner CAN Do:** - Change performance fees (up to 50%, timelocked) - Change management fees (up to 5%, timelocked) - Change fee recipients (timelocked) - Add/remove allocators (timelocked) **What the Owner CANNOT Do:** - Change the underlying vault (abdicated) - Add new adapters (abdicated) - Remove the existing adapter (abdicated) - Access user funds directly - Prevent users from exiting (via forceDeallocate)
--- ### 2. Offchain Agreement Model **Setup:** Distributor and curator establish a legal revenue-sharing agreement for liquidity provided. **Two Options:** **Option A - New Dedicated Vault:** - Curator launches new vault (V1 or V2) exclusively for distributor's users - Fee split negotiated up-front (e.g., 50/50 on performance fees) - Clean attribution of liquidity and fees --- **Option B - Existing Vault:** - Distributor directs users to existing vault - Revenue share calculated based on tracked liquidity contribution - Requires tracking mechanism (transaction mapping, user addresses, time-weighted deposits) **Considerations:** - Legal contract enforces agreement - Option B requires reliable attribution system - Settlement handled offchain (periodic payouts) **Use Case:** Best for strategic partnerships where trust exists or when onchain complexity isn't warranted. --- ### 3. Onchain Splitter Contract Model **Setup:** Smart contract automatically splits fees between curator and distributor based on pre-defined terms. **Requirements:** - Dedicated new vault (V1 or V2) for the partnership - Splitter contract receives fee recipient role - Automated distribution of fees to both parties **Fee Flow:** 1. Vault accrues performance/management fees 2. Fees sent to splitter contract 3. Contract automatically distributes per agreement (e.g., 60% curator / 40% distributor, or 50/50) **Advantages:** - Trustless execution - Transparent onchain tracking - No manual settlement required **Trade-offs:** - Requires dedicated vault (curator unlikely to share existing vault) - Additional smart contract complexity - Gas costs for splitting operations **Use Case:** Best for formal partnerships requiring trustless, transparent revenue sharing with onchain guarantees. ## [Rewards for Lenders](https://docs.morpho.org/build/earn/concepts/rewards/) Vault depositors on Morpho can earn additional rewards beyond base lending yield through incentive campaigns. These rewards significantly enhance total returns and are a key feature of competitive earn products. ## Overview When you deposit into a Morpho Vault, you can earn rewards from **two distinct sources**: 1. **Direct Vault Campaigns**: Rewards distributed directly to vault depositors. Morpho Vault V2 allocating into Morpho Vault V1 will be detected on Merkl (see [rewards section](/build/rewards/concepts/reward-campaigns#reward-forwarding)) and forward the rewards to its users. 2. **Forwarded Market Campaigns**: Rewards earned from underlying markets where the vault allocates liquidity The total yield a depositor earns combines the native lending APY with reward APR from both sources: ``` Net APY = Native Vault APY + Vault Campaign APR + Forwarded Market Campaign APR ``` ## What Makes Vault Rewards Unique ### Reward Forwarding This is the key differentiator for vault depositors. When a vault allocates liquidity to underlying Morpho Markets that have active supply campaigns, those market-level rewards are **automatically forwarded** to vault depositors. **How it works:** 1. A Morpho Market has an active supply campaign 2. Your vault allocates liquidity to that market as a supplier 3. The vault contract earns those market rewards 4. Rewards are automatically reallocated to individual vault depositors 5. You claim these forwarded rewards directly **Why this matters:** - You benefit from ALL active campaigns across the markets your vault uses - Vault curators optimize allocations, and you receive rewards automatically - More capital-efficient than directly supplying to individual markets ### Complete APY Components The net APY shown to users combines multiple components: ``` Net APY = Native APY + Underlying Token Yield + Rewards APR - Performance Fee ``` Where: - **Native APY**: Native vault yield before fees and rewards - **Underlying Token Yield**: Yield from the asset itself (for yield-bearing tokens) - **Rewards APR**: Vault rewards + weighted market rewards - **Performance Fee**: Applied only to base APY ## Distribution System Rewards distribution has migrated from the Morpho URD system to Merkl. New campaigns use Merkl, while historical rewards may still be claimable via the legacy URD system. The claiming process is **identical** for all Morpho users, regardless of whether they're depositors, borrowers, or collateral suppliers. **For complete details on distribution systems, see:** - [Distribution System](/build/rewards/concepts/distribution-system) - [Reward Campaigns](/build/rewards/concepts/reward-campaigns) ## Learn More For comprehensive information about integrating rewards: - **[Rewards Integration Guide](/build/rewards/get-started)**: Complete overview and integration paths - **[Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)**: Complete API queries and calculations - **[Claim Rewards](/build/rewards/tutorials/claim-rewards)**: Implementation for both Merkl and URD - **[Integrate Display](/build/rewards/tutorials/integrate-display)**: UI/UX best practices ## Implementation For practical implementation guidance specific to earn products, see: - [Integrate Rewards for Earn Products](/build/earn/tutorials/rewards) ## [Vaults & ERC4626 Mechanics](https://docs.morpho.org/build/earn/concepts/vault-mechanics/) **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 The ERC‑4626 standard defines four core functions for deposits and withdrawals. ### Core Functions #### Deposit ```solidity // 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 ```solidity // 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 **Assets** are the underlying token (e.g., USDC, WETH). **Shares** represent proportional ownership of the vault and typically appreciate as yield accrues. ### Conversions ```ts // 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 Vault performance is reflected in the share price: ```ts // 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 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 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:** ```ts // 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. For assets with less than 9 decimals, the recommended minimum is 1e12 shares to prevent rounding issues (non-critical). **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 This protection is essential for vault security. Always verify the dead deposit exists before integrating a vault into production systems. Learn more about the attack mechanism in the [OpenZeppelin ERC4626 documentation](https://docs.openzeppelin.com/contracts/5.x/erc4626). ## Additional Considerations: Slippage ERC4626 functions do not include built-in slippage checks. While not a security requirement (when dead deposit protection is in place), slippage checks can improve user experience by preventing unexpected exchange rate movements between transaction simulation and execution. **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 - Implement min-received checks around ERC4626 operations for direct integrations See the [Assets Flow tutorial](/build/earn/tutorials/assets-flow) for integration examples. ## [Yield & Fees](https://docs.morpho.org/build/earn/concepts/yield-fees/) Understanding how yield is generated and fees are applied in Morpho Vaults is crucial for building accurate earn products and setting proper user expectations. ## Yield Generation While **Morpho Vaults V1.x** generate yield through a capital allocation to **Morpho Market V1**, **Morpho Vaults V2** generate yield through allocating capital to **Morpho Vault V1** and potentially **Morpho Market V1**. ### Where does the yield comes from? #### Borrower Interest Borrowers in underlying Morpho Markets pay interest #### Market Distribution Interest flows to lenders in each market #### Vault Collection Vault collects interest as a lender across multiple markets #### Share Price Increase Vault's total assets increase, raising share price #### Depositor Interest Depositors earn the interest paid by borrowers as the share of their position increased in token's value amount. ## Fee Mechanism **Morpho Vaults V2** implement a performance fee and a management fee that aligns curator incentives with vault performance. On the other side Morpho Vaults V1.x implement a single performance fee. ### Performance Fee The fee is taken as a cut on the native yield earned by allocating capital, and is capped at 50%. ### Management Fee For Morpho Vaults V2 only, this management fee is taken on the total asset deposited on the vault, and is capped at 5%. ## Integration Best Practices ### Real-Time Updates - Update share prices regularly - Show pending yield that hasn't been reflected in share price yet by accruing interests on the underlying markets - Display historical performance charts ### User Education - Clearly explain that performance fees only apply to yield, not principal, while management fee apply on the principal. ### Performance Monitoring - Track vault performance against benchmarks - Alert users to significant strategy changes - Provide detailed yield attribution ## [Morpho Vaults for Earn products](https://docs.morpho.org/build/earn/get-started/) 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](/learn/concepts/vault-v2/) and [Morpho Vaults V1](/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 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: {" "} 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 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 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](/build/rewards/get-started). ## Assets Flow - Earn Understanding the complete flow of assets is crucial for proper integration: ### 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 - 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 - 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 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 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. ## [Guide: Integrating One-Click Yield with OnchainKit](https://docs.morpho.org/build/earn/guides/base-onchainkit/) 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 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: ``` ┌───────────┐ │ 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 This guide assumes you are building a React application with TypeScript on the Base network. #### Step 1: Install Dependencies We recommend starting with the official OnchainKit template, which sets up the entire environment for you. ```bash npm create onchain@latest ``` If you are adding OnchainKit to an existing project, install the necessary packages: ```bash npm install @coinbase/onchainkit viem wagmi @tanstack/react-query ``` #### 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. Never hardcode API keys or Paymaster URLs. Use environment variables with a framework-specific prefix (e.g., `NEXT_PUBLIC_` or `VITE_`). #### 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)**. ```typescript // 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 Wrap your application's root with the `OnchainKitProvider`. This makes all of OnchainKit's hooks and components available throughout your app. ```tsx // 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 3: Production Considerations ### 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 | 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 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 → OnchainKit Quickstart Review the setup process and explore other powerful components for identity, transactions, and more. Start Building → Morpho Earn Concepts Understand the mechanics behind Morpho Vaults, including how yield is generated and risks are managed. Learn More → Community Support Join the Base Discord to ask questions and get help from the community and the OnchainKit team. Join Discord → ## [Earn: Developer Resources](https://docs.morpho.org/build/earn/resources/all/) 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 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](/get-started/resources/addresses/), the best way to dynamically fetch all deployed Morpho vaults is via the [Morpho API](/build/earn/tutorials/get-data). - **Contract Specifications**: For detailed function signatures, events, and errors, refer to the canonical [Morpho Vaults Contract Specs](/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 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](/build/earn/tutorials/get-data) - **Morpho Subgraphs**: For developers who prefer querying via The Graph protocol. - **Tutorial**: [Using Subgraphs for Vaults](/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. - **Learn more**: [Introduction to Morpho SDKs](/tools/offchain/sdks/get-started/) ## 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. ## [Depositing & Withdrawing from Vaults](https://docs.morpho.org/build/earn/tutorials/assets-flow/) **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. For background on ERC4626 mechanics and vault architecture, see [Vaults & ERC4626 Mechanics](/build/earn/concepts/vault-mechanics). 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 ## 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 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](/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 Before integrating with any ERC4626 vault, verify that adequate inflation attack protection is in place. 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:** ```ts // 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** for assets with more than 9 decimals, or **1e12 shares** otherwise (approximately $1 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](/build/earn/concepts/vault-mechanics#inflation-attack-protection). ## EIP-2612 Permit Support Both Morpho Vault V1 and V2 support [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612) permit for vault shares, allowing gasless approvals via off-chain signatures. ### Vault Shares Permit (V1 & V2) All Morpho Vault versions implement EIP-2612 on vault **shares**. This lets you approve someone to transfer your vault shares without a separate on-chain `approve()` transaction. | Version | Implementation | |---------|----------------| | V1 / V1.1 | Inherits OpenZeppelin's `ERC20Permit` | | V2 | Native EIP-2612 implementation | **Use case:** Approve a third party (e.g., a router contract) to transfer your vault shares using an off-chain signature. This permit is for **vault shares**, not for depositing assets. It does not enable gasless deposits on its own. ### Gasless Deposits via the Underlying Asset's Permit (V1 & V2) If the underlying asset supports EIP-2612 (e.g., USDC, DAI), you can sign a permit off-chain for the asset, then call `asset.permit()` + `vault.deposit()` in sequence. This eliminates the need for a separate `approve()` transaction. This flow works identically on both V1 and V2. Neither V1 nor V2 has a `depositWithPermit()` function. The deposit flow always requires the vault to have approval on the underlying asset. That approval can come from: - A traditional `approve()` transaction - An EIP-2612 `permit` (if the asset supports it) — USDC, DAI, etc. - Permit2 (for assets without native permit) — WETH, WBTC, etc. ### Example: Gasless Deposit with EIP-2612 Permit (TypeScript) The following example demonstrates a deposit into a Morpho Vault using the underlying asset's EIP-2612 permit. The flow is: 1. Sign an EIP-712 permit message off-chain (gasless) 2. Call `asset.permit()` on-chain to set the approval 3. Call `vault.deposit()` to deposit the approved tokens Steps 2 and 3 can be combined into a single atomic transaction using a multicall contract. ```typescript import { createPublicClient, createWalletClient, http, type Address, type Hex, parseUnits, } from "viem"; import { mainnet } from "viem/chains"; import { privateKeyToAccount } from "viem/accounts"; // Example vault using USDC as underlying (USDC supports EIP-2612 permit) const VAULT_ADDRESS = "0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB" as Address; const USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as Address; const erc2612Abi = [ { name: "permit", type: "function", inputs: [ { name: "owner", type: "address" }, { name: "spender", type: "address" }, { name: "value", type: "uint256" }, { name: "deadline", type: "uint256" }, { name: "v", type: "uint8" }, { name: "r", type: "bytes32" }, { name: "s", type: "bytes32" }, ], outputs: [], stateMutability: "nonpayable", }, { name: "nonces", type: "function", inputs: [{ name: "owner", type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view", }, ] as const; const vaultAbi = [ { name: "deposit", type: "function", inputs: [ { name: "assets", type: "uint256" }, { name: "receiver", type: "address" }, ], outputs: [{ name: "shares", type: "uint256" }], stateMutability: "nonpayable", }, ] as const; function parseSignature(signature: Hex): { v: number; r: Hex; s: Hex } { const r = `0x${signature.slice(2, 66)}` as Hex; const s = `0x${signature.slice(66, 130)}` as Hex; const v = parseInt(signature.slice(130, 132), 16); return { v, r, s }; } async function depositWithEIP2612Permit( publicClient: ReturnType, walletClient: ReturnType, vaultAddress: Address, assetAddress: Address, depositAmount: bigint, assetDomainConfig: { name: string; version: string }, ) { const account = walletClient.account!; const chainId = await publicClient.getChainId(); // 1. Get current nonce for the permit const nonce = await publicClient.readContract({ address: assetAddress, abi: erc2612Abi, functionName: "nonces", args: [account.address], }); // 2. Set deadline (1 hour from now) const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600); // 3. Create EIP-712 typed data for the permit const typedData = { domain: { name: assetDomainConfig.name, version: assetDomainConfig.version, chainId, verifyingContract: assetAddress, }, types: { Permit: [ { name: "owner", type: "address" }, { name: "spender", type: "address" }, { name: "value", type: "uint256" }, { name: "nonce", type: "uint256" }, { name: "deadline", type: "uint256" }, ], }, primaryType: "Permit" as const, message: { owner: account.address, spender: vaultAddress, value: depositAmount, nonce, deadline, }, }; // 4. Sign the permit (GASLESS — off-chain signature) const signature = await walletClient.signTypedData(typedData); const { v, r, s } = parseSignature(signature); // 5. Execute permit on-chain (sets approval) const permitHash = await walletClient.writeContract({ address: assetAddress, abi: erc2612Abi, functionName: "permit", args: [account.address, vaultAddress, depositAmount, deadline, v, r, s], }); await publicClient.waitForTransactionReceipt({ hash: permitHash }); // 6. Deposit into vault const depositHash = await walletClient.writeContract({ address: vaultAddress, abi: vaultAbi, functionName: "deposit", args: [depositAmount, account.address], }); await publicClient.waitForTransactionReceipt({ hash: depositHash }); return { permitHash, depositHash }; } // Example: Deposit 100 USDC using permit async function main() { const publicClient = createPublicClient({ chain: mainnet, transport: http(), }); const account = privateKeyToAccount("0x..." as `0x${string}`); const walletClient = createWalletClient({ chain: mainnet, transport: http(), account, }); const depositAmount = parseUnits("100", 6); // 100 USDC await depositWithEIP2612Permit( publicClient, walletClient, VAULT_ADDRESS, USDC_ADDRESS, depositAmount, { name: "USD Coin", version: "2" }, // USDC domain config ); } ``` This code has not been audited and is for educational purposes only. Always verify the token's domain separator configuration against its contract implementation. --- ## 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. The examples below show integration patterns for both Morpho Vault V1 and Morpho Vault V2. Since both implement the ERC4626 standard, the core deposit/withdraw functions remain the same, but the import statements and interface references differ. SDK examples for Vault V2 will be added later. ### 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. ```solidity 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); ``` If the underlying asset supports [EIP-2612 `permit`](https://eips.ethereum.org/EIPS/eip-2612), you can use it for gasless approvals instead of a separate `approve()` transaction. See the [EIP-2612 Permit Support](#eip-2612-permit-support) section for details. ### Step 2: Deposit or Mint Assets Choose the function that best fits your needs. ```solidity [deposit (V2)] 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)); ``` ```solidity [mint (V2)] import { IVaultV2 } from "@morpho-org/vault-v2/src/interfaces/IVaultV2.sol"; // Shares-first approach: Mint a specific number of vault shares. // The contract will calculate and pull the required amount of the underlying asset. uint256 sharesToMint = 1 ether; uint256 assetsNeeded = IVaultV2(vaultAddress).mint(sharesToMint, address(this)); ``` ```solidity [deposit (V1)] import { IMetaMorpho } from "@morpho-org/metamorpho/src/interfaces/IMetaMorpho.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 = IMetaMorpho(vaultAddress).deposit(depositAmount, address(this)); ``` ```solidity [mint (V1)] import { IMetaMorpho } from "@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol"; // Shares-first approach: Mint a specific number of vault shares. // The contract will calculate and pull the required amount of the underlying asset. uint256 sharesToMint = 1 ether; uint256 assetsNeeded = IMetaMorpho(vaultAddress).mint(sharesToMint, address(this)); ``` ### Step 3: Withdraw or Redeem Assets Similarly, you can withdraw by specifying either the asset amount or the share amount. ```solidity [withdraw (V2)] 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)); ``` ```solidity [redeem (V2)] import { IVaultV2 } from "@morpho-org/vault-v2/src/interfaces/IVaultV2.sol"; // Shares-first approach (Recommended for full withdrawal): Redeem a specific number of shares. uint256 sharesToRedeem = IVaultV2(vaultAddress).balanceOf(address(this)); uint256 assetsReceived = IVaultV2(vaultAddress).redeem(sharesToRedeem, address(this), address(this)); ``` ```solidity [withdraw (V1)] import { IMetaMorpho } from "@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol"; // Asset-first approach: Withdraw a specific amount of the underlying token. uint256 assetsToWithdraw = 1 ether; uint256 sharesBurned = IMetaMorpho(vaultAddress).withdraw(assetsToWithdraw, address(this), address(this)); ``` ```solidity [redeem (V1)] import { IMetaMorpho } from "@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol"; // Shares-first approach (Recommended for full withdrawal): Redeem a specific number of shares. uint256 sharesToRedeem = IMetaMorpho(vaultAddress).balanceOf(address(this)); uint256 assetsReceived = IMetaMorpho(vaultAddress).redeem(sharesToRedeem, address(this), address(this)); ``` ### Full Example: Solidity Snippets Here are some example contracts demonstrating these interactions for both vault versions. The following contracts have not been audited and are for educational purposes only. Refer to the [full snippets repository](https://github.com/morpho-org/morpho-blue-snippets) for more details. ```solidity [Morpho Vault V2] // 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); } } } ``` ```solidity [Morpho Vault V1] // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IMetaMorpho } from "@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract VaultV1Interaction { IMetaMorpho public immutable vault; IERC20 public immutable asset; constructor(address _vault) { vault = IMetaMorpho(_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) 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**. Currently, the released version of SDKs only support **Morpho Vaults V1**. The ones for **Morpho Vaults V2** are coming out soon. ### Step 1: Setup First, install the necessary packages and set up your Viem client. ```bash npm install viem @morpho-org/blue-sdk @morpho-org/blue-sdk-viem @morpho-org/morpho-ts ``` ```typescript 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 Before depositing, check the current allowance and approve if necessary. ```typescript // 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 Call the `deposit` function to add funds to the vault. ```typescript 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 To withdraw the full balance, first fetch the user's share balance, then call `redeem`. ```typescript // 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); } ``` For more detailed examples and advanced usage, including handling different wallet types and simulation states, explore the [Morpho SDKs documentation](/tools/offchain/sdks/get-started/). ## Additional Considerations ### 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. Here's an educational example of how to implement a basic slippage check (1% tolerance): ```solidity [Vault V2 with slippage check] // 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; } } ``` ```solidity [Vault V1 with slippage check] // Educational example: Deposit with 1% slippage protection import { IMetaMorpho } from "@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract VaultV1DepositWithSlippage { function depositWithSlippage( address vaultAddress, uint256 depositAmount ) external returns (uint256) { IMetaMorpho vault = IMetaMorpho(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; } } ``` These are simplified educational examples showing the pattern within a smart contract function. Production implementations should consider additional factors like gas costs, user-configurable tolerances, and edge cases. See also [Vault Mechanics: Slippage Considerations](/build/earn/concepts/vault-mechanics#additional-considerations-slippage) for more context. ## [Get Data](https://docs.morpho.org/build/earn/tutorials/get-data/) ## Before Starting In this tutorial, you might see different ways to fetch data for Morpho Vaults: - **API**: Using the Morpho public API (see endpoint below). This is the easiest and most direct way for most applications. Note that only a subset of chains are supported. - **Typescript**: Using Typescript snippet. For Developers expecting to perform offchain computation. - **Smart Contract**: Fetching data directly onchain. This is best for real-time or trustless data. - **SDK**: [Examples Incoming] Using the Morpho SDKs for pre-built abstractions and faster development. API Endpoint: [api.morpho.org/graphql](https://api.morpho.org/graphql) Review the [Morpho API main rules](/tools/offchain/api/get-started/#morpho-api-main-rules) before sending requests. By default, the API returns only the first 100 results and targets the Ethereum network unless you specify otherwise. For each topic below, you'll find short guides for each method (where possible). This avoids redundancy and helps you choose the best approach for your use case. ## Discovery and Listing ### Vaults List #### Morpho Vaults V2 ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:get-all-vaults-v2] ``` {" "} ```typescript // [!include ~/snippets/typescript/02-vaults-v2-list.ts:imports] // [!include ~/snippets/typescript/02-vaults-v2-list.ts:client-setup] // [!include ~/snippets/typescript/02-vaults-v2-list.ts:constants] // [!include ~/snippets/typescript/02-vaults-v2-list.ts:vault-creation-types] // [!include ~/snippets/typescript/02-vaults-v2-list.ts:fetch-vault-creations] // [!include ~/snippets/typescript/02-vaults-v2-list.ts:display-results] // [!include ~/snippets/typescript/02-vaults-v2-list.ts:main-execution] ``` **Example Output:** ```json { "message": "Fetching Vault V2 creations from block 23716940 to 23717000...", "found": "Found 1 Vault V2 creation(s)", "vaults": [ { "address": "0x5E5b30c5fD07da26d1e515dfEDb1D37C93417652", "owner": "0x46057881E0B9d190920FB823F840B837f65745d5", "asset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "salt": "0x5dbd6b3d5444d58eb3b873a76f4a26158f4a960b67d87125ffcd305053e16a3a", "blockNumber": "23716959", "transactionHash": "0x73f2c14195c38ca887e44fed4e2bb9619a858ddea7337258d748a3079ef417f0" } ] } ``` This example demonstrates how to: - Listen to `CreateVaultV2` events from the Morpho Vault V2 Factory contract on Ethereum (`0xA1D94F746dEfa1928926b84fB2596c06926C0405`). Factories addresses on resp. chains supported are [here](/get-started/resources/addresses/). - Filter events within a specific block range - Extract all vault creation details from the event logs - Parse and format the results for easy consumption {" "} One can listen to all `CreateVaultV2` events emitted from the `MorphoVaultV2Factory` contract. The contracts addresses are [here](/get-started/resources/addresses/). ```solidity /// @notice Emitted when a new Morpho Vault V2 is created. /// @param owner The initial owner of the vault. /// @param asset The address of the underlying asset. /// @param salt The salt used for the vault's CREATE2 address. /// @param newVaultV2 The address of the newly created Vault V2. event CreateVaultV2( address indexed owner, address indexed asset, bytes32 salt, address indexed newVaultV2 ); ``` #### Morpho Vaults V1 ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:get-all-vaults] ``` {" "} ```typescript // [!include ~/snippets/typescript/02-vaults-v1-list.ts:imports] // [!include ~/snippets/typescript/02-vaults-v1-list.ts:client-setup] // [!include ~/snippets/typescript/02-vaults-v1-list.ts:constants] // [!include ~/snippets/typescript/02-vaults-v1-list.ts:vault-creation-types] // [!include ~/snippets/typescript/02-vaults-v1-list.ts:fetch-vault-creations] // [!include ~/snippets/typescript/02-vaults-v1-list.ts:display-results] // [!include ~/snippets/typescript/02-vaults-v1-list.ts:main-execution] ``` **Example Output:** ```json { "message": "Fetching vault creations from block 22880720 to 22880740...", "found": "1 vault creation(s)", "vaults": [ { "name": "Yearn Degen USDC", "symbol": "yDG-USDC", "address": "0xdC2Dd5189F70Fe2832D9caf7b17d27AA3D79dbE1", "asset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "caller": "0xFc5F89d29CCaa86e5410a7ad9D9d280d4455C12B", "initialOwner": "0xFc5F89d29CCaa86e5410a7ad9D9d280d4455C12B", "initialTimelock": "0", "salt": "0x0000000000000000000000000000000000000000000000000000000000000000", "blockNumber": "22880731", "transactionHash": "0xa6c2906efec1a0f413038076a4f05f41b3d23e49d1af4543e54c1c0b69def6ba" } ] } ``` This example demonstrates how to: - Listen to `CreateMetaMorpho` events from the Morpho Vault V1 Factory contract on Ethereum (`0x1897A8997241C1cD4bD0698647e4EB7213535c24`). All addresses are [here](/get-started/resources/addresses/). - Filter events within a specific block range - Extract all vault creation details from the event logs - Parse and format the results for easy consumption {" "} One can listen to all `CreateMetaMorpho` events emitted from the Morpho Vault V1 Factory contracts. The contracts addresses are [here](/get-started/resources/addresses/). ```solidity /// @notice Emitted when a new MetaMorphoV1_1 vault is created. /// @param metaMorpho The address of the MetaMorphoV1_1 vault. /// @param caller The caller of the function. /// @param initialOwner The initial owner of the MetaMorphoV1_1 vault. /// @param initialTimelock The initial timelock of the MetaMorphoV1_1 vault. /// @param asset The address of the underlying asset. /// @param name The name of the MetaMorphoV1_1 vault. /// @param symbol The symbol of the MetaMorphoV1_1 vault. /// @param salt The salt used for the MetaMorphoV1_1 vault's CREATE2 address. event CreateMetaMorpho( address indexed metaMorpho, address indexed caller, address initialOwner, uint256 initialTimelock, address indexed asset, string name, string symbol, bytes32 salt ); ``` ## Vault Metrics ### Total Deposits & Assets #### Morpho Vaults V2 Easiest to implement - perfect for most applications ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:total-deposits-unique-vault-v2] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:total-deposits-all-vaults-v2] ``` {" "} The following example demonstrates how to: - Connect to the Ethereum mainnet using Viem - Fetch total deposits and assets from a Morpho Vault V2 - Calculate and display formatted vault statistics including total supply, total assets, and USD value - Parse and format results for easy consumption ```typescript // [!include ~/snippets/typescript/03-total-deposits-liquidity-v2.ts:imports] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v2.ts:client-setup] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v2.ts:constants-and-abis] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v2.ts:vault-stats-types] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v2.ts:fetch-vault-stats] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v2.ts:display-results] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v2.ts:main-execution] ``` **Example Output:** ``` Fetching stats for vault: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145... ✅ --- Morpho Vault Stats --- ✅ Vault Address: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145 Underlying Asset: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --- Totals --- Total Supply (Shares): 406046.668299445014491638 (raw: 406046668299445014491638) Total Assets (6 decimals): 409312.044166 (raw: 409312044166) Total Assets (USD): $409,312.04 --------------------------------- ``` {" "} As it is important to accrue interests on the underlying adapters and markets, consider using the full implementation in the [Morpho Vault V2 Snippets](https://github.com/morpho-org/vault-v2/blob/main/README.md) repository for production use. ```solidity [Raw Contract Calls] // [!include ~/snippets/solidity/morpho-vault-v2-snippets.sol:totalDepositVaultV2] ``` #### On Morpho Vaults V1 Easiest to implement - perfect for most applications ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:total-deposits-unique-vault] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:total-deposits-all-vaults] ``` {" "} The following example demonstrates how to: - Connect to the Ethereum mainnet using Viem - Fetch total deposits and assets from a Morpho Vault V1 - Calculate and display formatted vault statistics including total supply, total assets, and USD value - Parse and format results for easy consumption ```typescript // [!include ~/snippets/typescript/03-total-deposits-liquidity-v1.ts:imports] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v1.ts:client-setup] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v1.ts:constants-and-abis] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v1.ts:vault-stats-types] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v1.ts:fetch-vault-stats] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v1.ts:display-results] // [!include ~/snippets/typescript/03-total-deposits-liquidity-v1.ts:main-execution] ``` **Example Output:** ``` Fetching stats for vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB... ✅ --- Morpho Vault Stats --- ✅ Vault Address: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB Underlying Asset: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --- Totals --- Total Supply (Shares): 151070805.545457516059431924 (raw: 151070805545457516059431924) Total Assets (6 decimals): 164797857.365748 (raw: 164797857365748) Total Assets (USD): $164,797,857.37 --------------------------------- ``` {" "} As it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain. Feel free to refer to the [Morpho Vaults Snippets](https://github.com/morpho-org/morpho-blue-snippets/blob/main/src/metamorpho/MetaMorphoSnippets.sol) for extensive example. ```solidity [Raw Contract Calls] // [!include ~/snippets/solidity/morpho-vault-snippets.sol:totalDepositVault] ``` ### APY (Native + Rewards) #### Morpho Vaults V2 ###### Morpho Vaults V2 can be eligible for 2 levels of rewards: - **Market level rewards:** These are inherited from the Morpho Markets V1 where the Morpho Vault V2 allocates assets. - **Vault level rewards:** 1. One type of rewards here are inherited from the Morpho Vaults V1 where the Morpho Vault V2 allocates assets. 2. Second type of rewards here are distributed directly to the Morpho Vault V2 itself. Note for Morpho Vault V2: all rewards appearing on the Morpho Api are displayed under `rewards` section directly. ###### APY Components Breakdown: 1. **Native APY:** The base yield earned from depositing assets into either Morpho Markets V1 or Morpho Vaults V1. 2. **Underlying Token Yield:** The yield generated by the underlying token itself (when applicable). For yield-bearing loan assets, this is calculated using daily exchange rate changes queried at 1-day block intervals. Access this via `asset.yield.apr`. 3. **Reward APRs:** Additional incentives from both types. All rewards are currently accessible via `rewards` (Note, it is different from the queries for Morpho Vaults V1 below) 4. **Performance Fee Adjustment:** The performance fee is applied only to the Native APY component. 5. **Management Fee Adjustment:** A time-based fee (annual rate, if applicable) deducted from the total assets regardless of performance. The combination of these components results in the Net APY: ```math \text{Net APY}= \text{Native APY} \times (1 - \text{Performance Fee}) + \text{Underlying Token Yield} ``` ```math \phantom{\text{Net APY} =} + \sum \text{Rewards APR} - \text{Management Fee} ``` Where: - Performance Fee is applied **only** to Native APY (as a percentage) - Management Fee is applied to total assets (as an annual rate) - Underlying Token Yield applies only to yield-bearing assets (0 otherwise) - Rewards APR is the sum of all reward incentives ###### Important UI Reference one might find on apps: 1. `avgApy` represents the Native APY (6h average vault APY excluding rewards, before deducting the performance fee) 2. `avgNetApy` represents the complete APY (6h average vault APY including rewards, after deducting the performance fee) ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:apy-unique-vault-v2] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:apy-all-vaults-v2] ``` {" "} **Important Limitation:** The current onchain APY calculation for Vault V2 only supports vaults that allocate to **Morpho Vaults V1** (MetaMorpho) through `MorphoVaultV1Adapter`. **Rewards** APR are omitted. If a Vault V2 allocates directly to Morpho Markets V1 via `MorphoMarketV1AdapterV2`, those allocations will be **excluded** from the APY calculation in the current implementation. For production use with full adapter support, refer to the complete implementation in the [Morpho Vault V2 Snippets](https://github.com/morpho-org/vault-v2/blob/main/README.md) repository. As it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain. Feel free to refer to the [Morpho Vault V2 Snippets](https://github.com/morpho-org/vault-v2/blob/main/README.md) for extensive examples. ```solidity // [!include ~/snippets/solidity/morpho-vault-v2-snippets.sol:supplyAPYVaultV2] ``` #### Morpho Vaults V1 ###### Morpho Vaults V1 can be eligible for 2 levels of rewards: - **Market level rewards:** These are inherited from the markets where the vault allocates assets, accessible via `state.allocation.market.state.rewards` (e.g., `supplyApr`). - **Vault level rewards:** These are distributed directly to the vault itself, accessible via `state.rewards` (e.g., `supplyApr`). ###### APY Components Breakdown: 1. **Native APY:** The base yield earned from depositing assets into markets. 2. **Underlying Token Yield:** The yield generated by the underlying token itself (when applicable). For yield-bearing loan assets, this is calculated using daily exchange rate changes queried at 1-day block intervals. Access this via `asset.yield.apr`. 3. **Reward APRs:** Additional incentives from both: - **Vault-level rewards:** Direct rewards to the vault via `state.rewards` - **Market-level rewards:** Allocated proportionally from markets via `state.allocations.market.state.rewards` using weighted averages on allocations 4. **Performance Fee Adjustment:** The performance fee is applied only to the Native APY component. The combination of these components (adding rewards, subtracting fees) results in the Net APY. ```math Net Apy = Native APY + Underlying Token Yield + Rewards APRs - Perf Fee_{onNativeApy} ``` ###### Important UI Reference one might find on apps: 1. `avgApy` represents the Native APY (6h average vault APY excluding rewards, before deducting the performance fee) 2. `avgNetApy` represents the complete APY (6h average vault APY including rewards, after deducting the performance fee) ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:apy-unique-vault] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:apy-all-vaults] ``` {" "} 1. Rewards extra APY **are NOT** query-able onchain. 2. **It is important to accrue interests on the underlying markets to compute the APY.** The following example demonstrates how to calculate a vault's APY by performing a weighted average of the supply APYs of all markets where the vault has allocated assets. 3. This example demonstrates how to: - Calculate the weighted average APY across all markets in the vault's withdrawal queue - Use multicall for efficient batch operations to fetch market data - Properly handle IRM (Interest Rate Model) calculations for each market - Account for asset allocation weights when computing the final vault APY - Display both percentage and raw WAD values for precision ```typescript // [!include ~/snippets/typescript/04-vault-apy.ts:imports] // [!include ~/snippets/typescript/04-vault-apy.ts:client-setup] // [!include ~/snippets/typescript/04-vault-apy.ts:abis-and-constants] // [!include ~/snippets/typescript/04-vault-apy.ts:types] // [!include ~/snippets/typescript/04-vault-apy.ts:math-helpers] // [!include ~/snippets/typescript/04-vault-apy.ts:core-logic] // [!include ~/snippets/typescript/04-vault-apy.ts:display-results] // [!include ~/snippets/typescript/04-vault-apy.ts:main-execution] ``` **Example Output:** ``` Fetching vault's withdrawal queue length... Fetching 4 market(s) from withdrawal queue... Found 4 market(s). Fetching allocations and APYs... ✅ --- Morpho Vault Underlying APY --- ✅ Calculated Vault APY: 3.2576470788039398% (Raw WAD value: 32576470788039398) --------------------------------------- ``` {" "} As it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain. Feel free to refer to the [Morpho Vaults Snippets](https://github.com/morpho-org/morpho-blue-snippets/blob/main/src/metamorpho/MetaMorphoSnippets.sol) for extensive example. ```solidity // [!include ~/snippets/solidity/morpho-vault-snippets.sol:supplyAPYVault] ``` ### Share Price (Token Value) **Why You Shouldn't Calculate Manually** Computing the exchange rate as `totalAssets / totalSupply` can show false "drops" during fee accruals. This happens because these values update at different times, creating temporary inconsistencies. **How ERC-4626 Calculates Share Price** The standard includes **virtual offsets** to prevent inflation attacks and ensure consistency: - **Virtual Assets**: `+1` added to totalAssets - **Virtual Shares**: `+10^DECIMALS_OFFSET` added to totalSupply - DECIMALS_OFFSET matches the underlying asset decimals (6 for USDC, 18 for WETH) **Formula** for pricing 1 share (10^18 wei): ```math \text{sharePrice} = \frac{10^{18} \times (\text{totalAssets} + 1)}{\text{totalSupply} + 10^{\text{DECIMALS\_OFFSET}}} ``` The result is in raw underlying asset units. To get the human-readable price, divide by `10^assetDecimals`. **Recommended Methods:** - **API**: Use the `sharePrice` field (already computed correctly) - **Onchain**: Use `convertToAssets(10^18)` instead of manual calculation **Practical Example with USDC Vault** Using real data from a USDC vault (6 decimals): ```math \text{totalAssets: } 473{,}435{,}155{,}471{,}028 \text{ (raw USDC units)} ``` ```math \text{totalSupply: } 427{,}784{,}657{,}006{,}652{,}956{,}819{,}706{,}379 \text{ (raw share units)} ``` Applying the formula: ```math \text{sharePrice} = \frac{10^{18} \times 473{,}435{,}155{,}471{,}029}{427{,}784{,}657{,}006{,}652{,}956{,}819{,}706{,}379 + 10^6} = 1{,}106{,}713 \text{ (raw units)} ``` Converting to human-readable: ```math \frac{1{,}106{,}713}{10^6} = 1.106713 \text{ USDC per share} ``` This matches the API's `sharePrice` field value! #### Morpho Vaults V2 Morpho Api for Morpho Vaults V2 provides only `totalAssets`& `totalSupply` at the moment. One has to do the maths explained above. ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:vault-token-price-unique-vault-v2] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:vault-token-price-all-vaults-v2] ``` {" "} This example demonstrates how to price a Morpho Vault V2 token using the standard ERC-4626 methodology. Since vault tokens represent a share of the underlying assets, their price appreciates as the vault accrues yield. The script shows how to: - Connect to Ethereum mainnet using Viem. - Use the `convertToAssets` function to determine how many underlying assets correspond to one full vault share token. - Fetch vault and underlying asset details (symbols, decimals) using `multicall` for efficiency. - Format the raw price into a human-readable string (e.g., "1.008 USDC"). - Calculate the USD value of the vault token. ```typescript // [!include ~/snippets/typescript/06-vault-price-v2.ts:imports] // [!include ~/snippets/typescript/06-vault-price-v2.ts:client-setup] // [!include ~/snippets/typescript/06-vault-price-v2.ts:abis-and-constants] // [!include ~/snippets/typescript/06-vault-price-v2.ts:types] // [!include ~/snippets/typescript/06-vault-price-v2.ts:core-logic] // [!include ~/snippets/typescript/06-vault-price-v2.ts:display-results] // [!include ~/snippets/typescript/06-vault-price-v2.ts:main-execution] ``` **Example Output:** ``` Calculating token price for vault: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145... --- Morpho Vault V2 Token Price --- Vault: kUSDC (0x04422053aDDbc9bB2759b248B574e3FCA76Bc145) Underlying Asset: USDC (0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48) --- Price --- 1 kUSDC = 1.008451 USDC Price (raw units): 1008451 (with 6 decimals) Price (USD): $1.0085 ---------------------------------------- ``` {" "} ```solidity // Get the price of 1 vault token in underlying asset units // Works for both Vault V1 and V2 as they are both ERC-4626 compliant uint256 oneShare = 10**IERC20Metadata(vault).decimals(); uint256 priceInAssets = IERC4626(vault).convertToAssets(oneShare); // Alternative: Calculate manually using total supply and total assets uint256 totalSupply = IERC20(vault).totalSupply(); uint256 totalAssets = IERC4626(vault).totalAssets(); uint256 priceManual = (totalAssets * oneShare) / totalSupply; // Both methods return the same result: // Price = how many underlying assets 1 vault token is worth ``` **Key Functions:** - `convertToAssets(shares)`: ERC-4626 standard function that converts vault shares to underlying assets - `totalAssets()`: Total underlying assets managed by the vault - `totalSupply()`: Total vault tokens in circulation **Price Formula:** `Price = totalAssets / totalSupply` The `convertToAssets` approach is recommended as it handles edge cases and follows the ERC-4626 standard. **Note:** Both Morpho Vault V1 and V2 are ERC-4626 compliant, so the same functions work for both versions. #### Morpho Vaults V1 ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:vault-token-price-unique-vault-v1] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:vault-token-price-all-vaults-v1] ``` {" "} This example demonstrates how to price a Morpho Vault token using the standard ERC-4626 methodology. Since vault tokens represent a share of the underlying assets, their price appreciates as the vault accrues yield. The script shows how to: - Connect to Ethereum mainnet using Viem. - Use the `convertToAssets` function to determine how many underlying assets correspond to one full vault share token. - Fetch vault and underlying asset details (symbols, decimals) using `multicall` for efficiency. - Format the raw price into a human-readable string (e.g., "1.026 USDC"). - Calculate the USD value of the vault token. ```typescript // [!include ~/snippets/typescript/06-vault-price-v1.ts:imports] // [!include ~/snippets/typescript/06-vault-price-v1.ts:client-setup] // [!include ~/snippets/typescript/06-vault-price-v1.ts:abis-and-constants] // [!include ~/snippets/typescript/06-vault-price-v1.ts:types] // [!include ~/snippets/typescript/06-vault-price-v1.ts:core-logic] // [!include ~/snippets/typescript/06-vault-price-v1.ts:display-results] // [!include ~/snippets/typescript/06-vault-price-v1.ts:main-execution] ``` **Example Output:** ```json Calculating token price for vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB... --- Morpho Vault Token Price --- Vault: steakUSDC (0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB) Underlying Asset: USDC (0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48) --- Price --- 1 steakUSDC = 1.090931 USDC Price (raw units): 1090931 (with 6 decimals) Price (USD): $1.0909 ---------------------------------------- ``` {" "} ```solidity // Get the price of 1 vault token in underlying asset units uint256 oneShare = 10**IERC20Metadata(vault).decimals(); uint256 priceInAssets = IMetaMorpho(vault).convertToAssets(oneShare); // Alternative: Calculate manually using total supply and total assets uint256 totalSupply = IERC20(vault).totalSupply(); uint256 totalAssets = IMetaMorpho(vault).totalAssets(); uint256 priceManual = (totalAssets * oneShare) / totalSupply; // Both methods return the same result: // Price = how many underlying assets 1 vault token is worth ``` **Key Functions:** - `convertToAssets(shares)`: ERC-4626 standard function that converts vault shares to underlying assets - `totalAssets()`: Total underlying assets managed by the vault - `totalSupply()`: Total vault tokens in circulation **Price Formula:** `Price = totalAssets / totalSupply` The `convertToAssets` approach is recommended as it handles edge cases and follows the ERC-4626 standard. ## Allocation & Strategy ### Current Allocations #### Morpho Vaults V2 **Vaults V2 allocate through Adapters, not directly to markets.** Each adapter reports its current holdings via `realAssets()`, and the vault aggregates these values to calculate total allocations. Vaults V2 can allocate to: - **Morpho Markets V1** (via `MorphoMarketV1AdapterV2`) - **Morpho Vaults V1** (via `MorphoVaultV1Adapter`) - Any future Morpho protocol with an enabled adapter ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:vaults-allocation-unique-vault-v2] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:vaults-allocation-all-vaults-v2] ``` {" "} This example demonstrates how to: - Fetch all adapters from the Vault V2 and detect their types - Retrieve allocations from each adapter (MorphoMarketV1AdapterV2 or MorphoVaultV1Adapter) - Calculate idle assets held directly by the vault - Determine allocation amounts and percentages across all destinations - Display formatted allocation results with adapter breakdown - Use multicall for efficient batch operations ```typescript // [!include ~/snippets/typescript/05-vault-allocations-v2.ts:imports] // [!include ~/snippets/typescript/05-vault-allocations-v2.ts:client-setup] // [!include ~/snippets/typescript/05-vault-allocations-v2.ts:abis-and-constants] // [!include ~/snippets/typescript/05-vault-allocations-v2.ts:types] // [!include ~/snippets/typescript/05-vault-allocations-v2.ts:math-helpers] // [!include ~/snippets/typescript/05-vault-allocations-v2.ts:core-logic] // [!include ~/snippets/typescript/05-vault-allocations-v2.ts:display-results] // [!include ~/snippets/typescript/05-vault-allocations-v2.ts:main-execution] ``` **Example Output:** ``` Found 1 adapter(s). Fetching allocations... ✅ --- Morpho Vault V2 Allocations --- ✅ Vault Address: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145 Total Allocated: 380947.871852 -------------------------------------------------------------------------------------------------- 🏦 Idle Assets: -------------------------------------------------------------------------------------------------- Idle (in vault) 0 0.00% 📦 Adapters (1): -------------------------------------------------------------------------------------------------- Adapter: 0x0c2D17F72965944e7755C992E052b725Ab5AA5Ea Type: MorphoVaultV1Adapter Total in Adapter: 380947.871852 Destinations: ---------------------------------------------------------------------------------------------- Destination Allocation Percentage ---------------------------------------------------------------------------------------------- Vault: 0x6C26793c7F1e2785c09b460676e797b716f0Bc8E 380,947.87 100.00% -------------------------------------------------------------------------------------------------- ``` {" "} #### Morpho Vaults V1 **Morpho Vaults V1** allocate exclusively to Morpho Markets V1. The vault uses two queues to manage capital flow: - **Supply Queue**: Determines the order markets receive new deposits - **Withdraw Queue**: Determines the order markets are tapped for withdrawals The Morpho Vaults V1 allocations fall here into markets existing in those queues. ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:vaults-allocation-unique-vault-v1] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:vaults-allocation-all-vaults-v1] ``` {" "} This example demonstrates how to: - Fetch the vault's withdrawal queue and iterate through all markets - Calculate real-time market states with proper interest accrual - Determine asset allocation amounts and percentages across markets - Display formatted allocation results with proper decimal handling - Use multicall for efficient batch operations to retrieve market data ```typescript // [!include ~/snippets/typescript/05-vault-allocations-v1.ts:imports] // [!include ~/snippets/typescript/05-vault-allocations-v1.ts:client-setup] // [!include ~/snippets/typescript/05-vault-allocations-v1.ts:abis-and-constants] // [!include ~/snippets/typescript/05-vault-allocations-v1.ts:types] // [!include ~/snippets/typescript/05-vault-allocations-v1.ts:math-helpers] // [!include ~/snippets/typescript/05-vault-allocations-v1.ts:core-logic] // [!include ~/snippets/typescript/05-vault-allocations-v1.ts:display-results] // [!include ~/snippets/typescript/05-vault-allocations-v1.ts:main-execution] ``` **Example Output:** ``` Found 4 market(s). Fetching allocations... ✅ --- Morpho Vault Market Allocations --- ✅ Vault Address: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB -------------------------------------------------------------------------------------------------- Market ID Allocation Percentage -------------------------------------------------------------------------------------------------- 0x54efdee08e272e929034a8f26f7ca34b1ebe364b275391169b28c6d7db24dbc8 0 0.00% 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64 110,890,214.88 67.28% 0x3a85e619751152991742810df6ec69ce473daef99e28a64ab2340d7b7ccfee49 48,440,342.6 29.39% 0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc 5,467,834.41 3.31% -------------------------------------------------------------------------------------------------- ``` {" "} ### Vault Queues **Morpho Vaults V1** allocate exclusively to Morpho Markets V1. The vault uses two queues to manage capital flow: - **Supply Queue**: Determines the order markets receive new deposits - **Withdraw Queue**: Determines the order markets are tapped for withdrawals The Morpho Vaults V1 allocations fall here into markets existing in those queues. ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:vault-queues-unique-vault] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:vault-queues-all-vaults] ``` {" "} This example demonstrates how to retrieve and display vault queue information including: - Supply queue: Markets where the vault can supply liquidity (ordered by priority) - Withdraw queue: Markets from which the vault withdraws liquidity during redemptions (ordered by priority) - Market details including loan/collateral tokens, LLTV, oracle, and IRM addresses - Queue positions and summary statistics - Efficient multicall operations to fetch all market data ```typescript // [!include ~/snippets/typescript/08-vault-queues.ts:imports] // [!include ~/snippets/typescript/08-vault-queues.ts:client-setup] // [!include ~/snippets/typescript/08-vault-queues.ts:abis-and-constants] // [!include ~/snippets/typescript/08-vault-queues.ts:types] // [!include ~/snippets/typescript/08-vault-queues.ts:helper-functions] // [!include ~/snippets/typescript/08-vault-queues.ts:core-logic] // [!include ~/snippets/typescript/08-vault-queues.ts:display-results] // [!include ~/snippets/typescript/08-vault-queues.ts:main-execution] ``` **Example Output:** ``` Fetching queue information for vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB... Supply queue length: 4, Withdraw queue length: 4 Fetching market details for 4 unique markets... --- Morpho Vault Queues --- Vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB Asset: USDC (0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48) --- Supply Queue (4 markets) --- Pos | Market ID | Loan Token | Collateral Token | LLTV ----+----------------------+--------------+------------------+--------- 1 | 0x64d65c...883fcc64 | USDC | cbBTC | 86.00% 2 | 0x3a85e6...7ccfee49 | USDC | WBTC | 86.00% 3 | 0xb32349...acbc86cc | USDC | wstETH | 86.00% 4 | 0x54efde...db24dbc8 | USDC | Token(0x0000...) | 0.00% --- Withdraw Queue (4 markets) --- Pos | Market ID | Loan Token | Collateral Token | LLTV ----+----------------------+--------------+------------------+--------- 1 | 0x54efde...db24dbc8 | USDC | Token(0x0000...) | 0.00% 2 | 0x64d65c...883fcc64 | USDC | cbBTC | 86.00% 3 | 0x3a85e6...7ccfee49 | USDC | WBTC | 86.00% 4 | 0xb32349...acbc86cc | USDC | wstETH | 86.00% --- Queue Summary --- Total Supply Queue Length: 4 Total Withdraw Queue Length: 4 Markets in both queues: 4 ---------------------------------------- ``` {" "} ```solidity // Get queue lengths uint256 supplyQueueLength = IMetaMorpho(vault).supplyQueueLength(); uint256 withdrawQueueLength = IMetaMorpho(vault).withdrawQueueLength(); // Fetch supply queue markets bytes32[] memory supplyQueueIds = new bytes32[](supplyQueueLength); for (uint256 i = 0; i < supplyQueueLength; i++) { supplyQueueIds[i] = IMetaMorpho(vault).supplyQueue(i); } // Fetch withdraw queue markets bytes32[] memory withdrawQueueIds = new bytes32[](withdrawQueueLength); for (uint256 i = 0; i < withdrawQueueLength; i++) { withdrawQueueIds[i] = IMetaMorpho(vault).withdrawQueue(i); } // Get market parameters for each market ID for (uint256 i = 0; i < supplyQueueIds.length; i++) { ( address loanToken, address collateralToken, address oracle, address irm, uint256 lltv ) = IMorpho(morpho).idToMarketParams(supplyQueueIds[i]); // Process market information... } ``` **Key Functions:** - **Queue Lengths**: `supplyQueueLength()`, `withdrawQueueLength()` - **Queue Access**: `supplyQueue(index)`, `withdrawQueue(index)` - **Market Details**: `IMorpho.idToMarketParams(marketId)` returns market configuration **Queue Behavior:** - **Supply Queue**: Ordered by priority for new liquidity allocation - **Withdraw Queue**: Ordered by priority for liquidity withdrawal during redemptions - **Position Matters**: Lower index = higher priority in queue operations - **Market IDs**: Each queue contains bytes32 market identifiers **Important Notes:** - Markets can appear in both queues with different positions - Empty queues return length 0, accessing invalid indices will revert - Market parameters are retrieved from the main Morpho V1 contract ## Configuration & Governance ### Vault Parameters #### Morpho Vaults V2 ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:vault-configuration-unique-vault-v2] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:vault-configuration-all-vaults-v2] ``` {" "} This example demonstrates how to retrieve comprehensive Vault V2 configuration including: - Basic vault information (name, symbol, decimals) - Asset details and financial metrics (totalAssets, totalSupply, fees) - Governance roles (owner, curator) - Adapter configuration (adaptersLength, adapters, adapterRegistry, liquidityAdapter) - Vault gates (receiveAssetsGate, sendSharesGate, receiveSharesGate) - Timelock settings for all critical functions (addAdapter, removeAdapter, setAdapterRegistry, etc.) - Abdication status for each function - Max rate and fee configuration ```typescript // [!include ~/snippets/typescript/07-vault-configuration-v2.ts:imports] // [!include ~/snippets/typescript/07-vault-configuration-v2.ts:client-setup] // [!include ~/snippets/typescript/07-vault-configuration-v2.ts:abis-and-constants] // [!include ~/snippets/typescript/07-vault-configuration-v2.ts:types] // [!include ~/snippets/typescript/07-vault-configuration-v2.ts:helper-functions] // [!include ~/snippets/typescript/07-vault-configuration-v2.ts:core-logic] // [!include ~/snippets/typescript/07-vault-configuration-v2.ts:display-results] // [!include ~/snippets/typescript/07-vault-configuration-v2.ts:main-execution] ``` **Example Output:** ``` Fetching configuration for Vault V2: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145... --- Morpho Vault V2 Configuration --- --- Basic Information --- Vault Name: Keyrock USDC Vault Symbol: kUSDC Vault Address: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145 Vault Decimals: 18 --- Asset Information --- Asset Name: USD Coin Asset Symbol: USDC Asset Address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 Asset Decimals: 6 --- Financial Information --- Total Assets: 380908.53096 USDC Total Supply: 377706.886328436653684714 kUSDC Performance Fee: 0.0000% (annual) Management Fee: 0.0000% (annual) Max Rate: 15.01% APR --- Governance --- Owner: 0xbA75546ACD56b3a9142f94F179b03970eE4283Fd Curator: 0xbA75546ACD56b3a9142f94F179b03970eE4283Fd --- Adapters --- Adapters Length: 1 Adapter Registry: 0x3696c5eAe4a7Ffd04Ea163564571E9CD8Ed9364e Liquidity Adapter: 0x0c2D17F72965944e7755C992E052b725Ab5AA5Ea Configured Adapters: 1. 0x0c2D17F72965944e7755C992E052b725Ab5AA5Ea --- Vault Gates --- Receive Assets Gate: Not set (0x0) Send Shares Gate: Not set (0x0) Receive Shares Gate: Not set (0x0) --- Timelocks & Abdications --- Function Duration Abdicated ---------------------------------------------------------------------- setReceiveAssetsGate 7d 0h 0m No addAdapter 3d 0h 0m No increaseRelativeCap 3d 0h 0m No setReceiveSharesGate 7d 0h 0m No setForceDeallocatePenalty 3d 0h 0m No increaseTimelock 7d 0h 0m No removeAdapter 7d 0h 0m No setSendSharesGate 7d 0h 0m No increaseAbsoluteCap 3d 0h 0m No setAdapterRegistry 0s (No timelock) Yes ---------------------------------------- ``` {" "} ```solidity // Basic vault information string memory vaultName = IMorphoVaultV2(vault).name(); string memory vaultSymbol = IMorphoVaultV2(vault).symbol(); uint8 vaultDecimals = IMorphoVaultV2(vault).decimals(); address assetAddress = IMorphoVaultV2(vault).asset(); // Financial metrics uint256 totalAssets = IMorphoVaultV2(vault).totalAssets(); uint256 totalSupply = IMorphoVaultV2(vault).totalSupply(); uint256 performanceFee = IMorphoVaultV2(vault).performanceFee(); // In WAD (18 decimals) uint256 managementFee = IMorphoVaultV2(vault).managementFee(); // In WAD (18 decimals) uint256 maxRate = IMorphoVaultV2(vault).maxRate(); // Max rate in WAD per second // Governance roles address owner = IMorphoVaultV2(vault).owner(); address curator = IMorphoVaultV2(vault).curator(); // Adapter configuration uint256 adaptersLength = IMorphoVaultV2(vault).adaptersLength(); address adapterRegistry = IMorphoVaultV2(vault).adapterRegistry(); address liquidityAdapter = IMorphoVaultV2(vault).liquidityAdapter(); // Get specific adapter by index for (uint256 i = 0; i < adaptersLength; i++) { address adapter = IMorphoVaultV2(vault).adapters(i); // Process adapter... } // Vault gates address receiveAssetsGate = IMorphoVaultV2(vault).receiveAssetsGate(); address sendSharesGate = IMorphoVaultV2(vault).sendSharesGate(); address receiveSharesGate = IMorphoVaultV2(vault).receiveSharesGate(); // Timelock and abdication for specific function bytes4 functionSelector = bytes4(keccak256("addAdapter(address,uint256,uint256)")); uint256 timelockDuration = IMorphoVaultV2(vault).timelock(functionSelector); bool isAbdicated = IMorphoVaultV2(vault).abdicated(functionSelector); ``` **Key Functions:** - **Basic Info**: `name()`, `symbol()`, `decimals()`, `asset()` - **Financial**: `totalAssets()`, `totalSupply()`, `performanceFee()`, `managementFee()`, `maxRate()` - **Roles**: `owner()`, `curator()` - **Adapters**: `adaptersLength()`, `adapters(index)`, `adapterRegistry()`, `liquidityAdapter()` - **Gates**: `receiveAssetsGate()`, `sendSharesGate()`, `receiveSharesGate()` - **Timelocks**: `timelock(bytes4 selector)`, `abdicated(bytes4 selector)` **Important Notes:** - Vault V2 uses adapters for asset allocation instead of direct market queues - Timelocks are function-specific, identified by their 4-byte selector - Abdication means a function's control has been permanently given up (timelock set to infinity) - High-risk functions typically have 7-day timelocks, medium-risk have 3-day timelocks - Gates control access to deposit/withdrawal/transfer operations (address(0) means no gate) #### Morpho Vaults V1 ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:vault-configuration-unique-vault-v1] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:vault-configuration-all-vaults-v1] ``` {" "} This example demonstrates how to retrieve comprehensive vault configuration including: - Basic vault information (name, symbol, decimals) - Asset details and financial metrics - Governance roles and permissions - Timelock settings and pending changes - Queue lengths and allocator status - Proper handling of zero addresses for unset roles ```typescript // [!include ~/snippets/typescript/07-vault-configuration.ts:imports] // [!include ~/snippets/typescript/07-vault-configuration.ts:client-setup] // [!include ~/snippets/typescript/07-vault-configuration.ts:abis-and-constants] // [!include ~/snippets/typescript/07-vault-configuration.ts:types] // [!include ~/snippets/typescript/07-vault-configuration.ts:helper-functions] // [!include ~/snippets/typescript/07-vault-configuration.ts:core-logic] // [!include ~/snippets/typescript/07-vault-configuration.ts:display-results] // [!include ~/snippets/typescript/07-vault-configuration.ts:main-execution] ``` **Example Output:** ```json Fetching configuration for vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB... --- Morpho Vault Configuration --- --- Basic Information --- Vault Name: Steakhouse USDC Vault Symbol: steakUSDC Vault Address: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB Vault Decimals: 18 --- Asset Information --- Asset Name: USD Coin Asset Symbol: USDC Asset Address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 Asset Decimals: 6 --- Financial Information --- Total Assets: 164441677.475477 USDC Total Supply: 150734916.783575645489233854 steakUSDC Last Total Assets: 164440150.994583 USDC Performance Fee: 0.0000% --- Governance & Roles --- Owner: 0x0A0e559bc3b0950a7e448F0d4894db195b9cf8DD Curator: 0x827e86072B06674a077f592A531dcE4590aDeCdB Guardian: 0xaa0500198B4425DfC4E272FbE42C8E64E21fc03d Fee Recipient: 0x255c7705e8BB334DfCae438197f7C4297988085a Skim Recipient: Not set --- Configuration --- Timelock: 7d 0h 0m Morpho Address: 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb --- Pending Changes --- Pending Timelock: None Valid At: None Pending Guardian: None Valid At: None --- Queue Information --- Supply Queue Length: 4 Withdraw Queue Length: 4 ---------------------------------------- ``` {" "} ```solidity // Basic vault information string memory vaultName = IMetaMorpho(vault).name(); string memory vaultSymbol = IMetaMorpho(vault).symbol(); uint8 vaultDecimals = IMetaMorpho(vault).decimals(); address assetAddress = IMetaMorpho(vault).asset(); // Financial metrics uint256 totalAssets = IMetaMorpho(vault).totalAssets(); uint256 totalSupply = IMetaMorpho(vault).totalSupply(); uint96 performanceFee = IMetaMorpho(vault).fee(); // In WAD (18 decimals) // Governance roles address owner = IMetaMorpho(vault).owner(); address curator = IMetaMorpho(vault).curator(); address guardian = IMetaMorpho(vault).guardian(); address feeRecipient = IMetaMorpho(vault).feeRecipient(); // Configuration uint256 timelock = IMetaMorpho(vault).timelock(); uint256 supplyQueueLength = IMetaMorpho(vault).supplyQueueLength(); uint256 withdrawQueueLength = IMetaMorpho(vault).withdrawQueueLength(); // Check allocator status bool isAllocator = IMetaMorpho(vault).isAllocator(userAddress); // Pending changes (uint192 pendingTimelockValue, uint64 pendingTimelockValidAt) = IMetaMorpho(vault).pendingTimelock(); (address pendingGuardianValue, uint64 pendingGuardianValidAt) = IMetaMorpho(vault).pendingGuardian(); ``` **Key Functions:** - **Basic Info**: `name()`, `symbol()`, `decimals()`, `asset()` - **Financial**: `totalAssets()`, `totalSupply()`, `fee()`, `lastTotalAssets()` - **Roles**: `owner()`, `curator()`, `guardian()`, `feeRecipient()`, `skimRecipient()` - **Configuration**: `timelock()`, `isAllocator()`, `MORPHO()` - **Queues**: `supplyQueueLength()`, `withdrawQueueLength()` - **Pending**: `pendingTimelock()`, `pendingGuardian()` **Note:** Always check for zero addresses when roles are not set. The `fee()` returns a value in WAD format (18 decimals). ### Risk Indicators #### Morpho Vault Warnings Warning `type` can be: - `unrecognized_deposit_asset`, - `unrecognized_vault_curator`, - `not_whitelisted` Warning `level` is either: - YELLOW, - RED. ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:vaults-warnings-morpho-vaults-v2] ``` {" "} ```graphql [API] // [!include ~/snippets/api/all-queries.graphql:vaults-warnings-morpho-vaults-v1] ``` ## Position Tracking ### User All Vaults Position #### Morpho Vaults V2 & V1 ```graphql // [!include ~/snippets/api/all-queries.graphql:user-all-vaults-position-v2-v1] ``` {" "} ### Vault Depositors #### Morpho Vaults V2 ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:depositors-unique-morpho-vault-v2] ``` {" "} #### Morpho Vaults V1 ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:depositors-unique-morpho-vault-v1] ``` ```graphql [Set of Vaults] // [!include ~/snippets/api/all-queries.graphql:depositors-set-of-morpho-vaults-v1] ``` {" "} ### Transaction History #### Morpho Vaults V2 ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:transaction-history-unique-morpho-vault-v2] ``` {" "} #### Morpho Vaults V1 ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:transaction-history-unique-morpho-vault-v1] ``` {" "} ## Historical Data ### APY Historical State #### Morpho Vaults v2 Coming soon. #### Morpho Vaults V1 ```graphql [Unique Vault] // [!include ~/snippets/api/all-queries.graphql:apy-historical-unique-vault] ``` ```graphql [All Vaults] // [!include ~/snippets/api/all-queries.graphql:apy-historical-all-vaults] ``` With those variables: ```json { "options": { "startTimestamp": 1740000000, "endTimestamp": 1742564817, "interval": "DAY" } } ``` {" "} ## [Integrate Rewards for Earn Products](https://docs.morpho.org/build/earn/tutorials/rewards/) Vault depositors on Morpho can earn rewards beyond base lending yield. Integrating rewards display and claiming is essential for providing competitive APY and maximizing user returns. ## What's Unique for Earn Products When building earn products, understand that vault depositors earn rewards from **two sources**: 1. **Direct Vault Campaigns**: Rewards distributed directly to vault depositors 2. **Forwarded Market Campaigns**: Rewards from underlying markets where the vault allocates liquidity **Critical integration requirement:** ``` Net APY = Vault Native APY + Vault Campaign Rewards APR + Forwarded Market Rewards APR ``` ## Integration Steps Follow the centralized rewards tutorials with vault-specific considerations: ### Step 1: Fetch Vault Rewards Data **Follow:** [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) **Vault-specific notes:** - Query both `state.rewards` and `state.allocation[].market.state.rewards` - Calculate weighted average for market rewards based on allocation - Use `supplyAssetsUsd` to determine weights - Alternatively, use `netApy` convenience field for simple total APY ### Step 2: Display Rewards in Your UI **Follow:** [Integrate Rewards Display](/build/rewards/tutorials/integrate-display) **Vault-specific notes:** - Prominently display Net APY (native + all rewards) - Show breakdown: base yield vs. rewards - List reward tokens with their respective APRs - Optionally show which markets contribute to forwarded rewards ### Step 3: Enable Reward Claiming **Follow:** [Claim Rewards](/build/rewards/tutorials/claim-rewards) **Important:** The claiming process is **identical** for all Morpho users (vault depositors, borrowers, market suppliers). Both Merkl and URD use the same claiming flow regardless of how rewards were earned. ## Complete Integration Example For a full working reference implementation: **See:** [Complete Rewards Integration Guide](/build/rewards/guides/complete-integration) This guide includes production-ready code using the [morpho-merkl-recipe](https://github.com/morpho-org/merkl-morpho-recipe). ## Quick Reference | Task | Main Tutorial | Vault-Specific Consideration | |---------------------------|---------------------------------------------------------------------|---------------------------------------------| | **Understanding rewards** | [Reward Campaigns](/build/rewards/concepts/reward-campaigns) | Understand forwarding mechanism | | **Distribution system** | [Distribution Systems](/build/rewards/concepts/distribution-system) | Same Merkl/URD for all users | | **Fetch rewards** | [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) | Query two API locations, manual aggregation | | **Display rewards** | [Integrate Display](/build/rewards/tutorials/integrate-display) | Show total APY breakdown | | **Claim rewards** | [Claim Rewards](/build/rewards/tutorials/claim-rewards) | Same process for all users | ## Need Help? - **Conceptual questions**: [Rewards for Lenders Concept](/build/earn/concepts/rewards) - **Main rewards guide**: [Rewards Integration Guide](/build/rewards/get-started) - **Technical support**: [help.morpho.org](https://help.morpho.org) - **Example code**: [morpho-merkl-recipe](https://github.com/morpho-org/merkl-morpho-recipe) ## [Merkl Distribution System](https://docs.morpho.org/build/rewards/concepts/distribution-system/) [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 ### 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 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 Users can claim their rewards by submitting a transaction with their Merkle proof. - Low waiting period between earning and claiming ## 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 Integrate Merkl for: - All new reward programs (July 2025 onwards) - Current MORPHO token distributions - Third-party incentive programs - Real-time reward tracking ## Integration Points **For Claiming Rewards:** head to the [Integrate Rewards Claim](/build/rewards/tutorials/claim-rewards) section. **For Displaying Rewards:** head to the [Integrate Rewards Display](/build/rewards/tutorials/integrate-display) section. ## [Reward Campaigns on Morpho](https://docs.morpho.org/build/rewards/concepts/reward-campaigns/) 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? 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 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 **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 **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 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:** ``` 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 One of the most important features of Morpho's reward system is **automatic reward forwarding** for vault depositors. ### 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 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 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 **Historical Note** Prior to July 2025, Morpho used a native rewards distribution system (the Universal Rewards Distributor or URD) with different program types called "Market Programs" and "Vault Programs." These legacy programs: - Used weekly distribution cycles (vs. Merkl's 8-hour cycles) - Had different API endpoints and claiming processes - May still have unclaimed rewards for users with historical positions **For integrators:** - Support both Merkl (current) and URD (legacy) claiming. - See [URD Technical Details](/get-started/resources/contracts/rewards/) for legacy support ## Querying Active Campaigns You can see how to retrieve campaigns data in the [Fetch Rewards Data section](/build/rewards/tutorials/fetch-rewards-data). ## Next Steps - **Create campaigns**: Follow the [Create a Rewards Program tutorial](/build/rewards/tutorials/create-program) - **Understand distribution**: Read about [Distribution System](/build/rewards/concepts/distribution-system) - **Fetch data**: Follow the [Fetch Rewards Data tutorial](/build/rewards/tutorials/fetch-rewards-data) - **Display rewards**: See the [Integrate Display tutorial](/build/rewards/tutorials/integrate-display) ## [Integrating Morpho Rewards](https://docs.morpho.org/build/rewards/get-started/) 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 Rewards on Morpho are distributed through **two primary systems**: 1. **Merkl** (Primary - Current Standard) 2. **Morpho URD** (Legacy - Historical Programs) **Important Migration Notice** The rewards distribution has been migrated from the Morpho rewards stack (URD) to the Merkl stack following [MIP 111](https://snapshot.box/#/s:morpho.eth/proposal/0xadf3862d97cf4e8bb84a4b3d5117abe1a9db774e92ad97c65bde22214c0b76c9). **What this means for integrators:** - **New programs**: All new MORPHO rewards and third-party rewards are distributed via Merkl - **Historical programs**: Some rewards from older programs remain claimable via the Morpho URD (Universal Rewards Distributor) - **Complete integration**: Support both systems to provide users access to all available rewards **Important: Non-Claimable Addresses** If you're interacting with Morpho through a smart contract or address that cannot claim rewards, please contact Merkl before depositing to have your rewards redirected. Rewards allocated to addresses that cannot claim aren't recoverable or redirectable after the fact and will stay permanently unclaimable. ## 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 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? 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 A complete rewards integration involves three main components: ### 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 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 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 First, [Understand Reward Programs](/build/rewards/concepts/reward-campaigns) and learn the different program types. Choose your integration approach based on your needs: ### Quick Start (Display Only) Just want to show rewards APR alongside base yield? Start here: 1. [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) - Learn to query both APIs 2. [Integrate Display](/build/rewards/tutorials/integrate-display) - Show rewards in your UI ### Full Integration (Display + Claiming) Building a complete product? Follow this path: 1. [Merkl Distribution System](/build/rewards/concepts/distribution-system) - Understand Distribution 2. [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) - Query rewards information 3. [Claim Rewards](/build/rewards/tutorials/claim-rewards) - Implement claiming for both systems 4. [Complete Integration Guide](/build/rewards/guides/complete-integration) - See a full working example ### Creating Rewards (Issuers) Are you a protocol or DAO looking to create a rewards program? 1. [Create a Program](/build/rewards/tutorials/create-program) - Step-by-step program creation ## Need Help? - **Technical Support**: Visit [help.morpho.org](https://help.morpho.org) - **Merkl Support**: Reach out via [Merkl's documentation](https://docs.merkl.xyz/) ## [Complete Integration Example](https://docs.morpho.org/build/rewards/guides/complete-integration/) 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. **Example Repository** **[morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe)** This is an educational Next.js application that showcases how to: - Fetch vault metrics and rewards from Morpho API - Query user claimable rewards from both Merkl and Morpho URD - Display combined APY (base + rewards) - Implement claim functionality for both systems **⚠️ Educational Purpose**: This is a learning resource. Additional security measures, testing, and auditing are required before production use. ## Repository Overview ### 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 ``` 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 ### 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`** ```typescript 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 **File: `src/lib/helpers/rewards.ts`** ```typescript 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 **File: `src/lib/claiming.ts`** The demo includes claim implementations for both systems: **Merkl Claim:** ```typescript 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:** ```typescript 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 **File: `src/components/VaultMetricsPanel.tsx`** ```tsx 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`** ```tsx 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 ### Prerequisites - Node.js 18+ and yarn - A wallet with Morpho positions (for testing user rewards) ### Quick Start ```bash # 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 The demo includes standalone scripts to understand the data flow: ```bash # See vault APY + rewards calculation yarn demo:yield # Check user claimable rewards yarn demo:rewards # Complete integration flow yarn demo:full ``` **Example Output:** ``` $ 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 ### 1. Error Handling The demo implements graceful error handling: ```typescript 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 Full TypeScript coverage ensures correctness: ```typescript export interface VaultReward { token: string; apr: number; yearlySupplyTokens: string; tokenAddress: string; } export interface UserClaimableReward { token: string; amount: bigint; source: "merkl" | "urd"; } ``` ### 3. Caching Strategy ```typescript 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 ```typescript // 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 When building on this demo for production, consider: ### 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 - **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 - **Transaction notifications**: Toast notifications for claim status - **Transaction history**: Show past claims - **Gas estimation**: Display estimated gas costs before claiming ### 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 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 - **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](/build/rewards/tutorials/fetch-rewards-data) - [Claim Rewards](/build/rewards/tutorials/claim-rewards) - [Integrate Display](/build/rewards/tutorials/integrate-display) ## [Rewards: Developer Resources](https://docs.morpho.org/build/rewards/resources/all/) 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 ### Morpho API (Recommended for Vault/Market 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](/tools/offchain/api/morpho/) - **Rewards Queries**: - [Morpho Markets Rewards](/tools/offchain/api/rewards/#morpho-markets-rewards) - [Morpho Vaults Rewards](/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) 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) 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 ### 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 **Mainnet (Ethereum):** - URD Address: `0x330eefa8a787552DC5cAd3C3cA644844B1E61Ddb` **Other Chains:** - See [Rewards Addresses](/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 **Merkl Distributor ABI:** ```json [ { "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):** ```json [ { "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 ### 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 - **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 ### 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 **Learn More**: [Morpho SDKs Documentation](/tools/offchain/sdks/get-started/) ### 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 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 ### 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 - **Developer Hub**: [/tools/](/tools/) - **API Documentation**: [/tools/offchain/api/rewards/](/tools/offchain/api/rewards/) ## Onchain Data Sources - **Morpho Subgraphs**: [/tools/offchain/subgraphs/](/tools/offchain/subgraphs/) - **Merkl Subgraphs**: See [Merkl docs](https://docs.merkl.xyz/) ## Tutorials & Guides ### Getting Started - [Rewards Integration Overview](/build/rewards/get-started) - [Understanding Reward Programs](/build/rewards/concepts/reward-campaigns) - [Distribution Systems (Merkl vs URD)](/build/rewards/concepts/distribution-system) ### Step-by-Step Tutorials - [Create a Rewards Program](/build/rewards/tutorials/create-program) - [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) - [Claim Rewards](/build/rewards/tutorials/claim-rewards) - [Integrate Rewards Display](/build/rewards/tutorials/integrate-display) ### Advanced - [Complete Integration Example](/build/rewards/guides/complete-integration) - [URD Technical Details](/get-started/resources/contracts/rewards/) ## Support Channels ### For Integrators - **Technical Questions**: [help.morpho.org](https://help.morpho.org) ### For Reward Issuers - **Program Creation Help**: [Merkl Docs](https://docs.merkl.xyz/) ## Monitoring & Analytics ### 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 - **Dune Analytics**: [Morpho Dashboards](/tools/offchain/dune/) - **DefiLlama**: Track TVL and yields across Morpho ## Governance & Updates ### Morpho Governance - **Snapshot**: [snapshot.box/#/s:morpho.eth](https://snapshot.box/#/s:morpho.eth) ### Migration Information - **MIP 111**: [Snapshot Proposal](https://snapshot.box/#/s:morpho.eth/proposal/0xadf3862d97cf4e8bb84a4b3d5117abe1a9db774e92ad97c65bde22214c0b76c9) - Migration to Merkl ## 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? If you can't find what you're looking for, reach out via: - **Chat**: [help.morpho.org](https://help.morpho.org) ## [Claim Rewards](https://docs.morpho.org/build/rewards/tutorials/claim-rewards/) 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 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 - Understanding of [Distribution Systems](/build/rewards/concepts/distribution-system) - Familiarity with [Fetching Rewards Data](/build/rewards/tutorials/fetch-rewards-data) - A web3 library (viem, ethers, web3.js) - User's wallet connected to your app ## Claiming via Merkl Merkl is the primary distribution system for current reward programs. ### Step 1: Fetch Claim Data **Endpoint:** ``` GET https://api.merkl.xyz/v4/claim?user={address}&chainId={chainId} ``` **Example:** ```typescript 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:** ```json { "claim": { "user": "0x...", "tokens": ["0xTOKEN1", "0xTOKEN2"], "amounts": ["1000000000000000000", "2000000000000000000"], "proofs": [ ["0xproof1a", "0xproof1b"], ["0xproof2a", "0xproof2b"] ] } } ``` ### Step 2: Execute the Claim Using **viem**: ```typescript 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 ```typescript 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 The URD handles legacy reward programs. While new programs use Merkl, many users still have unclaimed URD rewards. ### Step 1: Fetch Distribution Data **Endpoint:** ``` GET https://rewards.morpho.org/v1/users/{address}/distributions ``` **Example:** ```typescript 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:** ```json [ { "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 Before claiming, verify how much the user has already claimed to avoid unnecessary transactions: ```typescript 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 Using Pre-formatted `tx_data` The API provides ready-to-use transaction calldata: ```typescript 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 - **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) ## [Create a Rewards Program](https://docs.morpho.org/build/rewards/tutorials/create-program/) This tutorial guides you through creating a new rewards program for Morpho Vaults or Markets using **Merkl**, the current standard for reward distribution. **Target Audience** This tutorial is for: - Protocol teams looking to incentivize specific Morpho Markets or Vaults - DAOs planning reward campaigns - Token issuers wanting to boost liquidity in Morpho - Projects building on top of Morpho ## 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](/build/rewards/concepts/reward-campaigns) ## 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 Merkl provides a user-friendly interface for creating reward campaigns. The process differs slightly between Vault and Market programs. #### Jump on the studio https://studio.merkl.xyz/create-campaign/lend #### Select `Morpho` as protocol #### Fill the inputs as per Merkl doc ## Next Steps - **Fetch campaign data**: Follow the [Fetch Rewards Data tutorial](/build/rewards/tutorials/fetch-rewards-data) - **Integrate display**: Check out the [Integrate Display tutorial](/build/rewards/tutorials/integrate-display) - **Enable claiming**: See the [Claim Rewards tutorial](/build/rewards/tutorials/claim-rewards) ## [Fetch Rewards Data](https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data/) 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 - 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 - Basic understanding of [Reward Programs](/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 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 ### 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 ```graphql 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:** ```json { "address": "0x9aB2d181E4b87ba57D5eD564D3eF652C4E710707", "chainId": 8453 } ``` #### Calculate Total Rewards APR Vault rewards require **manual aggregation** with weighted averaging: ```typescript 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 For simple total APY display without breakdown: ```typescript 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 Markets can have rewards for **supply** and **borrow**. ### Using Morpho API ```graphql 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 ### Merkl API (Current Programs) To get a user's claimable Merkl rewards: **Endpoint:** ``` GET https://api.merkl.xyz/v4/userRewards?user={address} ``` **Example:** ```bash curl "https://api.merkl.xyz/v4/userRewards?user=0x1234...5678" ``` **Response Structure:** ```json { "1": { // Chain ID "0xVAULT_OR_MARKET_ADDRESS": { "claimable": { "0xREWARD_TOKEN_ADDRESS": { "accumulated": "1234567890", "unclaimed": "1234567890", "symbol": "MORPHO", "decimals": 18 } } } } } ``` **TypeScript Example:** ```typescript 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) To get a user's URD rewards: **Endpoint:** ``` GET https://rewards.morpho.org/v1/users/{address}/rewards ``` **Example:** ```bash curl "https://rewards.morpho.org/v1/users/0x0ec553110e53122d1226646670a8475D4C8E6F04/rewards" ``` **Response Structure:** ```json [ { "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:** ```typescript 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 To show a complete rewards picture, you'll need to combine data from Merkl and URD: ```typescript 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 ### 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 Always fetch from multiple APIs in parallel: ```typescript const [vaultData, merklRewards, urdRewards] = await Promise.all([ fetchVaultFromMorphoAPI(vaultAddress), fetchMerklRewards(userAddress), fetchURDRewards(userAddress), ]); ``` ### Error Handling ```typescript 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 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 - **Display rewards**: Follow the [Integrate Display tutorial](/build/rewards/tutorials/integrate-display) - **Enable claiming**: See the [Claim Rewards tutorial](/build/rewards/tutorials/claim-rewards) - **Full example**: Check out the [Complete Integration Guide](/build/rewards/guides/complete-integration) ## 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) ## [Integrate Rewards Display](https://docs.morpho.org/build/rewards/tutorials/integrate-display/) 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 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 ### Fetching and Calculating Total APY ```typescript 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 ```tsx 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 **Highlight Total Yield:** ```tsx
Total APY {totalApy.toFixed(2)}%
``` **Show Breakdown on Hover/Click:** ```tsx
Base APY: {baseApy}%
MORPHO Rewards: +{morphoApr}%
Partner Rewards: +{partnerApr}%
}> {totalApy}%
``` **Use Badges for Rewards:** ```tsx {rewards.length > 0 && ( +{rewardsApr.toFixed(1)}% Rewards )} ``` ## Displaying User Claimable Rewards ### Fetching User Rewards from Both Systems ```typescript 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 ```tsx 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 For portfolio or dashboard views: ```tsx 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 Provide transparency about active programs: ```tsx 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 ### Polling for Updates ```typescript 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 For a more dynamic experience: ```tsx 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 ### No Rewards Available ```tsx {rewards.length === 0 ? (

No active reward programs for this vault

Check back later or explore other vaults

) : ( )} ``` ### Failed to Fetch Rewards ```tsx {error ? (

Unable to load rewards data

) : ( )} ``` ### Dust Amounts Don't show tiny amounts that aren't worth claiming: ```typescript 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 - **Use semantic HTML**: `` for tabular data, `