{
  "/get-started/products/": {
    "title": "Products",
    "url": "https://docs.morpho.org/get-started/products/",
    "section": "Get Started",
    "content": "## Earn & Borrow \n\nBuild powerful financial applications with Morpho's decentralized lending infrastructure.\n\n    \n      Earn\n      Put your crypto to work\n      \n        \n          +\n          Simple\n        +\n          Optimized\n        +\n          Tailored\n        +\n          Non-custodial\n      \n      \n      \n          Build →\n      \n    \n\n    \n  \n\n  \n      Borrow\n      Provide collateral to borrow any asset\n      \n        \n          +\n          Low costs\n        \n        \n          +\n          Higher collateralization factors\n        \n        \n          +\n          Per market rates\n        \n        \n          +\n          Zero fees\n        \n      \n      \n      \n        \n          Build →"
  },
  "/get-started/resources/addresses/": {
    "title": "Addresses",
    "url": "https://docs.morpho.org/get-started/resources/addresses/",
    "section": "Get Started",
    "content": "## Morpho V2 Contracts\n\n| Contract                         | Address                                                                                                                                                                                                 | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0xA1D94F746dEfa1928926b84fB2596c06926C0405 ](https://etherscan.io/address/0xA1D94F746dEfa1928926b84fB2596c06926C0405#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xD1B8E2dee25c2b89DCD2f98448a7ce87d6F63394 ](https://etherscan.io/address/0xD1B8E2dee25c2b89DCD2f98448a7ce87d6F63394#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0x32BB1c0D48D8b1B3363e86eeB9A0300BAd61ccc1 ](https://etherscan.io/address/0x32BB1c0D48D8b1B3363e86eeB9A0300BAd61ccc1#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0x3696c5eAe4a7Ffd04Ea163564571E9CD8Ed9364e ](https://etherscan.io/address/0x3696c5eAe4a7Ffd04Ea163564571E9CD8Ed9364e#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x6b46fa3cc9EBF8aB230aBAc664E37F2966Bf7971 ](https://arbiscan.io/address/0x6b46fa3cc9EBF8aB230aBAc664E37F2966Bf7971#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xD8Fc8a85779551e78B516da9f74061cb3b086793 ](https://arbiscan.io/address/0xD8Fc8a85779551e78B516da9f74061cb3b086793#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0xeF84b1ecEbe43283ec5AF95D7a5c4D7dE0a9859b ](https://arbiscan.io/address/0xeF84b1ecEbe43283ec5AF95D7a5c4D7dE0a9859b#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0xc00eb3c7aD1aE986A7f05F5A9d71aCa39c763C65 ](https://arbiscan.io/address/0xc00eb3c7aD1aE986A7f05F5A9d71aCa39c763C65#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                                              | Source Code                                                                              |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0xf7b1d9e43BAeA3705f2B303693766ACbcfec6A55 ](https://snowtrace.io/address/0xf7b1d9e43BAeA3705f2B303693766ACbcfec6A55/contract/43114/code?chainid=43114)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                       |\n| MorphoMarketV1 AdapterV2Factory  | [ 0x9633D22Bb8F42f6f70DbbBe34c11EB9209769b8b ](https://snowtrace.io/address/0x9633D22Bb8F42f6f70DbbBe34c11EB9209769b8b/contract/43114/code?chainid=43114)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                       |\n| 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) |\n\n| Contract                         | Address                                                                                                                                                                                                 | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x4501125508079A99ebBebCE205DeC9593C2b5857 ](https://basescan.org/address/0x4501125508079A99ebBebCE205DeC9593C2b5857#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xF42D9c36b34c9c2CF3Bc30eD2a52a90eEB604642 ](https://basescan.org/address/0xF42D9c36b34c9c2CF3Bc30eD2a52a90eEB604642#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0x9a1B378C43BA535cDB89934230F0D3890c51C0EB ](https://basescan.org/address/0x9a1B378C43BA535cDB89934230F0D3890c51C0EB#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0x5C2531Cbd2cf112Cf687da3Cd536708aDd7DB10a ](https://basescan.org/address/0x5C2531Cbd2cf112Cf687da3Cd536708aDd7DB10a#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                                 | Source Code                                                                                                        |\n| :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x2C83a291cF1428F915e60D4dC0c063498d9B137A ](https://botanixscan.io/address/0x2C83a291cF1428F915e60D4dC0c063498d9B137A/contract/3637/code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xda8d0b0e00A3062FD09005bBAe843a1C82d67a97 ](https://botanixscan.io/address/0xda8d0b0e00A3062FD09005bBAe843a1C82d67a97/contract/3637/code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0xa4a4b6D925734fa1e45Bb38fbA20d32BB39A3E7A ](https://botanixscan.io/address/0xa4a4b6D925734fa1e45Bb38fbA20d32BB39A3E7A/contract/3637/code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0xcA0CCC121000561134BF5f2a0cF8b8d6FC4Cf044 ](https://botanixscan.io/address/0xcA0CCC121000561134BF5f2a0cF8b8d6FC4Cf044/contract/3637/code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                                        | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x3137e22F379A1Df004DDb10EBbecF1CfD8CbC0e2 ](https://explorer.mainnet.citrea.xyz/address/0x3137e22F379A1Df004DDb10EBbecF1CfD8CbC0e2?tab=contract)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0x01Ff31888b1FB51f951273C409f653Dba5Ce8200 ](https://explorer.mainnet.citrea.xyz/address/0x01Ff31888b1FB51f951273C409f653Dba5Ce8200?tab=contract)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0x83dd673Fa2C4DE16cAAF0e6109845EeEbb6d1E00 ](https://explorer.mainnet.citrea.xyz/address/0x83dd673Fa2C4DE16cAAF0e6109845EeEbb6d1E00?tab=contract)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                        | Source Code                                                                              |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x05519a0835a1bFD90f110aA7ca46e9A5F81Ed3b4 ](https://explorer.cronos.org/address/0x05519a0835a1bFD90f110aA7ca46e9A5F81Ed3b4#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                       |\n| MorphoVaultV1 AdapterFactory     | [ 0x8840F99Bb2D4f69fb02b2d019384C5c98a11746c ](https://explorer.cronos.org/address/0x8840F99Bb2D4f69fb02b2d019384C5c98a11746c#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                       |\n| MorphoRegistry                   | [ 0x295e0aB80f8234398cd0E51C85D873ee69E5F0DD ](https://explorer.cronos.org/address/0x295e0aB80f8234398cd0E51C85D873ee69E5F0DD#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries) |\n\n| Contract                         | Address                                                                                                                                                                                                    | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0xD7217E5687FF1071356C780b5fe4803D9D967da7 ](https://hyperevmscan.io/address/0xD7217E5687FF1071356C780b5fe4803D9D967da7#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xdf5202e29654e02011611A086f15477880580CAc ](https://hyperevmscan.io/address/0xdf5202e29654e02011611A086f15477880580CAc#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0xaEff6Ef4B7bbfbAadB18b634A8F11392CBeB72Be ](https://hyperevmscan.io/address/0xaEff6Ef4B7bbfbAadB18b634A8F11392CBeB72Be#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0x857B55cEb57dA0C2A83EE08a8dB529B931089aee ](https://hyperevmscan.io/address/0x857B55cEb57dA0C2A83EE08a8dB529B931089aee#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                   | Source Code                                                                                                        |\n| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0xFcb8b57E56787bB29e130Fca67f3c5a1232975D1 ](https://katanascan.com/address/0xFcb8b57E56787bB29e130Fca67f3c5a1232975D1#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xc8D22B1adD3D176600E9952e7876e9249254cAAF ](https://katanascan.com/address/0xc8D22B1adD3D176600E9952e7876e9249254cAAF#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0x6d6A3ba62836d6B40277767dCAc8fd390d4BcedC ](https://katanascan.com/address/0x6d6A3ba62836d6B40277767dCAc8fd390d4BcedC#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0xA9132a09838fD20304dF2B2892679d06A4cc6371 ](https://katanascan.com/address/0xA9132a09838fD20304dF2B2892679d06A4cc6371#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                    | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x5DC11CF8BA4C39d1194F91218D35008d9F52A5d0 ](https://lineascan.build/address/0x5DC11CF8BA4C39d1194F91218D35008d9F52A5d0#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0x6FaF26DD640e22457cA4fd5DA702BA3E169eEd87 ](https://lineascan.build/address/0x6FaF26DD640e22457cA4fd5DA702BA3E169eEd87#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0xcAB7C66F7191Ad3Ef1e7fEeb67F3137BC975F8cE ](https://lineascan.build/address/0xcAB7C66F7191Ad3Ef1e7fEeb67F3137BC975F8cE#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0x122Ea8ff8888C29F8736665d576e3fAEF15D27D5 ](https://lineascan.build/address/0x122Ea8ff8888C29F8736665d576e3fAEF15D27D5#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [0x8B2F922162FBb60A6a072cC784A2E4168fB0bb0c](https://monadscan.com/address/0x8B2F922162FBb60A6a072cC784A2E4168fB0bb0c#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [0x9f3c0999425656fD189C69a8aD68cB64986D644A](https://monadscan.com/address/0x9f3c0999425656fD189C69a8aD68cB64986D644A#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [0xa00666E86C7e2FA8d2c78d9481E687e098340180](https://monadscan.com/address/0xa00666E86C7e2FA8d2c78d9481E687e098340180#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [0x6a42f8b46224baA4DbBBc2F860F4675eeA7bd52B](https://monadscan.com/address/0x6a42f8b46224baA4DbBBc2F860F4675eeA7bd52B#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                            | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x6128b680b277Bf4Df80DFE9D8c55A498660870ef ](https://optimistic.etherscan.io/address/0x6128b680b277Bf4Df80DFE9D8c55A498660870ef#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xEe9F7C64dD827ED7b5CAA2272936366FAca00CF3 ](https://optimistic.etherscan.io/address/0xEe9F7C64dD827ED7b5CAA2272936366FAca00CF3#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0x71B299bDb52b6396429cd1E11c418324502CB434 ](https://optimistic.etherscan.io/address/0x71B299bDb52b6396429cd1E11c418324502CB434#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0xD1346be260cd22Eab9E6163010b0D5CbfAAAD32b ](https://optimistic.etherscan.io/address/0xD1346be260cd22Eab9E6163010b0D5CbfAAAD32b#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                                | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0xD7373D3597C26e7340B0612C938EEFE6DE02Ab30 ](https://plasmascan.to/address/0xD7373D3597C26e7340B0612C938EEFE6DE02Ab30/contract/9745/code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0x42432F31D085ECb8D9C128092c84b084123C624e ](https://plasmascan.to/address/0x42432F31D085ECb8D9C128092c84b084123C624e/contract/9745/code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0xB241753668F929EB78A0069330c31305C0C83255 ](https://plasmascan.to/address/0xB241753668F929EB78A0069330c31305C0C83255/contract/9745/code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0x171b2807E8ce8fb853C37bc3C3b4805aBf6f9896 ](https://plasmascan.to/address/0x171b2807E8ce8fb853C37bc3C3b4805aBf6f9896/contract/9745/code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                               | Source Code                                                                                                        |\n| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x4f0a370bb367843CFd914c4d9972523aD2f8FCc9 ](https://explorer.plume.org/address/0x4f0a370bb367843CFd914c4d9972523aD2f8FCc9?tab=contract)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0x5935fFcD1C5D269840ae7c685bC957A73E04AEDB ](https://explorer.plume.org/address/0x5935fFcD1C5D269840ae7c685bC957A73E04AEDB?tab=contract)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0xB7c243AfACb25870775ADFdAe9D0EAc2324dD152 ](https://explorer.plume.org/address/0xB7c243AfACb25870775ADFdAe9D0EAc2324dD152?tab=contract)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0x60d3184BDD31BAE7De973894B3bA0b3B6900B79a ](https://explorer.plume.org/address/0x60d3184BDD31BAE7De973894B3bA0b3B6900B79a?tab=contract)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                    | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0xC11a53eE9B1eCc7a068D8e40F8F17926584F97Cf ](https://polygonscan.com/address/0xC11a53eE9B1eCc7a068D8e40F8F17926584F97Cf#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xEb174FEA51Da241eB3B516959B216e013de2888a ](https://polygonscan.com/address/0xEb174FEA51Da241eB3B516959B216e013de2888a#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0xc0006f52B38625C283dd2f972dD9B779A5851Dd0 ](https://polygonscan.com/address/0xc0006f52B38625C283dd2f972dD9B779A5851Dd0#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0xb70a43821d2707fA9d0EDd9511CC499F468Ba564 ](https://polygonscan.com/address/0xb70a43821d2707fA9d0EDd9511CC499F468Ba564#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                   | Source Code                                                                                                        |\n| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x7fc35488803D49D00a94b206A223f7661898BE3a ](https://stablescan.xyz/address/0x7fc35488803D49D00a94b206A223f7661898BE3a#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0x4EF83ACD552598a1196c1aBDD0bA2EdE6f2237B4 ](https://stablescan.xyz/address/0x4EF83ACD552598a1196c1aBDD0bA2EdE6f2237B4#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0x9282DBa3d1788f4f02B5DdFc4fc5985e70197620 ](https://stablescan.xyz/address/0x9282DBa3d1788f4f02B5DdFc4fc5985e70197620#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0xCe93fcB2849EB886F1e81d45D2747dF803f843C3 ](https://stablescan.xyz/address/0xCe93fcB2849EB886F1e81d45D2747dF803f843C3#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0xC9b34c108014B44e5a189A830e7e04c56704a0c9 ](https://uniscan.xyz/address/0xC9b34c108014B44e5a189A830e7e04c56704a0c9#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xf1Ab9e885C0faa0cbCEd407498BBA895537aD754 ](https://uniscan.xyz/address/0xf1Ab9e885C0faa0cbCEd407498BBA895537aD754#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0x9a13bdA35F98811fbAcf097966b2C838f3F9c58C ](https://uniscan.xyz/address/0x9a13bdA35F98811fbAcf097966b2C838f3F9c58C#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0xB9130D2A87d7c60ED7E7e4b25bdA6e3E6841becB ](https://uniscan.xyz/address/0xB9130D2A87d7c60ED7E7e4b25bdA6e3E6841becB#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n| Contract                         | Address                                                                                                                                                                                                  | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| VaultV2Factory                   | [ 0x6846EA318B6B987Ee6b28eBFd87c3409F1d13108 ](https://worldscan.org/address/0x6846EA318B6B987Ee6b28eBFd87c3409F1d13108#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoVaultV1 AdapterFactory     | [ 0xbF7DEa3756668C7E396C655D646C039826ba8416 ](https://worldscan.org/address/0xbF7DEa3756668C7E396C655D646C039826ba8416#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoMarketV1 AdapterV2Factory  | [ 0xEd0b06fcdDB6dD0985e2de9D22ad034d313b7dBd ](https://worldscan.org/address/0xEd0b06fcdDB6dD0985e2de9D22ad034d313b7dBd#code)  | [vault-v2](https://github.com/morpho-org/vault-v2)                                                                 |\n| MorphoRegistry                   | [ 0x06A47994B4890dcA28C076969cedE1151d86EFCF ](https://worldscan.org/address/0x06A47994B4890dcA28C076969cedE1151d86EFCF#code)  | [vault-v2-adapter-registries](https://github.com/morpho-org/vault-v2-adapter-registries)                           |\n\n## Morpho V1 Contracts\n\n| Contract                         | Address                                                                                                                 | Source Code                                                                                                        |\n| :------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb ](https://etherscan.io/address/0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC ](https://etherscan.io/address/0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| Morpho ChainlinkOracleV2 Factory | [ 0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766 ](https://etherscan.io/address/0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766)  | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles/tree/v1.0.0)                               |\n| MetaMorpho Factory V1.1          | [ 0x1897A8997241C1cD4bD0698647e4EB7213535c24 ](https://etherscan.io/address/0x1897A8997241C1cD4bD0698647e4EB7213535c24)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| MetaMorpho Factory [OLD]         | [ 0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101 ](https://etherscan.io/address/0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101)  | [metamorpho](https://github.com/morpho-org/metamorpho/tree/c5e758da97d210ede921bf228d37d31e744bd5bf)               |\n| Public Allocator                 | [ 0xfd32fA2ca22c76dD6E550706Ad913FC6CE91c75D ](https://etherscan.io/address/0xfd32fA2ca22c76dD6E550706Ad913FC6CE91c75D)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x6FF33615e792E35ed1026ea7cACCf42D9BF83476 ](https://etherscan.io/address/0x6FF33615e792E35ed1026ea7cACCf42D9BF83476)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                    | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xc85CE8ffdA27b646D269516B8d0Fa6ec2E958B55 ](https://abscan.org/address/0xc85CE8ffdA27b646D269516B8d0Fa6ec2E958B55#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x609f3DF49806B5617A0Bd3301f04Ac3CB26d9e82 ](https://abscan.org/address/0x609f3DF49806B5617A0Bd3301f04Ac3CB26d9e82#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x1058DA51242dF63bA3A61c838A61405ea6Edb083 ](https://abscan.org/address/0x1058DA51242dF63bA3A61c838A61405ea6Edb083#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x6c247b1F6182318877311737BaC0844bAa518F5e ](https://arbiscan.io/address/0x6c247b1F6182318877311737BaC0844bAa518F5e)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0x66F30587FB8D4206918deb78ecA7d5eBbafD06DA ](https://arbiscan.io/address/0x66F30587FB8D4206918deb78ecA7d5eBbafD06DA)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0x878988f5f561081deEa117717052164ea1Ef0c82 ](https://arbiscan.io/address/0x878988f5f561081deEa117717052164ea1Ef0c82)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| Public Allocator                 | [ 0x769583Af5e9D03589F159EbEC31Cc2c23E8C355E ](https://arbiscan.io/address/0x769583Af5e9D03589F159EbEC31Cc2c23E8C355E)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x635c31B5DF1F7EFbCbC07E302335Ef4230758e3d ](https://arbiscan.io/address/0x635c31B5DF1F7EFbCbC07E302335Ef4230758e3d)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                                                                                                              | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| 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)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n\n| Contract                         | Address                                                                                                                 | Source Code                                                                                                        |\n| :------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb ](https://basescan.org/address/0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0x46415998764C29aB2a25CbeA6254146D50D22687 ](https://basescan.org/address/0x46415998764C29aB2a25CbeA6254146D50D22687)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0xFf62A7c278C62eD665133147129245053Bbf5918 ](https://basescan.org/address/0xFf62A7c278C62eD665133147129245053Bbf5918)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| MetaMorpho Factory [OLD]         | [ 0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101 ](https://basescan.org/address/0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101)  | [metamorpho](https://github.com/morpho-org/metamorpho/tree/c5e758da97d210ede921bf228d37d31e744bd5bf)               |\n| Public Allocator                 | [ 0xA090dD1a701408Df1d4d0B85b716c87565f90467 ](https://basescan.org/address/0xA090dD1a701408Df1d4d0B85b716c87565f90467)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x8cd16b62E170Ee0bA83D80e1F80E6085367e2aef ](https://basescan.org/address/0x8cd16b62E170Ee0bA83D80e1F80E6085367e2aef)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                      | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xAeA7eFF1bD3c875c18ef50F0387892dF181431C6 ](https://www.btrscan.com/address/0xaea7eff1bd3c875c18ef50f0387892df181431c6?tab=Contract)       | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x3A1db0038361528756bED147abe3d41255c7128c ](https://www.btrscan.com/address/0x3A1db0038361528756bED147abe3d41255c7128c?tab=Contract)       | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x4E28CAE07A008FF2D7D345992C969118eb253CD6 ](https://www.btrscan.com/address/0x4E28CAE07A008FF2D7D345992C969118eb253CD6?tab=Contract)       | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                      | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x01b0Bd309AA75547f7a37Ad7B1219A898E67a83a ](https://bscscan.com/address/0x01b0Bd309AA75547f7a37Ad7B1219A898E67a83a#code)                   | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x842bEccF8eBC11006c4bE96DEfE09b60326D0495 ](https://bscscan.com/address/0x842bEccF8eBC11006c4bE96DEfE09b60326D0495#code)                   | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0xEB8871F0FA8aB787AbCD28d1095f7B486d241D42 ](https://bscscan.com/address/0xEB8871F0FA8aB787AbCD28d1095f7B486d241D42#code)                   | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                      | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x8183d41556Be257fc7aAa4A48396168C8eF2bEAD ](https://botanixscan.io/address/0x8183d41556Be257fc7aAa4A48396168C8eF2bEAD/contract/3637/code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x1251473c33E398226C7b9453d75dF59548f1D228 ](https://botanixscan.io/address/0x1251473c33E398226C7b9453d75dF59548f1D228/contract/3637/code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x2e999ddEbd85bdA0B87C370f30ad18cCb943De60 ](https://botanixscan.io/address/0x2e999ddEbd85bdA0B87C370f30ad18cCb943De60/contract/3637/code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                           | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xea4f2979D7A99B40404b447Cf71c008e3805760F ](https://camp.cloud.blockscout.com/address/0xea4f2979D7A99B40404b447Cf71c008e3805760F?tab=contract)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| 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)                                     |\n| PreLiquidation Factory           | [ 0xD55fA5DF6F1A21C2B93009A702aad3a0891C1B48 ](https://camp.cloud.blockscout.com/address/0xD55fA5DF6F1A21C2B93009A702aad3a0891C1B48?tab=contract)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                     | Source Code                                                                                                        |\n| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xd24ECdD8C1e0E57a4E26B1a7bbeAa3e95466A569 ](https://celoscan.io/address/0xd24ECdD8C1e0E57a4E26B1a7bbeAa3e95466A569#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x3Fe12193D178B76BaF4e23a083A64e49ACDE3188 ](https://celoscan.io/address/0x3Fe12193D178B76BaF4e23a083A64e49ACDE3188#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x717a3eF7D366F5ce4636011924D0Bd65ea5eCE2f ](https://celoscan.io/address/0x717a3eF7D366F5ce4636011924D0Bd65ea5eCE2f#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                                                                                                        | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x99D31FEcc885204b4136ea5D2ef2a37F36E3AeB8 ](https://explorer.mainnet.citrea.xyz/address/0x99D31FEcc885204b4136ea5D2ef2a37F36E3AeB8?tab=contract)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| PreLiquidation Factory           | [ 0xdc1078a8A29dB9FB1eb9266e92fA5f2130432E5A ](https://explorer.mainnet.citrea.xyz/address/0xdc1078a8A29dB9FB1eb9266e92fA5f2130432E5A?tab=contract)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xc2B1E031540e3F3271C5F3819F0cC7479a8DdD90 ](https://cornscan.io/address/0xc2B1E031540e3F3271C5F3819F0cC7479a8DdD90)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0x58a42117d753a0e69694545DfA19d64c2fB759fB ](https://cornscan.io/address/0x58a42117d753a0e69694545DfA19d64c2fB759fB)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0xe430821595602eA5DD0cD350f86987437c7362fA ](https://cornscan.io/address/0xe430821595602eA5DD0cD350f86987437c7362fA)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| Public Allocator                 | [ 0xDFde06e2B2A2D718eE5560b73dA4F830E56A2f10 ](https://cornscan.io/address/0xDFde06e2B2A2D718eE5560b73dA4F830E56A2f10)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0xb9065AC18d3EBdb3263B77B587f9c5CD570545D1 ](https://cornscan.io/address/0xb9065AC18d3EBdb3263B77B587f9c5CD570545D1)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                                                                                        | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xDF9a1DC07e5dEe5ccCCaBeC35e446C70fAF7434e ](https://explorer.cronos.org/address/0xDF9a1DC07e5dEe5ccCCaBeC35e446C70fAF7434e#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0xFEAbEf95f3C937Ff4d5fD70005CF3392f8Ca02d5 ](https://explorer.cronos.org/address/0xFEAbEf95f3C937Ff4d5fD70005CF3392f8Ca02d5#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x8bedC738f5F0D54dF7E003297AAc6692b870F3Ed ](https://explorer.cronos.org/address/0x8bedC738f5F0D54dF7E003297AAc6692b870F3Ed#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                        | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xbCE7364E63C3B13C73E9977a83c9704E2aCa876e ](https://explorer.etherlink.com/address/0xbCE7364E63C3B13C73E9977a83c9704E2aCa876e?tab=contract)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x8b8B1bd41d36c06253203CD21463994aB752c1e6 ](https://explorer.etherlink.com/address/0x8b8B1bd41d36c06253203CD21463994aB752c1e6?tab=contract)  | | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0xd1c37fDd941256FC184eF3A07Be540a90b81Ec21 ](https://explorer.etherlink.com/address/0xd1c37fDd941256FC184eF3A07Be540a90b81Ec21?tab=contract)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                 | Source Code                                                                                                        |\n| :------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xa6030627d724bA78a59aCf43Be7550b4C5a0653b ](https://fraxscan.com/address/0xa6030627d724bA78a59aCf43Be7550b4C5a0653b)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0xA0D4D77b5D9933073572E19C172BFE866312673b ](https://fraxscan.com/address/0xA0D4D77b5D9933073572E19C172BFE866312673b)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0x27D4Af0AC9E7FDfA6D0853236f249CC27AE79488 ](https://fraxscan.com/address/0x27D4Af0AC9E7FDfA6D0853236f249CC27AE79488)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| Public Allocator                 | [ 0x37a888192165fC39884f87c64E2476BfD2C09675 ](https://fraxscan.com/address/0x37a888192165fC39884f87c64E2476BfD2C09675)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x373ccddcd3F09D2e1430B3F2b290B9bF56Ae7336 ](https://fraxscan.com/address/0x373ccddcd3F09D2e1430B3F2b290B9bF56Ae7336)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                       | Source Code                                                                                                        |\n| :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xB74D4dd451E250bC325AFF0556D717e4E2351c66 ](https://gnosisscan.io/address/0xB74D4dd451E250bC325AFF0556D717e4E2351c66#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x6F3313A395Fb09a56502710aB75cf69fb692270A ](https://gnosisscan.io/address/0x6F3313A395Fb09a56502710aB75cf69fb692270A#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x919d1273014Ec7e34aDb952Bff161D6dC9964261 ](https://gnosisscan.io/address/0x919d1273014Ec7e34aDb952Bff161D6dC9964261#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                      | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xa4Ca2c2e25b97DA19879201bA49422bc6f181f42 ](https://explorer.hemi.xyz/address/0xa4Ca2c2e25b97DA19879201bA49422bc6f181f42)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x4107Ea1746909028d6212B315dE5fE9538F9eb39 ](https://explorer.hemi.xyz/address/0x4107Ea1746909028d6212B315dE5fE9538F9eb39)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x40F2896C551194e364F7C846046C34d8a9FE97e4 ](https://explorer.hemi.xyz/address/0x40F2896C551194e364F7C846046C34d8a9FE97e4)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                           | Address                                                                                                                         | Source Code                                                                                                                   |\n| :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- |\n| Morpho                             | [ 0x68e37dE8d93d3496ae143F2E900490f6280C57cD ](https://hyperevmscan.io/address/0x68e37dE8d93d3496ae143F2E900490f6280C57cD#code)  | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                               |\n| 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) |\n| Public Allocator                   | [ 0x517505be22D9068687334e69ae7a02fC77edf4Fc ](https://hyperevmscan.io/address/0x517505be22D9068687334e69ae7a02fC77edf4Fc#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                                |\n| PreLiquidation Factory             | [ 0x1b6782Ac7A859503cE953FBf4736311CC335B8f0 ](https://hyperevmscan.io/address/0x1b6782Ac7A859503cE953FBf4736311CC335B8f0#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src)            |\n\n| Contract                         | Address                                                                                                                            | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x857f3EefE8cbda3Bc49367C996cd664A880d3042 ](https://explorer.inkonchain.com/address/0x857f3EefE8cbda3Bc49367C996cd664A880d3042)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x85416891752a6B81106c1C2999AE1AF5d8Cd3357 ](https://explorer.inkonchain.com/address/0x85416891752a6B81106c1C2999AE1AF5d8Cd3357)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x30607fEa77168d2c0401B6f60F0B40E32F9339E3 ](https://explorer.inkonchain.com/address/0x30607fEa77168d2c0401B6f60F0B40E32F9339E3)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                        | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xD50F2DffFd62f94Ee4AEd9ca05C61d0753268aBc ](https://katanascan.com/address/0xD50F2DffFd62f94Ee4AEd9ca05C61d0753268aBc#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x39EB6Da5e88194C82B13491Df2e8B3E213eD2412 ](https://katanascan.com/address/0x39EB6Da5e88194C82B13491Df2e8B3E213eD2412#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x678EB53A3bB79111263f47B84989d16D81c36D85 ](https://katanascan.com/address/0x678EB53A3bB79111263f47B84989d16D81c36D85#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                                                                                    | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x6B0D716aC0A45536172308e08fC2C40387262c9F ](https://lineascan.build/address/0x6B0D716aC0A45536172308e08fC2C40387262c9F#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x2d4cf00e18D48fD030d9b1E2FAAE6e0384C7610B ](https://lineascan.build/address/0x2d4cf00e18D48fD030d9b1E2FAAE6e0384C7610B#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x05a0Ff4E564ED1ba6B42247E19edFf83545C3C40 ](https://lineascan.build/address/0x05a0Ff4E564ED1ba6B42247E19edFf83545C3C40#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                           | Address                                                                                                                                     | Source Code                                                                                                                   |\n| :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- |\n| 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)                                               |\n| 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)                                       |\n| 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)                               |\n| 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) |\n| Public Allocator                   | [ 0xb1E5B1De2a54ab55C412B5ee1E38e46799588103 ](https://blockscout.lisk.com/address/0xb1E5B1De2a54ab55C412B5ee1E38e46799588103?tab=contract)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                                |\n| PreLiquidation Factory             | [ 0xF2c325F26691b6556e6f66451bb38bDa37FEbaa7 ](https://blockscout.lisk.com/address/0xF2c325F26691b6556e6f66451bb38bDa37FEbaa7?tab=contract)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src)            |\n\n| Contract                         | Address                                                                                                                          | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xd85cE6BD68487E0AaFb0858FDE1Cd18c76840564 ](https://explorer.mode.network/address/0xd85cE6BD68487E0AaFb0858FDE1Cd18c76840564)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0xEE868Bf3359DA30c10ea472EAEBFC0a06E8F0120 ](https://explorer.mode.network/address/0xEE868Bf3359DA30c10ea472EAEBFC0a06E8F0120)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x249E4808264c545861e43728186a731dE7c7D745 ](https://explorer.mode.network/address/0x249E4808264c545861e43728186a731dE7c7D745)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                                                                                | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [0xD5D960E8C380B724a48AC59E2DfF1b2CB4a1eAee](https://monadscan.com/address/0xd5d960e8c380b724a48ac59e2dff1b2cb4a1eaee#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [0xfd70575B732F9482F4197FE1075492e114E97302](https://monadscan.com/address/0xfd70575B732F9482F4197FE1075492e114E97302#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [0xB5b3e541abD19799E0c65905a5a42BD37d6c94c0](https://monadscan.com/address/0xB5b3e541abD19799E0c65905a5a42BD37d6c94c0#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                            | Source Code                                                                                                        |\n| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xce95AfbB8EA029495c66020883F87aaE8864AF92 ](https://optimistic.etherscan.io/address/0xce95AfbB8EA029495c66020883F87aaE8864AF92)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x0d68a97324E602E02799CD83B42D337207B40658 ](https://optimistic.etherscan.io/address/0x0d68a97324E602E02799CD83B42D337207B40658)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x3d05C01EE8e97361b9E19D172128255eaE5F98B9 ](https://optimistic.etherscan.io/address/0x3d05C01EE8e97361b9E19D172128255eaE5F98B9)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                           | Address                                                                                                                                                                                                                | Source Code                                                                                                                   |\n| :--------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- |\n| 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)                                               |\n| 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)                                       |\n| 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)                               |\n| 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) |\n| Public Allocator                   | [ 0xb41Aa3E41131947f4cd070617C582c1f9604ED11 ](https://plasmascan.to/address/0xb41Aa3E41131947f4cd070617C582c1f9604ED11/contract/9745/code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                                |\n| PreLiquidation Factory             | [ 0xA15Ec8609646A62b97522FC2568063145d081B91 ](https://plasmascan.to/address/0xA15Ec8609646A62b97522FC2568063145d081B91/contract/9745/code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src)            |\n\n| Contract                           | Address                                                                                                                                                                                                               | Source Code                                                                                                                   |\n| :--------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- |\n| 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)                                               |\n| 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)                                       |\n| 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)                               |\n| 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) |\n| Public Allocator                   | [ 0x58485338D93F4e3b4Bf2Af1C9f9C0aDF087AEf1C ](https://explorer.plume.org/address/0x58485338D93F4e3b4Bf2Af1C9f9C0aDF087AEf1C?tab=contract)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                                |\n| PreLiquidation Factory             | [ 0xF184156Cf6Ad4D3dA7F6449D40755A0f9de97ef3 ](https://explorer.plume.org/address/0xF184156Cf6Ad4D3dA7F6449D40755A0f9de97ef3?tab=contract)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src)            |\n\n| Contract                         | Address                                                                                                                    | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x1bF0c2541F820E775182832f06c0B7Fc27A25f67 ](https://polygonscan.com/address/0x1bF0c2541F820E775182832f06c0B7Fc27A25f67)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0xe675A2161D4a6E2de2eeD70ac98EEBf257FBF0B0 ](https://polygonscan.com/address/0xe675A2161D4a6E2de2eeD70ac98EEBf257FBF0B0)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0xa9c87daB340631C34BB738625C70499e29ddDC98 ](https://polygonscan.com/address/0xa9c87daB340631C34BB738625C70499e29ddDC98)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| Public Allocator                 | [ 0xfac15aff53ADd2ff80C2962127C434E8615Df0d3 ](https://polygonscan.com/address/0xfac15aff53ADd2ff80C2962127C434E8615Df0d3)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0xeDadDe37D76c72b98725614d0b41C20Fe612d304 ](https://polygonscan.com/address/0xeDadDe37D76c72b98725614d0b41C20Fe612d304)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                   | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x2d012EdbAdc37eDc2BC62791B666f9193FDF5a55 ](https://scrollscan.com/address/0x2d012EdbAdc37eDc2BC62791B666f9193FDF5a55)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0xa5EA7500A27C0079961D93366A6e93aafF18CB90 ](https://scrollscan.com/address/0xa5EA7500A27C0079961D93366A6e93aafF18CB90)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0x56b65742ade55015e6480959808229Ad6dbc9295 ](https://scrollscan.com/address/0x56b65742ade55015e6480959808229Ad6dbc9295)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| Public Allocator                 | [ 0x8a7f671E45E51dE245649Cf916cA0256FB8a9927 ](https://scrollscan.com/address/0x8a7f671E45E51dE245649Cf916cA0256FB8a9927)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0xeD960178e4aDA0296786Fa79D84e8FDF7bd44B25 ](https://scrollscan.com/address/0xeD960178e4aDA0296786Fa79D84e8FDF7bd44B25)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                    | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xc9cDAc20FCeAAF616f7EB0bb6Cd2c69dcfa9094c ](https://seiscan.io/address/0xc9cDAc20FCeAAF616f7EB0bb6Cd2c69dcfa9094c#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0xD878509446bE2C601f0f032F501851001B159D6B ](https://seiscan.io/address/0xD878509446bE2C601f0f032F501851001B159D6B#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x65eD61058cEB4895B7d62437BaCEA39b04f6D27B ](https://seiscan.io/address/0x65eD61058cEB4895B7d62437BaCEA39b04f6D27B#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                           | Address                                                                                                                                        | Source Code                                                                                                                   |\n| :--------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- |\n| 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)                                               |\n| 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)                                       |\n| 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)                               |\n| 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) |\n| Public Allocator                   | [ 0x76f93A21573014Ab7d634D3204818922A234249e ](https://soneium.blockscout.com/address/0x76f93A21573014Ab7d634D3204818922A234249e?tab=contract)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                                |\n| PreLiquidation Factory             | [ 0xcBD0710425613d666C5Ffb4dE2eE73554F21c34B ](https://soneium.blockscout.com/address/0xcBD0710425613d666C5Ffb4dE2eE73554F21c34B?tab=contract)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src)            |\n\n| Contract                         | Address                                                                                                                  | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xd6c916eB7542D0Ad3f18AEd0FCBD50C582cfa95f ](https://sonicscan.org/address/0xd6c916eB7542D0Ad3f18AEd0FCBD50C582cfa95f)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0xDEfCf242226425f93d8DD0e314735C28517C473F ](https://sonicscan.org/address/0xDEfCf242226425f93d8DD0e314735C28517C473F)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0x0cE9e3512CB4df8ae7e265e62Fb9258dc14f12e8 ](https://sonicscan.org/address/0x0cE9e3512CB4df8ae7e265e62Fb9258dc14f12e8)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| Public Allocator                 | [ 0x6Cef2EDC70D87E8f1623f3096efF05d066E59B36 ](https://sonicscan.org/address/0x6Cef2EDC70D87E8f1623f3096efF05d066E59B36)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0xc72129DA4CC808e955699111b8c22B22Ca8A10b8 ](https://sonicscan.org/address/0xc72129DA4CC808e955699111b8c22B22Ca8A10b8)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                                                                                   | Source Code                                                                                                        |\n| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xa40103088A899514E3fe474cD3cc5bf811b1102e ](https://stablescan.xyz/address/0xa40103088A899514E3fe474cD3cc5bf811b1102e#code)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0xbCB063D4B6D479b209C186e462828CBACaC82DbE ](https://stablescan.xyz/address/0xbCB063D4B6D479b209C186e462828CBACaC82DbE#code)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x741A6604e974FeAF35a5FBb1416B3e01c33e5C0e ](https://stablescan.xyz/address/0x741A6604e974FeAF35a5FBb1416B3e01c33e5C0e#code)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                    | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x918B9F2E4B44E20c6423105BB6cCEB71473aD35c ](https://explorer.tac.build/address/0x918B9F2E4B44E20c6423105BB6cCEB71473aD35c?tab=contract)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x414247afcf1fE3b94C617e7E3A7adB81D8D3208F ](https://explorer.tac.build/address/0x414247afcf1fE3b94C617e7E3A7adB81D8D3208F?tab=contract)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x5851C1e423A2F93aFb821834a63cA052D19ae4Ef ](https://explorer.tac.build/address/0x5851C1e423A2F93aFb821834a63cA052D19ae4Ef?tab=contract)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                                                                           | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0x8f5ae9CddB9f68de460C77730b018Ae7E04a140A ](https://uniscan.xyz/address/0x8f5ae9CddB9f68de460C77730b018Ae7E04a140A)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0x9a6061d51743B31D2c3Be75D83781Fa423f53F0E ](https://uniscan.xyz/address/0x9a6061d51743B31D2c3Be75D83781Fa423f53F0E)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0xe9EdE3929F43a7062a007C3e8652e4ACa610Bdc0 ](https://uniscan.xyz/address/0xe9EdE3929F43a7062a007C3e8652e4ACa610Bdc0)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| Public Allocator                 | [ 0xB0c9a107fA17c779B3378210A7a593e88938C7C9 ](https://uniscan.xyz/address/0xB0c9a107fA17c779B3378210A7a593e88938C7C9)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0xb04e4D3D59Ee47Ca9BA192707AF13A7D02969911 ](https://uniscan.xyz/address/0xb04e4D3D59Ee47Ca9BA192707AF13A7D02969911)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                  | Source Code                                                                                                        |\n| :------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xE741BC7c34758b4caE05062794E8Ae24978AF432 ](https://worldscan.org/address/0xE741BC7c34758b4caE05062794E8Ae24978AF432)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| Adaptive Curve Irm               | [ 0x34E99D604751a72cF8d0CFDf87069292d82De472 ](https://worldscan.org/address/0x34E99D604751a72cF8d0CFDf87069292d82De472)  | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm/tree/v1.0.0)                                       |\n| 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)                       |\n| MetaMorpho Factory V1.1          | [ 0x4DBB3a642a2146d5413750Cca3647086D9ba5F12 ](https://worldscan.org/address/0x4DBB3a642a2146d5413750Cca3647086D9ba5F12)  | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1/tree/5a0717b2c863060ff452ca324716083fe6d09374/src) |\n| Public Allocator                 | [ 0xef9889B4e443DEd35FA0Bd060f2104Cca94e6A43 ](https://worldscan.org/address/0xef9889B4e443DEd35FA0Bd060f2104Cca94e6A43)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0xe3cE2051a24e58DBFC0eFBe4c2d9e89c5eAe4695 ](https://worldscan.org/address/0xe3cE2051a24e58DBFC0eFBe4c2d9e89c5eAe4695)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                         | Address                                                                                                                                     | Source Code                                                                                                        |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------- |\n| Morpho                           | [ 0xA902A365Fe10B4a94339B5A2Dc64F60c1486a5c8 ](https://explorer.zircuit.com/address/0xA902A365Fe10B4a94339B5A2Dc64F60c1486a5c8?activeTab=3)  | [morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                       |\n| 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) |\n| Public Allocator                 | [ 0x7ac8F86Be7D7A15d9C95c07684004574647E0Af5 ](https://explorer.zircuit.com/address/0x7ac8F86Be7D7A15d9C95c07684004574647E0Af5?activeTab=3)  | [public-allocator](https://github.com/morpho-org/public-allocator/tree/v1.0.0)                                     |\n| PreLiquidation Factory           | [ 0x09d7629E82DdD80890495672201fe5FE1f909B0b ](https://explorer.zircuit.com/address/0x09d7629E82DdD80890495672201fe5FE1f909B0b?activeTab=3)  | [pre-liquidation](https://github.com/morpho-org/pre-liquidation/tree/16978c569549a08714667beae10e96567ff11516/src) |\n\n| Contract                           | Address                                                                                                                         | Source Code                                                                                                                   |\n| :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- |\n| Morpho                             | [ 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb ](https://sepolia.basescan.org/address/0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb)  | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                               |\n| 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) |\n\n| Contract                           | Address                                                                                                                         | Source Code                                                                                                                   |\n| :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- |\n| Morpho                             | [ 0xd011EE229E7459ba1ddd22631eF7bF528d424A14 ](https://sepolia.etherscan.io/address/0xd011EE229E7459ba1ddd22631eF7bF528d424A14)  | [morpho-org/morpho-blue](https://github.com/morpho-org/morpho-blue/tree/v1.0.0)                                               |\n| 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)                                       |\n| 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)                               |\n| 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) |\n\n## Bundlers\n\n| Contract                         | Address                                                                                                                                                                                            | Source Code                                                                                                                         |\n| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- |\n| Bundler3                         | [ 0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245 ](https://etherscan.io/address/0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| EthereumGeneralAdapter1          | [ 0x4A6c312ec70E8747a587EE860a0353cd42Be0aE0 ](https://etherscan.io/address/0x4A6c312ec70E8747a587EE860a0353cd42Be0aE0)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| ERC20WrapperAdapter              | [ 0xf83D17dFE160597b19e4FdD8ea61A23e9a87F962 ](https://etherscan.io/address/0xf83D17dFE160597b19e4FdD8ea61A23e9a87F962)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| ParaswapAdapter                  | [ 0x03b5259Bd204BfD4A616E5B79b0B786d90c6C38f ](https://etherscan.io/address/0x03b5259Bd204BfD4A616E5B79b0B786d90c6C38f)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| AaveV3MigrationAdapter “Core”    | [ 0xb09e40EbE31b738fbf20289270a397118707D475 ](https://etherscan.io/address/0xb09e40EbE31b738fbf20289270a397118707D475)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| AaveV3MigrationAdapter “Prime”   | [ 0x2CC8d502a65824B4cF9A58DB03490bA024BDB806 ](https://etherscan.io/address/0x2CC8d502a65824B4cF9A58DB03490bA024BDB806)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| AaveV3MigrationAdapter “EtherFi” | [ 0x4011dc6581fA05F9B0c7A12AdCd676e2b1a59ca3 ](https://etherscan.io/address/0x4011dc6581fA05F9B0c7A12AdCd676e2b1a59ca3)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| CompoundV3MigrationAdapter       | [ 0xdBa5bdE29eA030Bfa6A608592dFcA1D02CB26773 ](https://etherscan.io/address/0xdBa5bdE29eA030Bfa6A608592dFcA1D02CB26773)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| AaveV3OptimizerMigrationAdapter  | [ 0x9e2ea2d5785598a163D569D795f286F5C55ad972 ](https://etherscan.io/address/0x9e2ea2d5785598a163D569D795f286F5C55ad972)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| AaveV2MigrationAdapter           | [ 0x40288815C399709dFC0875A384B637fFe387961B ](https://etherscan.io/address/0x40288815C399709dFC0875A384B637fFe387961B)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| CompoundV2MigrationAdapter       | [ 0x9B89c07f480Df1945279031b5fC6fF241b8f1101 ](https://etherscan.io/address/0x9B89c07f480Df1945279031b5fC6fF241b8f1101)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3)                         |\n| EthereumBundlerV2                | [ 0x4095F064B8d3c3548A3bebfd0Bbfd04750E30077 ](https://etherscan.io/address/0x4095F064B8d3c3548A3bebfd0Bbfd04750E30077)  | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/97ecc8b05b6a5ea8693668c24b946347d2847e4c) |\n| EthereumBundler                  | [ 0xa7995f71aa11525DB02Fc2473c37Dee5dbf55107 ](https://etherscan.io/address/0xa7995f71aa11525DB02Fc2473c37Dee5dbf55107)  | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) |\n| AaveV2MigrationBundler           | [ 0xb3dCc75DB379925edFd3007511A8CE0cB4aa8e76 ](https://etherscan.io/address/0xb3dCc75DB379925edFd3007511A8CE0cB4aa8e76)  | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) |\n| AaveV3MigrationBundler           | [ 0x98ccB155E86bb478d514a827d16f58c6912f9BDC ](https://etherscan.io/address/0x98ccB155E86bb478d514a827d16f58c6912f9BDC)  | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) |\n| AaveV3OptimizerMigrationBundler  | [ 0x16F38d2E764E7BeBF625a8E995b34968226D2F9c ](https://etherscan.io/address/0x16F38d2E764E7BeBF625a8E995b34968226D2F9c)  | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) |\n| CompoundV2MigrationBundler       | [ 0x26bF52a84360Ad3d01d7CDc28FC2dDC04d8c8647 ](https://etherscan.io/address/0x26bF52a84360Ad3d01d7CDc28FC2dDC04d8c8647)  | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) |\n| CompoundV3MigrationBundler       | [ 0x3a0e2E9FB9c95fBc843daF166276C90B6C479558 ](https://etherscan.io/address/0x3a0e2E9FB9c95fBc843daF166276C90B6C479558)  | [morpho-org/morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers/tree/5466a6bedc5c9afc37584c0515ddaf51fc095370) |\n\n| Contract        | Address                                                                                                                    | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xc13A3Ca3B0120EE6121d1E0ca9Da22fDD7ed28Cd ](https://abscan.org/address/0xc13A3Ca3B0120EE6121d1E0ca9Da22fDD7ed28Cd#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x3716AA06304D1bC70f553Da44904d13086A4a791 ](https://abscan.org/address/0x3716AA06304D1bC70f553Da44904d13086A4a791#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract                   | Address                                                                                                                     | Source Code                                                                                                 |\n| :------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3                   | [ 0x1FA4431bC113D308beE1d46B0e98Cb805FB48C13 ](https://arbiscan.io/address/0x1FA4431bC113D308beE1d46B0e98Cb805FB48C13#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1            | [ 0x9954aFB60BB5A222714c478ac86990F221788B88 ](https://arbiscan.io/address/0x9954aFB60BB5A222714c478ac86990F221788B88#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| ParaswapAdapter            | [ 0xAA5c30C1482c189cA0d56057D3ac4dD7Af1e4726 ](https://arbiscan.io/address/0xAA5c30C1482c189cA0d56057D3ac4dD7Af1e4726#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| AaveV3MigrationAdapter     | [ 0x1923670d4F4eB7435d865E7477d28FEAFfA40C93 ](https://arbiscan.io/address/0x1923670d4F4eB7435d865E7477d28FEAFfA40C93#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| CompoundV3MigrationAdapter | [ 0x86Ca77a4a37A9CDBe9bBf4975F6d69531B96444b ](https://arbiscan.io/address/0x86Ca77a4a37A9CDBe9bBf4975F6d69531B96444b#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract                   | Address                                                                                                                                                                                                                              | Source Code                                                                                                 |\n| :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3                   | [ 0x708e04d46D82d8f1D0A70a3Aa0a780F27fcb3F92 ](https://snowtrace.io/address/0x708e04d46D82d8f1D0A70a3Aa0a780F27fcb3F92/contract/43114/code?chainid=43114)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1            | [ 0x8BcC016Ab7334A16DCcbEE9AB3FD6E52fEb29E96 ](https://snowtrace.io/address/0x8BcC016Ab7334A16DCcbEE9AB3FD6E52fEb29E96/contract/43114/code?chainid=43114)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| ParaswapAdapter            | [ 0x0ED0478946E00ca8BCF65475E7c8dfACA4a30005 ](https://snowtrace.io/address/0x0ED0478946E00ca8BCF65475E7c8dfACA4a30005/contract/43114/code?chainid=43114)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract                     | Address                                                                                                                 | Source Code                                                                                                 |\n| :--------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3                     | [ 0x6BFd8137e702540E7A42B74178A4a49Ba43920C4 ](https://basescan.org/address/0x6BFd8137e702540E7A42B74178A4a49Ba43920C4)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1              | [ 0xb98c948CFA24072e58935BC004a8A7b376AE746A ](https://basescan.org/address/0xb98c948CFA24072e58935BC004a8A7b376AE746A)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| ERC20WrapperAdapter          | [ 0xdeEf55F0A7366cC3Baf5E04313269389Fe17E9AE ](https://basescan.org/address/0xdeEf55F0A7366cC3Baf5E04313269389Fe17E9AE)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| ParaswapAdapter              | [ 0x6abE8ABd0275E5564ed1336F0243A52C32562F71 ](https://basescan.org/address/0x6abE8ABd0275E5564ed1336F0243A52C32562F71)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| CompoundV3MigrationAdapter   | [ 0x85D4812Ef92c040d4270eD8547b6835e41FbbB70 ](https://basescan.org/address/0x85D4812Ef92c040d4270eD8547b6835e41FbbB70)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| AaveV3MigrationAdapter       | [ 0xb27Aa2a964eAd5ed661D86974b37e4fB995b36f5 ](https://basescan.org/address/0xb27Aa2a964eAd5ed661D86974b37e4fB995b36f5)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| 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)   |\n| 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)   |\n| 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)   |\n| 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)   |\n\n| Contract        | Address                                                                                                                                      | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x82b3ea7558Fc383b949fa42Db7ee3eB101447B96 ](https://www.btrscan.com/address/0x82b3ea7558fc383b949fa42db7ee3eb101447b96?tab=Contract)       | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xa87F1422Df88B5f490203D71e2f8e7244843E62F ](https://www.btrscan.com/address/0xa87f1422df88b5f490203d71e2f8e7244843e62f?tab=Contract)       | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                            | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x16D40b9DF1497468195BFAfeb2718e486E15bF91 ](https://bscscan.com/address/0x16D40b9DF1497468195BFAfeb2718e486E15bF91#code)         | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x87c93660ECe6E68C6492EabBbBdbaafA102ae3a3 ](https://bscscan.com/address/0x87c93660ECe6E68C6492EabBbBdbaafA102ae3a3#code)         | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| ParaswapAdapter | [ 0xBb12B012Fa31f7FE418236cAf625713Edc852F82 ](https://bscscan.com/address/0xBb12B012Fa31f7FE418236cAf625713Edc852F82#code)         | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                      | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x8d0d5c4c4EDf537971B689A7d406349d230b2E7A ](https://botanixscan.io/address/0x8d0d5c4c4EDf537971B689A7d406349d230b2E7A/contract/3637/code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x2Cf5D5A68D70979d97968A8894EB93706eeAe3f1 ](https://botanixscan.io/address/0x2Cf5D5A68D70979d97968A8894EB93706eeAe3f1/contract/3637/code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                           | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x88A4038BB4A14ecD7301c8Fb1f1e8732c4355D53 ](https://camp.cloud.blockscout.com/address/0x88A4038BB4A14ecD7301c8Fb1f1e8732c4355D53?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x29dcA26F9862CFb8064163ddc3401aaB4D4D05c6 ](https://camp.cloud.blockscout.com/address/0x29dcA26F9862CFb8064163ddc3401aaB4D4D05c6?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                     | Source Code                                                                                                 |\n| :-------------- | :-------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xbd142f98f847c170D51d8B23e5FEBc51FC9a67D9 ](https://celoscan.io/address/0xbd142f98f847c170D51d8B23e5FEBc51FC9a67D9#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x3E7544a07157D03a49359eE89f2fCac9a6467230 ](https://celoscan.io/address/0x3E7544a07157D03a49359eE89f2fCac9a6467230#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                                                                                                        | Source Code                                                                                                 |\n| :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xe7C7271AfE4E49C12c66a0B8A9B774ed8b1640C8 ](https://explorer.mainnet.citrea.xyz/address/0xe7C7271AfE4E49C12c66a0B8A9B774ed8b1640C8?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x722B0e321544042741B3E45F200FBEDAc20529dC ](https://explorer.mainnet.citrea.xyz/address/0x722B0e321544042741B3E45F200FBEDAc20529dC?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x086889F9bdE8349512dD77088A7114E6C1c42Af7 ](https://cornscan.io/address/0x086889F9bdE8349512dD77088A7114E6C1c42Af7)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x464a402244bCDdc0c2091D5193E8ffdb2be54Ca9 ](https://cornscan.io/address/0x464a402244bCDdc0c2091D5193E8ffdb2be54Ca9)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                                                                                        | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xb1c59fE6A0DCE25b804F6113C441Bf4F3a4Ab6bC ](https://explorer.cronos.org/address/0xb1c59fE6A0DCE25b804F6113C441Bf4F3a4Ab6bC#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xCa470cBBc3de56FDe336466f2107cC969174d513 ](https://explorer.cronos.org/address/0xCa470cBBc3de56FDe336466f2107cC969174d513#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                        | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x69dc8086191437b55775b79C730BB3876397e7D1 ](https://explorer.etherlink.com/address/0x69dc8086191437b55775b79C730BB3876397e7D1?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xEabdAC78A7f0a9B3dF0e23D69A5a5fF7f580a910 ](https://explorer.etherlink.com/address/0xEabdAC78A7f0a9B3dF0e23D69A5a5fF7f580a910?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                 | Source Code                                                                                                 |\n| :-------------- | :---------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xA7a414823Ef0F8CFb2c4f67f2F445DA940641d91 ](https://fraxscan.com/address/0xA7a414823Ef0F8CFb2c4f67f2F445DA940641d91)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x228dDF333DDf6D1895dA1dE8a846EDD27F1284eD ](https://fraxscan.com/address/0x228dDF333DDf6D1895dA1dE8a846EDD27F1284eD)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                       | Source Code                                                                                                 |\n| :-------------- | :---------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x2AC3ea771547926D4714078e807eFbeF70D0997f ](https://gnosisscan.io/address/0x2AC3ea771547926D4714078e807eFbeF70D0997f#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x832625F5C0aAD4bc14d39291156D37898a40973b ](https://gnosisscan.io/address/0x832625F5C0aAD4bc14d39291156D37898a40973b#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                      | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x8eDa6E01a20E3Cd90B3B2AF6F790cB8FADEf3Ea8 ](https://explorer.hemi.xyz/address/0x8eDa6E01a20E3Cd90B3B2AF6F790cB8FADEf3Ea8)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x9623090C3943ad63F7d794378273610Dd0deeFD4 ](https://explorer.hemi.xyz/address/0x9623090C3943ad63F7d794378273610Dd0deeFD4)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                         | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xa3F50477AfA601C771874260A3B34B40e244Fa0e ](https://hyperevmscan.io/address/0xa3F50477AfA601C771874260A3B34B40e244Fa0e#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xD7F48aDE56613E8605863832B7B8A1985B934aE4 ](https://hyperevmscan.io/address/0xD7F48aDE56613E8605863832B7B8A1985B934aE4#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                            | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x7db0F1E2bf1f47ec82220090F388d75D8B9BB6BC ](https://explorer.inkonchain.com/address/0x7db0F1E2bf1f47ec82220090F388d75D8B9BB6BC)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xB8B2aDdCDe1cdC94AaE18a0F8A19df03D8683610 ](https://explorer.inkonchain.com/address/0xB8B2aDdCDe1cdC94AaE18a0F8A19df03D8683610)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                        | Source Code                                                                                                 |\n| :-------------- | :----------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xA8C5e23C9C0DF2b6fF716486c6bBEBB6661548C8 ](https://katanascan.com/address/0xA8C5e23C9C0DF2b6fF716486c6bBEBB6661548C8#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x916Aa175C36E845db45fF6DDB886AE437d403B61 ](https://katanascan.com/address/0x916Aa175C36E845db45fF6DDB886AE437d403B61#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                                                                                    | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x1Ee8Ec299E8014760D50A4E3CfC3b44Cc2242625 ](https://lineascan.build/address/0x1Ee8Ec299E8014760D50A4E3CfC3b44Cc2242625#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x454dAb6ce9891245696b239b4845a1cDC268255d ](https://lineascan.build/address/0x454dAb6ce9891245696b239b4845a1cDC268255d#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                     | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xD96E5e02580C4EAfE15B5537b25eE3dEe5861e00 ](https://blockscout.lisk.com/address/0xD96E5e02580C4EAfE15B5537b25eE3dEe5861e00?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x76cFE4BF840C7b461772fE7CDE399f58c4173584 ](https://blockscout.lisk.com/address/0x76cFE4BF840C7b461772fE7CDE399f58c4173584?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                          | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xFEA0edFa081C8D5960Ec9Bf6684981dB1834305d ](https://explorer.mode.network/address/0xFEA0edFa081C8D5960Ec9Bf6684981dB1834305d)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xF53925b95Cc409447066cd5c1A7756084b2Ee0a4 ](https://explorer.mode.network/address/0xF53925b95Cc409447066cd5c1A7756084b2Ee0a4)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                                                                                | Source Code                                                                                                 |\n| :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [0x82b684483e844422FD339df0b67b3B111F02c66E](https://monadscan.com/address/0x82b684483e844422FD339df0b67b3B111F02c66E#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [0x725AB8CAd931BCb80Fdbf10955a806765cCe00e5](https://monadscan.com/address/0x725AB8CAd931BCb80Fdbf10955a806765cCe00e5#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                            | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xFBCd3C258feB131D8E038F2A3a670A7bE0507C05 ](https://optimistic.etherscan.io/address/0xFBCd3C258feB131D8E038F2A3a670A7bE0507C05)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x79481C87f24A3C4332442A2E9faaf675e5F141f0 ](https://optimistic.etherscan.io/address/0x79481C87f24A3C4332442A2E9faaf675e5F141f0)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| ParaswapAdapter | [ 0x31F539f4Ed14fA1fd18781e93f6739249692aDC5 ](https://optimistic.etherscan.io/address/0x31F539f4Ed14fA1fd18781e93f6739249692aDC5)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                                                                                                | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xeC6f72cF30fb5d3D0f9Bea8509B61902Cf3B1E45 ](https://plasmascan.to/address/0xeC6f72cF30fb5d3D0f9Bea8509B61902Cf3B1E45/contract/9745/code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x6A7389f9D4fD199254479d6735aAd7aa5D4Db0cE ](https://plasmascan.to/address/0x6A7389f9D4fD199254479d6735aAd7aa5D4Db0cE/contract/9745/code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                                                                                               | Source Code                                                                                                 |\n| :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x5437C8788f4CFbaA55be6FBf30379bc7dd7f69C3 ](https://explorer.plume.org/address/0x5437C8788f4CFbaA55be6FBf30379bc7dd7f69C3?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x65ff368930Cb7eB4CA5C5eBC58bb69E6Ed198BA5 ](https://explorer.plume.org/address/0x65ff368930Cb7eB4CA5C5eBC58bb69E6Ed198BA5?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                    | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x2d9C3A9E67c966C711208cc78b34fB9E9f8db589 ](https://polygonscan.com/address/0x2d9C3A9E67c966C711208cc78b34fB9E9f8db589)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xB261B51938A9767406ef83bbFbaAFE16691b7047 ](https://polygonscan.com/address/0xB261B51938A9767406ef83bbFbaAFE16691b7047)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| ParaswapAdapter | [ 0x5F2617F12D1fDd1e43e72Cb80C92dFcE8124Db8d ](https://polygonscan.com/address/0x5F2617F12D1fDd1e43e72Cb80C92dFcE8124Db8d)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                   | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x60F9159d4dCd724e743212416FD57d8aC0B60768 ](https://scrollscan.com/address/0x60F9159d4dCd724e743212416FD57d8aC0B60768)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xD2780fae0869cDc06EE202152304A39653361525 ](https://scrollscan.com/address/0xD2780fae0869cDc06EE202152304A39653361525)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                    | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xF9457356F18A3349Bb317Ac144c3Bcc62e5761aD ](https://seiscan.io/address/0xF9457356F18A3349Bb317Ac144c3Bcc62e5761aD#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x02e0e71e145f254820B9D89c9E6068f08256F601 ](https://seiscan.io/address/0x02e0e71e145f254820B9D89c9E6068f08256F601#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                        | Source Code                                                                                                 |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x461378B79d400c963F48F57b3a99416bc3C5c6a6 ](https://soneium.blockscout.com/address/0x461378B79d400c963F48F57b3a99416bc3C5c6a6?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0xA47EeDE3Aac741B830E394B2e291f6774BD8bb48 ](https://soneium.blockscout.com/address/0xA47EeDE3Aac741B830E394B2e291f6774BD8bb48?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                  | Source Code                                                                                                 |\n| :-------------- | :----------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xB06F1Ad8c908b958E596c42973f67F2f1d9a9afF ](https://sonicscan.org/address/0xB06F1Ad8c908b958E596c42973f67F2f1d9a9afF)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x31D5aee8D75EEab548cfA0d11C4f9843a5201eaf ](https://sonicscan.org/address/0x31D5aee8D75EEab548cfA0d11C4f9843a5201eaf)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                                                                                   | Source Code                                                                                                 |\n| :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0xA0bb114F927dF03d9a1a639b9c71F71B0FaFDf1B ](https://stablescan.xyz/address/0xA0bb114F927dF03d9a1a639b9c71F71B0FaFDf1B#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x59b1F4376a81e39c466A0A218447E4D36f39A96b ](https://stablescan.xyz/address/0x59b1F4376a81e39c466A0A218447E4D36f39A96b#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                    | Source Code                                                                                                 |\n| :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x84b189823D0f84c36728Bb3335dD8C833564e72f ](https://explorer.tac.build/address/0x84b189823D0f84c36728Bb3335dD8C833564e72f?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x6D94E7dCA6d8FAE2CF954633C2Cf9c286258E0af ](https://explorer.tac.build/address/0x6D94E7dCA6d8FAE2CF954633C2Cf9c286258E0af?tab=contract)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract                   | Address                                                                                                                     | Source Code                                                                                                 |\n| :------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3                   | [ 0x7DD85759182495AF7F6757DA75036d24A9B58bc3 ](https://uniscan.xyz/address/0x7dd85759182495af7f6757da75036d24a9b58bc3#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1            | [ 0xC11329d19C2275c9E759867e879ECFcEeD7e30A0 ](https://uniscan.xyz/address/0xC11329d19C2275c9E759867e879ECFcEeD7e30A0#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| ParaswapAdapter            | [ 0xAa870Da2a9F611A3A53d0D2AEe5664B3700a59c9 ](https://uniscan.xyz/address/0xAa870Da2a9F611A3A53d0D2AEe5664B3700a59c9#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| CompoundV3MigrationAdapter | [ 0x617f8d7885CCE689115Af04576F7cB6F2534fA9a ](https://uniscan.xyz/address/0x617f8d7885CCE689115Af04576F7cB6F2534fA9a#code)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                  | Source Code                                                                                                 |\n| :-------------- | :----------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x3D07BF2FFb23248034bF704F3a4786F1ffE2a448 ](https://worldscan.org/address/0x3D07BF2FFb23248034bF704F3a4786F1ffE2a448)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x30fa9A3cF56931ACEea42E28D35519a97D90aA67 ](https://worldscan.org/address/0x30fa9A3cF56931ACEea42E28D35519a97D90aA67)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n| Contract        | Address                                                                                                                                     | Source Code                                                                                                 |\n| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- |\n| Bundler3        | [ 0x04C17BA8BAe185e655086e7f35357F7c3C70Dc53 ](https://explorer.zircuit.com/address/0x04C17BA8BAe185e655086e7f35357F7c3C70Dc53?activeTab=3)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n| GeneralAdapter1 | [ 0x2d09A9A5d41863314571E3c902D1b9DDfe6cAf9e ](https://explorer.zircuit.com/address/0x2d09A9A5d41863314571E3c902D1b9DDfe6cAf9e?activeTab=3)  | [morpho-org/bundler3](https://github.com/morpho-org/bundler3/tree/82e44ddebae998dc8b6e5cbd29ff69786135b1d3) |\n\n## Rewards\n\n| Contract                                                                      | Address                                                                                                                 | Source Code                                                                                                                                  |\n| :---------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |\n| 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)                  |\n| 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) |\n\n| Contract                              | Address                                                                                                                | Source Code                                                                                                                 |\n| :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                                                                      | Address                                                                                                                                                                                            | Source Code                                                                                                                                  |\n| :---------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |\n| 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)                  |\n| 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) |\n\n| Contract                              | Address                                                                                                                | Source Code                                                                                                                 |\n| :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                 | Source Code                                                                                                                 |\n| :------------------------------------ | :---------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                      | Source Code                                                                                                                 |\n| :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                            | Source Code                                                                                                                 |\n| :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                        | Source Code                                                                                                                 |\n| :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                                     | Source Code                                                                                                                 |\n| :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                          | Source Code                                                                                                                 |\n| :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                            | Source Code                                                                                                                 |\n| :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                                                                                                               | Source Code                                                                                                                 |\n| :------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                    | Source Code                                                                                                                 |\n| :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                   | Source Code                                                                                                                 |\n| :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                                        | Source Code                                                                                                                 |\n| :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                  | Source Code                                                                                                                 |\n| :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                | Source Code                                                                                                                 |\n| :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n| Contract                              | Address                                                                                                                  | Source Code                                                                                                                 |\n| :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |\n| 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) |\n\n## MORPHO Token\n\nThe MORPHO token has 18 decimals.\n\n| Contract         | Address                                                                                                                 | Source Code                                                                         |\n| :--------------- | :---------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------- |\n| MORPHO           | [ 0x58D97B57BB95320F9a05dC918Aef65434969c2B2 ](https://etherscan.io/address/0x58D97B57BB95320F9a05dC918Aef65434969c2B2)  | [morpho-org/morpho-token](https://github.com/morpho-org/morpho-token)               |\n| MorphoOFTAdapter | [ 0x50d3d6fD7518682155E3C1B65FDD50e1b35649D9 ](https://etherscan.io/address/0x50d3d6fD7518682155E3C1B65FDD50e1b35649D9)  | [morpho-org/morpho-token-l0](https://github.com/morpho-org/morpho-token-l0)         |\n| MORPHO wrapper   | [ 0x9D03bb2092270648d7480049d0E58d2FcF0E5123 ](https://etherscan.io/address/0x9d03bb2092270648d7480049d0e58d2fcf0e5123)  | [morpho-org/morpho-token](https://github.com/morpho-org/morpho-token)               |\n| Legacy MORPHO    | [ 0x9994E35Db50125E0DF82e4c2dde62496CE330999 ](https://etherscan.io/address/0x9994E35Db50125E0DF82e4c2dde62496CE330999)  | [morpho-org/legacy-morpho-token](https://github.com/morpho-org/legacy-morpho-token) |\n\n| Contract | Address                                                                                                                 | Source Code                                                           |\n| :------- | :---------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------- |\n| MORPHO   | [ 0xBAa5CC21fd487B8Fcc2F632f3F4E8D37262a0842 ](https://basescan.org/address/0xBAa5CC21fd487B8Fcc2F632f3F4E8D37262a0842)  | [morpho-org/morpho-token](https://github.com/morpho-org/morpho-token) |\n\n| Contract                   | Address                                                                                                                 | Source Code                                                                         |\n| :------------------------- | :-----------------------------------------------------------------------------------------------------------------------| :---------------------------------------------------------------------------------- |\n| MORPHO                     | [ 0x40BD670A58238e6E230c430BBb5cE6ec0d40df48 ](https://arbiscan.io/address/0x40bd670a58238e6e230c430bbb5ce6ec0d40df48)   | [morpho-org/morpho-token-l0](https://github.com/morpho-org/morpho-token-l0)         |\n| MorphoMintBurnOFTAdapter   | [ 0xFc3329363cd51adBBaa52E389bEE389981ccaAE0 ](https://arbiscan.io/address/0xFc3329363cd51adBBaa52E389bEE389981ccaAE0)   | [morpho-org/morpho-token-l0](https://github.com/morpho-org/morpho-token-l0)         |\n\n| Contract | Address                                                                                                                                           | Source Code                                                                                                                                                                  |\n| :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 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) |"
  },
  "/get-started/resources/app-ecosystem/": {
    "title": "Morpho Apps",
    "url": "https://docs.morpho.org/get-started/resources/app-ecosystem/",
    "section": "Get Started",
    "content": "This section details the critical applications developed by Morpho Association for effective vault management and ecosystem participation.\n\n## Consumer\n\n### Main App - [app.morpho.org](https://app.morpho.org/)\n\n**Purpose:** Interface for both lenders interacting with Morpho vaults and Borrowers interacting with Morpho Markets.\n\n**Key Features:**\n\n- View listed Morpho Markets & Morpho Vaults\n- Deposit, manage, and exit positions in Morpho Vaults\n- Enter, manage, and exit from borrow positions\n- Track vault performance metrics\n- Monitor position health and market statistics\n\n**Version: Production** \n\n#### If the main App is not accessible\n\nIf 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.\n\n#### Morpho Warnings\n\nMorpho 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.\n\nThe tables below explicitly explain some of the reasons why warnings may appear:\n\n##### Market V1 Warnings\n\n| Warning Type                       | Level    | Criteria / Threshold                                     | Notes                                                                                                                                                                                            |\n|------------------------------------|----------|----------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| **bad_debt_unrealized**            | 🔴 RED    | Unrealized bad debt / total supply assets > 5% (500 bps) | Detects accumulating bad debt                                                                                                                                                                    |\n| **not_whitelisted**                     | 🟡 YELLOW | Market not listed by a listed vault                      | -                                                                                                                                                                                                |\n| **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)                                     |\n| **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. |\n| **incorrect_oracle_configuration** | 🔴 RED    | Scale factor incorrect or negative exponent              | For Morpho Chainlink Oracle V1/V2                                                                                                                                                                |\n\n##### Vault V1 Warnings\n\n| Warning Type                   | Level    | Criteria / Threshold                  | Notes                                                                                                                                                        |\n|--------------------------------|----------|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| **invalid_name**               | 🔴 RED    | Contains \"morpho\" OR SQL injection    | Brand protection & security                                                                                                                                  |\n| **invalid_symbol**             | 🔴 RED    | Contains \"morpho\" OR SQL injection    | Brand protection & security                                                                                                                                  |\n| **short_timelock**             | 🔴 RED    | Timelock < 3 days                     | Governance security                                                                                                                                          |\n| **not_whitelisted**                 | 🟡 YELLOW | Vault not in listed curators database | -                                                                                                                                                            |\n| **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) |\n\n##### Vault V2 Warnings\n\n| Warning Type           | Level    | Criteria / Threshold                  | Notes                                                                                                                                                        |\n|------------------------|----------|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| **not_whitelisted**         | 🟡 YELLOW | Vault not in listed curators database | -                                                                                                                                                            |\n| **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) |\n| **timelock**           | 🔴 RED    | Functions without minimum timelock    | See timelock requirements below                                                                                                                              |\n\n##### Vault V2 Timelock Requirements\n\n| Function                    | Minimum Timelock | Purpose                                  |\n|-----------------------------|------------------|------------------------------------------|\n| `setReceiveSharesGate`      | **7 days**       | Controls who can receive vault shares    |\n| `setSendSharesGate`         | **7 days**       | Controls who can send vault shares       |\n| `setReceiveAssetsGate`      | **7 days**       | Controls deposit permissions             |\n| `setAdapterRegistry`        | **7 days**       | Updates adapter registry address         |\n| `increaseTimelock`          | **7 days**       | Increases timelock duration              |\n| `abdicate`                  | **7 days**       | Removes timelock requirement permanently |\n| `removeAdapter`             | **7 days**       | Removes approved adapter                 |\n| `addAdapter`                | **3 days**       | Adds new approved adapter                |\n| `increaseRelativeCap`       | **3 days**       | Increases relative allocation cap        |\n| `setForceDeallocatePenalty` | **3 days**       | Sets penalty for forced deallocation     |\n| `increaseAbsoluteCap`       | **3 days**       | Increases absolute allocation cap        |\n\nRefer to this [risk documentation](/learn/resources/risks/) to be sure you understand all the risks.\n\n#### Tokens checks\n\nTokens 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. \n\nHere are the checks performed:\n\n- **Contract Existence** - A valid smart contract exists at the provided address\n- **ERC-20 Compliance** - The contract implements the core ERC-20 interface (name, symbol, decimals)\n- **Non-zero total supply** - The token’s total supply is greater than 0\n- **DefiLlama Price Data** - The token has a recent price data available on DeFiLlama\n- **Logo Availability** - Token logo exists in Morpho database\n- **Not already listed** - The token is not already listed on the chain\n\n#### Policy\n\n##### Asset blocking policy\n\nThe Morpho protocol is a self-executing, permissionless, decentralized series of smart contracts that cannot be changed by anyone except the governance for given parameters.\n\nMorpho 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.\n\nAs such, there may be certain circumstances under which Morpho Association blocks access to certain markets and vaults through our the interface provided.\n\n##### Criteria for Restricting Access on Morpho Association Interfaces\n\n1. Morpho Association will block some components of the Protocol for the following reasons:\n   1. Risks to users. Morpho Association believes there are technical, fraud, or other risks that could significantly affect user safety.\n   2. Legal and regulatory requirements.\n   3. Fraud allegations.\n2. 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.\n3. 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.\n\n#### Additional disclosures\n\nInterface 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.\n\nMorpho 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.\n\n#### Slippage Considerations\n\nWhen 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.\n\n##### Types of Slippage Protection\n\n1. **Token Wrapping Operations**\n\n   - Applied to: stETH → wstETH conversions, ERC4626 deposits (including Morpho Vaults deposits)\n   - Fixed maximum slippage: 3 basis points (0.03%)\n\n2. **Market Operations**\n\n   - Formula:\n\n   ```math\n   e^{4 \\cdot r_{\\text{target}} \\cdot d} - 1\n   ```\n\n   - Where:\n     - **r_target** is the target interest rate\n     - **d** is the expected transaction duration (15 minutes for EOA, 45 minutes for Safe)\n\n3. **Vault Operations**\n\n   - Formula:\n\n   ```math\n   \\left( 1 + r_{apy} \\right)^{\\frac{d}{yearInSeconds}} - 1\n   ```\n\n   - Where:\n     - **r_apy** is the Annual Percentage Yield\n     - **d** is the expected transaction duration (15 minutes for EOA, 45 minutes for Safe)\n     - **yearInSeconds** is the number of seconds in a year\n\n##### Shares Conversion and Slippage\n\nIn 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:\n\n- **Asset-Based Operations**: Borrowing, partial repayments, Morpho Vaults deposits/partial withdrawals, supplying/withdrawing collateral\n- **Shares-Based Operations**: Maximum repayments, Morpho Vaults deposits in rehypothecation, maximum Morpho Vaults withdrawals\n\n**Note**: Slippage can significantly impact transactions combining asset-based and shares-based operations for the same token.\n\n##### Special Considerations for Morpho Vaults\n\nMorpho Vaults ERC4626-compliant tokens are treated differently depending on the context:\n- As assets when supplied as collateral\n- As shares when supplied as deposits\n\nIn rehypothecation, they are treated as shares during Morpho Vaults Deposit and as assets during Supply Collateral.\n\n#### At which level is it implemented?\n\nThese slippage calculations are automatically applied in relevant `bundlerActions` to protect users from adverse price movements during transaction processing.\n\n### Fallback App - [fallback.morpho.org](https://fallback.morpho.org/)\n\n**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.\n\n**Key Features:**\n\n- View your Morpho Markets & Morpho Vaults positions\n- Exit positions from Morpho Vaults and Morpho Markets\n\n**Version: Production**\n\n<details>\n<summary>**Deploy your own independent Fallback App**</summary>\n\n#### Why deploy your own?\n\nThe Morpho Fallback App can be self-hosted, giving you:\n- **Independence**: Access to your funds even if app.morpho.org is unavailable\n- **Censorship resistance**: No reliance on any single provider\n- **Version control**: Stay on a trusted version you've reviewed\n\nThe app is fully static (just files, no server needed) and connects directly to public blockchain nodes.\n\n-----------------|-----------------------------------|\n| DWeb (Recommended) | `https://YOUR_CID.ipfs.dweb.link` |\n| IPFS.io            | `https://ipfs.io/ipfs/YOUR_CID`   |\n| Web3.Storage       | `https://YOUR_CID.ipfs.w3s.link`  |\n\n---\n\n#### Updating Your Deployment\n\nSince IPFS content is immutable (never changes), updating means creating a new deployment:\n\n1. 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`\n2. Rebuild\n3. Upload the new `dist/` folder to Pinata (or your chosen host)\n4. Use your new CID\n\nYour old CID continues working forever, so you can stay on a known version or upgrade when ready.\n\n---\n\n#### Alternative: Use a Community Deployment\n\nIf 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**\n\n  \n\n  \n\nNote: When using third-party deployments, you trust that the deployer built from the official source without modifications.\n\n---\n\n#### Security Best Practices\n\n- **Verify the source**: Only build from the official repository ([morpho-lite-apps repository](https://github.com/morpho-org/morpho-lite-apps))\n- **Review before trusting**: Check the code before deploying, especially if you're security-conscious\n- **Use HTTPS gateways**: Always access via `https://` to prevent tampering\n- **Safe by design**: The app never asks for your private keys - it only requests transaction signatures through your wallet\n\n</details>\n\n### Data Dashboard - [data.morpho.org](https://data.morpho.org/)\n\n**Purpose:** Provides on-chain data and analytics for the Morpho ecosystem.\n\n**Version:** Production\n\n### Rewards - [campaigns.morpho.org](https://campaigns.morpho.org/)\n\n**Purpose:** Monitor reward campaigns on Morpho, track rewards linked to a specific address, and claim rewards.\n\nMerkl is an application developed by a third party allowing to interact with rewards distributed on Morpho.\nThe Morpho Association does not endorse or guarantee its functionality. Use at your own discretion.\n\n## Prime\n\n### Curator App V2 - [curator.morpho.org](https://curator.morpho.org/vaults)\n\n**Purpose:** Delivers specialized tools for Morpho Vault V2 curators to manage vault operations.\n\n**Key Features:**\n\n- Create and deploy new vaults V2\n- Curate adapter listings and parameters\n- Configure vault settings and permissions\n- Set allocation caps, strategies and timelocks\n\n**Version:** Beta deployment with ongoing feature development\n\n**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/).\n\n### Curator App V1 - [curator-v1.morpho.org](https://curator-v1.morpho.org/)\n\n**Purpose:** Delivers specialized tools for Morpho Vault V1 curators to manage vault operations.\n\n**Key Features:**\n\n- Create and deploy new vaults V1\n- Curate market listings and parameters\n- Configure vault settings and permissions\n- Set allocation caps, strategies and timelocks\n\n**Version:** Beta deployment with ongoing feature development\n\n**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/).\n\n## Other\n\n### Oracle Portal - [oracles.morpho.dev](https://oracles.morpho.dev/)\n\n**Purpose:** Aid oracle configurations to ensure price feed accuracy and security.\n\n**Key Features:**\n\n- Decode oracle configurations\n- Verify price accuracy against reference sources\n- Test oracle configurations\n- Identify configuration issues\n\n**Version:** Production\n\n**Implementation Note:** Always verify oracle data configurations before deploying to production environments. Use this tool to:\n\n1. Confirm correct asset pricing\n2. Validate operational parameters\n3. Test edge case scenarios\n\n### Liquidation App - [liquidation.morpho.org](https://liquidation.morpho.org/)\n\n**Purpose:** Provides manual liquidation capabilities for unhealthy positions.\n\n**Key Features:**\n\n- Identify liquidatable positions\n- Execute manual liquidations\n- Calculate liquidation profitability\n- Monitor position health metrics\n\n**Version:** Production and requires supplemental automation\n\n**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."
  },
  "/get-started/resources/audits/": {
    "title": "Audits - Security Reviews",
    "url": "https://docs.morpho.org/get-started/resources/audits/",
    "section": "Get Started",
    "content": "Morpho is known for its industry-leading security practices and follows a multi-faceted approach to security.\n\nMorpho 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.\n\nA whole article was dedicated to the [Morpho Security Framework](https://morpho.org/blog/morpho-blue-security-framework-building-the-most-secure-lending-protocol/).\n\nThe 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.\n\n| Auditors                                                                                 | Scope                                          | Date               | Report                                                                                                       |\n| :--------------------------------------------------------------------------------------- | :--------------------------------------------- | :----------------- | :----------------------------------------------------------------------------------------------------------- |\n| [Certora](https://www.certora.com/)                                                      | Vaults V2 - MarketV1AdapterV2                  | 2025-15-12         | [certora-report](https://github.com/morpho-org/vault-v2/tree/main/audits)                                    |\n| [Spearbit](https://spearbit.com/)                                                        | Vaults V2 - MarketV1AdapterV2                  | 2025-04-12         | [spearbit-report](https://github.com/morpho-org/vault-v2/tree/main/audits)                                   |\n| [Blackthorn](https://www.blackthorn.xyz/)                                                | Vaults V2 - MarketV1AdapterV2                  | 2025-04-12         | [blackthorn-report](https://github.com/morpho-org/vault-v2/tree/main/audits)                                 |\n| [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)                 |\n| [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)                |\n| [Spearbit](https://spearbit.com/)                                                        | Vaults V2                                      | 2025-11-08         | [spearbit-report](https://github.com/morpho-org/vault-v2/tree/main/audits)                                   |\n| [ChainSecurity](https://www.chainsecurity.com/)                                          | Vaults V2                                      | 2025-09-15         | [chainsecurity-report](https://github.com/morpho-org/vault-v2/tree/main/audits)                              |\n| [Blackthorn](https://www.blackthorn.xyz/)                                                | Vaults V2                                      | 2025-09-15         | [blackthorn-report](https://github.com/morpho-org/vault-v2/tree/main/audits)                                 |\n| [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)                              |\n| [Zellic](https://www.zellic.io/)                                                         | Vaults V2                                      | 2025-07-15         | [zellic-report](https://github.com/morpho-org/vault-v2/tree/main/audits)                                     |\n| [Spearbit](https://spearbit.com/)                                                        | Vaults V2                                      | 2025-05-19         | [spearbit-report](https://github.com/morpho-org/vault-v2/tree/main/audits)                                   |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V1 - Morpho Periphery                   | 2024-10-29         | [spearbit-report](https://github.com/morpho-org/pre-liquidation/tree/main/audits)                            |\n| [ABDK Consulting](https://abdk.consulting/)                                              | Morpho V1 - Morpho Periphery                   | 2024-11-01         | [ABDK-report](https://github.com/morpho-org/pre-liquidation/tree/main/audits)                                |\n| [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)                     |\n| [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)                      |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V1 - Public Allocator                   | 2024-03-11         | [cantina-managed-review](https://github.com/morpho-org/public-allocator/tree/main/audits)                    |\n| [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)                            |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V1                                      | 2023-10-16         | [cantina-managed-review](https://github.com/morpho-org/morpho-blue/tree/main/audits)                         |\n| [Open Zeppelin](https://www.openzeppelin.com/)                                           | Morpho V1                                      | 2023-10-13         | [open-zeppelin](https://github.com/morpho-org/morpho-blue/tree/main/audits)                                  |\n| [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)                             |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V1 - Morpho Periphery                   | 2023-11-16         | [cantina-managed-review](https://github.com/morpho-org/metamorpho/tree/main/audits)                          |\n| [Open Zeppelin](https://www.openzeppelin.com/)                                           | Morpho V1 - Morpho Periphery                   | 2023-11-16         | [open-zeppelin](https://github.com/morpho-org/metamorpho/tree/main/audits)                                   |\n| [Omniscia](https://omniscia.io/)                                                         | MORPHO Token                                   | 2022-06-15         | [omniscia-report](https://omniscia.io/morpho-specialized-token/)                                             |\n| [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)                                        |\n| [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)          |"
  },
  "/get-started/resources/contracts/": {
    "title": "Morpho Contracts",
    "url": "https://docs.morpho.org/get-started/resources/contracts/",
    "section": "Get Started",
    "content": "| **Category**                                      | **Contract**                  | **Github Repositories**                                                                      | **Specs**                                                        |\n| ------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |\n| **Morpho Core**           | Morpho Market V1              | [morpho-blue](https://github.com/morpho-org/morpho-blue)                                     | [spec](/get-started/resources/contracts/morpho/)             |\n|                                                   | Interest Rate Model           | [morpho-blue-irm](https://github.com/morpho-org/morpho-blue-irm)                             | [spec](/get-started/resources/contracts/irm/)                |\n|                                                   | Oracle                        | [morpho-blue-oracles](https://github.com/morpho-org/morpho-blue-oracles)                     | [spec](/get-started/resources/contracts/oracles/)            |\n|                                                   | Pre-Liquidation               | [pre-liquidation](https://github.com/morpho-org/pre-liquidation)                             | [spec](/get-started/resources/contracts/morpho/#liquidation) |\n| **Morpho Vaults V1**    | Vaults V1.1                   | [metamorpho-v1.1](https://github.com/morpho-org/metamorpho-v1.1)                             | [spec](/get-started/resources/contracts/morpho-vaults/)      |\n|                                                   | Vaults V1.0                   | [metamorpho](https://github.com/morpho-org/metamorpho)                                       | [spec](/get-started/resources/contracts/morpho-vaults/)      |\n| **Morpho Vaults V2** | Vaults V2                     | [vault-v2](https://github.com/morpho-org/vault-v2)                                           | [spec](/get-started/resources/contracts/morpho-vaults-v2/)   |\n|                                                   | MorphoVaultV1Adapter          | [vault-v2](https://github.com/morpho-org/vault-v2)                                           | [spec](/get-started/resources/contracts/morpho-vault-v1-adapter/)         |\n|                                                   | MorphoMarketV1AdapterV2       | [vault-v2](https://github.com/morpho-org/vault-v2)                                           | [spec](/get-started/resources/contracts/morpho-market-v1-adapter-v2/)     |\n| **Public Allocator** | Public-Allocator              | [public-allocator](https://github.com/morpho-org/public-allocator)                           | [spec](/get-started/resources/contracts/public-allocator/)   |\n| **Bundlers**                 | Bundler3                      | [bundler3](https://github.com/morpho-org/bundler3)                                           | [spec](/get-started/resources/contracts/bundlers/)           |\n|                                                   | Bundler2                      | [morpho-blue-bundlers](https://github.com/morpho-org/morpho-blue-bundlers)                   | [spec](/get-started/resources/contracts/bundlers/)           |\n| **Rewards**                   | Universal-Rewards-Distributor | [universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor) | [spec](/get-started/resources/contracts/rewards/)            |"
  },
  "/get-started/resources/contracts/bundlers/": {
    "title": "Bundler3 & Bundler2",
    "url": "https://docs.morpho.org/get-started/resources/contracts/bundlers/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Bundler3 & Bundler2\n\n## Code\n\n## Bundler3 Structure\n\nBundler3 is a call dispatcher that enables atomic execution of arbitrary calls\n  with enhanced features for authorization management and callback handling.\n\n  \n\n1. 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:\n\n   - **`to`**: Target address\n   - **`data`**: Calldata\n   - **`value`**: Native currency amount\n   - **`skipRevert`**: Flag to skip reverting if this particular call fails\n   - **`callbackHash`**: Specifies the hash used for controlling reentrancy callbacks\n\n2. **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).\n\n3. **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).\n\n4. **Specialized adapters** target specific integrations:\n   - [`ParaswapAdapter`](https://github.com/morpho-org/bundler3/blob/main/src/adapters/ParaswapAdapter.sol) for DEX aggregation (buy/sell/swaps)\n   - **Migration adapters** for moving user positions between protocols (Aave, Compound, Morpho, etc.)\n\n---\n\n## Bundler2 Structure\n\nEach 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.\n\n  \n\n1. 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.\n\n2. 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)).\n\n3. 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).\n\n4. 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)).\n\n# Permit 2\n\nIn 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.\n\nThe 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.\n\nDiscover the full potential of Permit2 and how it revolutionizes token approvals in the [integration guide](https://blog.uniswap.org/permit2-integration-guide)."
  },
  "/get-started/resources/contracts/irm/": {
    "title": "Interest Rate Models",
    "url": "https://docs.morpho.org/get-started/resources/contracts/irm/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Interest Rate Models\n\n## Code\n\nInterest rate models are defined as a list of governance-approved contracts.\nEach contract implements the [IRM interface](https://github.com/morpho-org/morpho-blue/blob/main/src/interfaces/IIrm.sol) exposed below.\n\n## Function\n\n### borrowRate\n\n```solidity\nfunction borrowRate(MarketParams memory marketParams, Market memory market) external returns (uint256);\n```\n\nReturns the borrow rate of the market `marketParams`.\n\n#### Parameters:\n\n| Name           | Type                                                                      | Description                            |\n| :------------- | :------------------------------------------------------------------------ | :------------------------------------- |\n| `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The MarketParams struct of the market. |\n| `market`       | [Market](/get-started/resources/contracts/morpho/#market-struct)             | The Market struct of the market.       |\n\n#### Return values:\n\n| Name         | Type    | Description                    |\n| :----------- | :------ | :----------------------------- |\n| `borrowRate` | uint256 | The borrow rate of the market. |\n\n## View Function\n\n### borrowRateView:\n\n```solidity\nfunction borrowRateView(MarketParams memory marketParams, Market memory market) external view returns (uint256);\n```\n\nReturns the borrow rate of the market `marketParams` without modifying any storage.\n\n#### Parameters:\n\n| Name           | Type                                                                      | Description                            |\n| :------------- | :------------------------------------------------------------------------ | :------------------------------------- |\n| `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The MarketParams struct of the market. |\n| `market`       | [Market](/get-started/resources/contracts/morpho/#market-struct)             | The Market struct of the market.       |\n\n#### Return values:\n\n| Name         | Type    | Description                    |\n| :----------- | :------ | :----------------------------- |\n| `borrowRate` | uint256 | The borrow rate of the market. |\n\nMake sure the input parameters correspond to the last time the market was\n  updated (check `lastUpdate`) and apply the returned borrow rate as is applied\n  in Morpho over the period between the market's `lastUpdate` and the query's\n  block timestamp.\n\n## Calculations\n\nThe 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.\n\n### Borrow APY\n\nThe Borrow APY is calculated using the following formula:\n\n```math\n\\text{borrowAPY} = \\left(e^{\\left(\\text{borrowRate} \\times \\text{secondsPerYear}\\right)} - 1\\right)\n```\n\nWhere:\n\n- `borrowRate` is the borrow rate per second, as determined by the Interest Rate Model (IRM),\n- `secondsPerYear` represents the total number of seconds in a year (31,536,000).\n\nTo obtain the `borrowRate` value, a simple call can be made to the `borrowRateView` or `borrowRate` functions defined in the upper sections.\n\n### Supply APY\n\nThe Supply APY is calculated considering the utilization and the fee. The formula is:\n\nThe `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).\n\n```math\n\\text{supplyAPY} = \\text{borrowAPY} \\times \\text{utilization} \\times (1 - \\text{fee})\n```\n\nWhere:\n\n- `fee` is the fee of the market, to be activated by the governance, on a per-market basis,\n- `utilization` is calculated as:\n\n```math\n\\text{utilization} = \\frac{\\text{totalBorrowAssets}}{\\text{totalSupplyAssets}}\n```\n\n# AdaptiveCurveIRM\n\nHere is a video that shows how the Adaptive Curve IRM works:\n\n## Overview\n\nIn 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.\n\nThe 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:\n\n- 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.\n- 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.\n\nThe 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.\n\nTo achieve this, the AdaptiveCurveIRM adjusts user incentives through the action of two different mechanisms:\n\n- The Curve Mechanism\n- The Adaptive Mechanism\n\n## The Curve Mechanism\n\nThis mechanism is similar to the interest rate curve used in traditional lending pools.\n\nThe curve is characterized by two parameters:\n\n```math\n  r_{90\\%}\n```\n\nwhich is the target rate at utilization target\n\n```math\nu\\_{target}=0.9\n```\n\nand\n\n```math\nc=4\n```\n\na fixed parameter that determines the steepness of the curve above and below the utilization target.\n\n  \n\nAt each interaction, utilization will change, resulting in a discontinuous change in the rate determined by the curve.\n\nFor example:\n\n- if utilization is 90%, the rate is\n\n```math\n  r\\_{90\\%}\n```\n\n- if utilization is 100%, the rate is\n\n```math\n4*r\\_{90\\%}\n```\n\n(APR)\n\nThe aim of the Curve Mechanism is to manage short-term utilization changes.\n\n## The Adaptive Mechanism\n\nThis mechanism continuously shifts the curve to adjust to market conditions over time.\n\nNote 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.\n\nThe shifting of the curve is done by continuously changing the value of\n\n```math\nr\\_{90\\%}\n\n```\n\nover time:\n\n- When the utilization is above the target utilization,\n\n```math\n  r\\_{90\\%}\n```\n\ncontinuously shifts upwards.\n\n- When the utilization is below the target utilization,\n\n```math\nr_{90\\%}\n```\n\ncontinuously shifts downwards.\n\n{\" \"}\n\n  \n\nThe speed at which `math\nr_{90\\%}\n` moves is updated at each interaction: the farther we are from the target, the faster\n\n```math\nr\\_{90\\%}\n\n```\n\nhence the curve, shifts.\n\nFor example, if the utilization remains at 100% for 5 days,\n\n```math\nr\\_{90\\%}\n```\n\nwill progressively double.\nThis is the maximum speed at which\n\n```math\nr\\_{90\\%}\n```\n\ncan move.\n\nThe values of some\n  [constants](https://github.com/morpho-org/morpho-blue-irm/blob/main/src/adaptive-curve-irm/libraries/ConstantsLib.sol)\n  are hardcoded into the code deployed on Ethereum, such as\n  `TARGET_UTILIZATION`, `INITIAL_RATE_AT_TARGET`, etc.\n\n## Formal description\n\nWe define:\n\n- Utilzation (\n  ```math\n  u\n  ```\n\n)\n\n```math\nu(t)\n```\n\nis the ratio of total borrow over total supply at time\n\n```math\nt\n```\n\nThe utilization target is constant:\n\n```math\nu\\_{target}=0.9\n\n```\n\n- Error (\n  ```math\n  e\n  ```\n\n):\n\n```math\n\\forall t,\n```\n\n```math\ne(u)=\\begin{cases}\n\\frac{u(t)-u_{target}}{1-u_{target}}&\\text{if } u(t)>u_{target} \n\\frac{u(t)-u_{target}}{u_{target}}&\\text{if } u(t)\\le u_{target}\n\\end{cases}\n```\n\nIt 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\nu_{target}\n` and `math\nu=1\n` equals to the distance between `math\nu_{target}\n` and\n\n```math\nu=0\n\n```\n\n  \n\n- Curve:\n\n```math\n\\text{curve}(u)=\n\\begin{cases}\n(1-\\frac{1}{k_d})*e(u)+1&\\text{if } u\\le u_{target} \n(k_d-1)*e(u)+1&\\text{if } u>u_{target}\n\\end{cases}\n```\n\nwith\n\n```math\nk_d=4\n\n```\n\n- History of interactions (\n\n  ```math\n  \\mathcal{H}\n  ```\n\n):\n\nNoting\n\n```math\nt_i\n```\n\nthe time at which the\n\n```math\ni^{th}\n```\n\ninteraction occurred,\n\n```math\n\\forall t,\n```\n\n```math\n\\mathcal{H}(t)=\\{0\\}+\\{t_i\\}_{t_i< t}\n```\n\n- Last interaction (\n\n```math\n  \\text{last}\n```\n\n```math\n\\forall t,\n```\n\n```math\n\\text{last}(t) = \\max(\\mathcal{H}(t))\n```\n\n- Speed factor (\n\n```math\n  \\text{speed}\n\n```\n\n):\n\n```math\n\\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\n```\n\n- Rate at target (\n\n```math\n  r_T\n\n```\n\n```math\nr_T(0)\n```\n\nis set to an arbitrary value\n\nThen,\n\n```math\n\\forall t >0, r_T(t)=r_{T}(\\text{last}(t))*\\text{speed}(t)\n```\n\nAt any time `math\nt\n`, the borrow rate\n\n```math\nr\n```\n\nis given by the formula:\n\n```math\nr(t) = r_{T}(t)* \\text{curve}(u(t))\n```\n\n## Implementation\n\n> [Adaptive Curve IRM Github repository](https://github.com/morpho-org/morpho-blue-irm)\n\nThe 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.\n\nMoreover, the implementation stores configuration variables and a market parameter updated at each `borrowRate` call for this market.\n\n## Variables\n\n### Constants\n\nThe values of the following constants are hardcoded into the [code deployed on Ethereum](https://etherscan.io/address/0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC#code#F8#L27)\n\n- `CURVE_STEEPNESS`: Curve steepness (scaled by WAD), value = `4`.\n- `ADJUSTMENT_SPEED`: Adjustment speed per second (scaled by WAD), value = `50/nb of seconds per year`.\n- `TARGET_UTILIZATION`: Target utilization (scaled by WAD), value = `90%`.\n- `INITIAL_RATE_AT_TARGET`: Initial rate at target per second (scaled by WAD), value = `4%/nb of seconds per year`.\n- `MIN_RATE_AT_TARGET`: Minimum rate at target per second (scaled by WAD), value = `0.1%/nb of seconds per year`.\n- `MAX_RATE_AT_TARGET`: Maximum rate at target per second (scaled by WAD), value = `200%/nb of seconds per year`.\n\n## Immutables\n\n- `MORPHO`: Address of Morpho.\n\n## Mappings\n\n### Rate at target\n\n```solidity\nmapping(Id => uint256) public rateAtTarget;\n```\n\nRate at target utilization for each market. Tells the height of the curve.\n\n## Events\n\n### BorrowRateUpdate\n\n```solidity\nevent BorrowRateUpdate(Id indexed id, uint256 avgBorrowRate, uint256 rateAtTarget);\n```\n\nEmitted when the borrow rate is updated (called by Morpho).\n\n#### Parameters:\n\n| Name            | Type    | Description                              |\n| :-------------- | :------ | :--------------------------------------- |\n| `id`            | Id      | The id of the market.                    |\n| `avgBorrowRate` | uint256 | The average borrow rate of the market.   |\n| `rateAtTarget`  | uint256 | The stored rate at target of the market. |"
  },
  "/get-started/resources/contracts/morpho-market-v1-adapter-v2/": {
    "title": "MorphoMarketV1AdapterV2",
    "url": "https://docs.morpho.org/get-started/resources/contracts/morpho-market-v1-adapter-v2/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# MorphoMarketV1AdapterV2\n\n## Code\n\n## Introduction\n\n`MorphoMarketV1AdapterV2` is an adapter that connects a Morpho Vault V2 to Morpho Market V1. It manages supply positions across multiple markets and implements its own timelock system using the same submit/execute pattern as Morpho Vault V2, with its own distinct set of timelocked functions.\n\nThis adapter must be used with Morpho Market V1 that are protected against inflation attacks with an initial supply. See [OpenZeppelin ERC4626 inflation attack](https://docs.openzeppelin.com/contracts/5.x/erc4626#inflation-attack) and Inflation Front-Running Attack Protection section [here](/curate/concepts/security-considerations/#inflation-front-running-attack-protection).\n\nThis adapter can only be used for markets with the AdaptiveCurveIRM.\n\nMarkets are removed from `marketIds` when the allocation is zero, but this does not mean that the adapter has zero shares on that market.\n\n-------------- | :----------- |\n| `increaseTimelock` | `0x47966291` |\n| `decreaseTimelock` | `0x5c1a1a4f` |\n| `abdicate`         | `0xb2e32848` |\n| `setSkimRecipient` | `0x2b30997b` |\n| `burnShares`       | `0x3b2de5ac` |\n\n## Immutables\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `factory` | address | The factory contract that deployed this adapter. |\n| `parentVault` | address | The Morpho Vault V2 that this adapter belongs to. |\n| `asset` | address | The underlying asset of the parent vault (must match the loan token of all managed markets). |\n| `morpho` | address | The Morpho (Morpho Blue) contract address. |\n| `adapterId` | bytes32 | Unique identifier for this adapter instance, computed as `keccak256(abi.encode(\"this\", address(this)))`. |\n| `adaptiveCurveIrm` | address | The AdaptiveCurveIRM address. All managed markets must use this IRM. |\n\n## Timelock System\n\nThe timelock system works identically to the one in Morpho Vault V2. The curator must `submit` a timelocked action, wait for the timelock to expire, then anyone can call the function directly.\n\n---\n\n### `submit`\n\n```solidity\nfunction submit(bytes calldata data) external\n```\nSubmits a timelocked action for later execution.\n\n**Callable by:** `Curator`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | The ABI-encoded function call data. |\n\n---\n\n### `revoke`\n\n```solidity\nfunction revoke(bytes calldata data) external\n```\nCancels a pending timelocked action.\n\n**Callable by:** `Curator`, `Sentinel`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | The ABI-encoded function call data to revoke. |\n\n---\n\n### `increaseTimelock`\n\n```solidity\nfunction increaseTimelock(bytes4 selector, uint256 newDuration) external\n```\nIncreases the timelock duration for a specific function selector.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x47966291`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector whose timelock to increase. |\n| `newDuration` | uint256 | The new timelock duration in seconds. Must be greater than or equal to the current duration. |\n\n---\n\n### `decreaseTimelock`\n\n```solidity\nfunction decreaseTimelock(bytes4 selector, uint256 newDuration) external\n```\nDecreases the timelock duration for a specific function selector. This action's own timelock equals the current timelock of the function being decreased.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x5c1a1a4f`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector whose timelock to decrease. |\n| `newDuration` | uint256 | The new timelock duration in seconds. Must be less than or equal to the current duration. |\n\n---\n\n### `abdicate`\n\n```solidity\nfunction abdicate(bytes4 selector) external\n```\nIrreversibly disables the ability to execute a specific type of action.\n\nThis action is irreversible. Existing pending operations submitted before abdicating cannot be executed.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0xb2e32848`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector to permanently abdicate. |\n\n## Curator Functions\n\n### `setSkimRecipient`\n\n```solidity\nfunction setSkimRecipient(address newSkimRecipient) external\n```\nSets the address that receives skimmed token balances (e.g., reward tokens earned by the adapter).\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x2b30997b`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newSkimRecipient` | address | The new skim recipient address. |\n\n---\n\n### `burnShares`\n\n```solidity\nfunction burnShares(bytes32 marketId) external\n```\nBurns the adapter's tracked supply shares for a market, setting `supplyShares[marketId]` to zero.\n\nBurnt shares are lost forever and cannot be recovered.\n\nWhen submitting `burnShares`, it is recommended to set the caps of the market to zero first to avoid losing more assets.\n\nAfter burning shares, call `deallocate` on the parent vault with this adapter's address, the market's data encoding, and `0` assets to sync the vault's recorded allocation.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x3b2de5ac`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `marketId` | bytes32 | The market ID whose shares to burn. |\n\n## Other Functions\n\n### `skim`\n\n```solidity\nfunction skim(address token) external\n```\nTransfers the adapter's entire balance of `token` to `skimRecipient`.\n\n**Callable by:** `skimRecipient`\n\nIf `skimRecipient` is not set (`address(0)`), this function will always revert.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `token` | address | The token to skim. |\n\n---\n\n### `allocate`\n\n```solidity\nfunction allocate(bytes memory data, uint256 assets, bytes4, address) external returns (bytes32[] memory, int256)\n```\nSupplies `assets` into the specified Morpho Market V1 market.\n\n**Callable by:** `parentVault`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | ABI-encoded `MarketParams` struct identifying the target market. |\n| `assets` | uint256 | The amount of assets to supply. |\n\nThe `bytes4` and `address` parameters are part of the shared adapter interface but unused by this implementation.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `ids` | bytes32[] | The allocation IDs affected by this operation. |\n| `delta` | int256 | The change in allocation (new allocation minus old allocation). Positive for `allocate`, negative for `deallocate`. |\n\n---\n\n### `deallocate`\n\n```solidity\nfunction deallocate(bytes memory data, uint256 assets, bytes4, address) external returns (bytes32[] memory, int256)\n```\nWithdraws `assets` from the specified Morpho Market V1 market back to the parent vault.\n\n**Callable by:** `parentVault`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | ABI-encoded `MarketParams` struct identifying the target market. |\n| `assets` | uint256 | The amount of assets to withdraw. |\n\nThe `bytes4` and `address` parameters are part of the shared adapter interface but unused by this implementation.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `ids` | bytes32[] | The allocation IDs affected by this operation. |\n| `delta` | int256 | The change in allocation (new allocation minus old allocation). Positive for `allocate`, negative for `deallocate`. |\n\n## View Functions\n\n### `realAssets`\n\n```solidity\nfunction realAssets() external view returns (uint256)\n```\nReturns the total expected supply assets across all managed markets, used by the parent vault during interest accrual.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The total assets across all markets in `marketIds`. |\n\n---\n\n### `expectedSupplyAssets`\n\n```solidity\nfunction expectedSupplyAssets(bytes32 marketId) public view returns (uint256)\n```\nReturns the expected supply assets for a specific market, accounting for the adapter's internal share balance.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `marketId` | bytes32 | The market ID to query. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The expected supply assets for the given market. |\n\n---\n\n### `allocation`\n\n```solidity\nfunction allocation(MarketParams memory marketParams) public view returns (uint256)\n```\nReturns the vault's current allocation for this market, as recorded in the parent vault.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `marketParams` | MarketParams | The market parameters struct. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The current allocation amount in the parent vault. |\n\n---\n\n### `ids`\n\n```solidity\nfunction ids(MarketParams memory marketParams) public view returns (bytes32[] memory)\n```\nReturns the three allocation IDs used by this adapter for a given market.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `marketParams` | MarketParams | The market parameters struct. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `ids_` | bytes32[] | Array of 3 IDs: `adapterId`, `keccak256(abi.encode(\"collateralToken\", collateralToken))`, and `keccak256(abi.encode(\"this/marketParams\", address(this), marketParams))`. |\n\n---\n\n### `marketIdsLength`\n\n```solidity\nfunction marketIdsLength() external view returns (uint256)\n```\nReturns the number of markets currently tracked by this adapter. Use this as the upper bound when iterating over [`marketIds`](#marketids).\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `length` | uint256 | The number of market IDs in `marketIds`. |\n\n---\n\n### `marketIds`\n\n```solidity\nbytes32[] public marketIds\n```\nReturns the market ID at the given position in the list of markets with non-zero allocation currently managed by this adapter.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `index` | uint256 | The position in the array. Must be less than [`marketIdsLength()`](#marketidslength). |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `marketId` | bytes32 | The market ID at the given index. |\n\n---\n\n### `timelock`\n\n```solidity\nmapping(bytes4 selector => uint256) public timelock\n```\nReturns the timelock duration (in seconds) for a given function selector.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector to query. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `duration` | uint256 | The timelock duration in seconds for the given selector. |\n\n---\n\n### `abdicated`\n\n```solidity\nmapping(bytes4 selector => bool) public abdicated\n```\nReturns whether the curator has permanently abdicated the ability to execute a specific action.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector to query. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `isAbdicated` | bool | `true` if the curator has abdicated the given selector, `false` otherwise. |\n\n---\n\n### `executableAt`\n\n```solidity\nfunction executableAt(bytes memory data) external view returns (uint256)\n```\nReturns the Unix timestamp (seconds) at which a submitted timelocked action becomes executable.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | The ABI-encoded function call data of the pending action. |\n\n#### Return Values:\n| Value | Meaning |\n| :--- | :--- |\n| `0` | No pending action (never submitted, already executed, or revoked) |\n| `<= block.timestamp` | Action is currently executable (timelock has elapsed) |\n| `> block.timestamp` | Not yet executable — equals `submissionTimestamp + timelock[selector]` |\n\n---\n\n### `supplyShares`\n\n```solidity\nmapping(bytes32 marketId => uint256) public supplyShares\n```\nReturns the adapter's tracked supply shares for a given market.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `marketId` | bytes32 | The market ID to query. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The adapter's tracked supply shares for the given market. |\n\n---\n\n### `skimRecipient`\n\n```solidity\naddress public skimRecipient\n```\nReturns the address that receives skimmed token balances.\n\n---"
  },
  "/get-started/resources/contracts/morpho-v0/": {
    "title": "Morpho V0 (Optimizers - Deprecated)",
    "url": "https://docs.morpho.org/get-started/resources/contracts/morpho-v0/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Morpho V0 (Optimizers - Deprecated)\n\nMorpho 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).\n\nIf you have a position on a Morpho V0 protocol, please reach out via the chatbox on [the Morpho Help Page](https://help.morpho.org/).\n\n## Code\n\n## Morpho V0 deployment addresses\n\n| Contract                                 | Address                                                                                                                                                                                            | Source Code                                                                                                          |\n| :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------- |\n| 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)                                  |\n| Morpho V0 (AaveV2 Optimizer)             | [ 0x777777c9898D384F785Ee44Acfe945efDFf5f3E0 ](https://etherscan.io/address/0x777777c9898D384F785Ee44Acfe945efDFf5f3E0)  | [morpho-org/morpho-optimizers](https://github.com/morpho-org/morpho-optimizers)                                      |\n| Morpho V0 (AaveV2 Lens)                  | [ 0x507fa343d0a90786d86c7cd885f5c49263a91ff4 ](https://etherscan.io/address/0x507fA343d0A90786d86C7cd885f5C49263A91FF4)  | [morpho-org/morpho-optimizers](https://github.com/morpho-org/morpho-optimizers)                                      |\n| Morpho V0 (CompoundV2 Optimizer)         | [ 0x8888882f8f843896699869179fB6E4f7e3B58888 ](https://etherscan.io/address/0x8888882f8f843896699869179fB6E4f7e3B58888)  | [morpho-org/morpho-optimizers](https://github.com/morpho-org/morpho-optimizers)                                      |\n| Morpho V0 (CompoundV2 Lens)              | [ 0x930f1b46e1D081Ec1524efD95752bE3eCe51EF67 ](https://etherscan.io/address/0x930f1b46e1D081Ec1524efD95752bE3eCe51EF67)  | [morpho-org/morpho-optimizers](https://github.com/morpho-org/morpho-optimizers)                                      |\n| 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) |\n\n### Tokenized Supply Vaults\n\nABI are different for Morpho V0 (AaveV2) & Morpho V0 (CompoundV2) vaults, and all the vaults are deployed on the Ethereum mainnet with 18 decimals.\nThey are fully compliant with the [ERC4626](https://eips.ethereum.org/EIPS/eip-4626) standard.\n\n| Contract | Address                                                                                                                                                                                            | Source Code                                                                                             |\n| :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------ |\n| maWBTC   | [ 0xd508F85F1511aAeC63434E26aeB6d10bE0188dC7 ](https://etherscan.io/address/0xd508F85F1511aAeC63434E26aeB6d10bE0188dC7)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| maWETH   | [ 0x490BBbc2485e99989Ba39b34802faFa58e26ABa4 ](https://etherscan.io/address/0x490BBbc2485e99989Ba39b34802faFa58e26ABa4)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| maDAI    | [ 0x36F8d0D0573ae92326827C4a82Fe4CE4C244cAb6 ](https://etherscan.io/address/0x36F8d0D0573ae92326827C4a82Fe4CE4C244cAb6)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| maUSDC   | [ 0xA5269A8e31B93Ff27B887B56720A25F844db0529 ](https://etherscan.io/address/0xA5269A8e31B93Ff27B887B56720A25F844db0529)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| maUSDT   | [ 0xAFe7131a57E44f832cb2dE78ade38CaD644aaC2f ](https://etherscan.io/address/0xAFe7131a57E44f832cb2dE78ade38CaD644aaC2f)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| maCRV    | [ 0x9dc7094530cB1bcf5442c3b9389ee386738A190c ](https://etherscan.io/address/0x9dc7094530cB1bcf5442c3b9389ee386738A190c)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| mcDAI    | [ 0x8F88EaE3e1c01d60bccdc3DB3CBD5362Dd55d707 ](https://etherscan.io/address/0x8F88EaE3e1c01d60bccdc3DB3CBD5362Dd55d707)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| mcWETH   | [ 0x676E1B7d5856f4f69e10399685e17c2299370E95 ](https://etherscan.io/address/0x676E1B7d5856f4f69e10399685e17c2299370E95)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| mcCOMP   | [ 0xaA768b85eC827cCc36D882c1814bcd27ec4A8593 ](https://etherscan.io/address/0xaA768b85eC827cCc36D882c1814bcd27ec4A8593)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| mcUNI    | [ 0x496da625C736a2fF122638Dc26dCf1bFdEf1778c ](https://etherscan.io/address/0x496da625C736a2fF122638Dc26dCf1bFdEf1778c)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| mcUSDC   | [ 0xba9E3b3b684719F80657af1A19DEbc3C772494a0 ](https://etherscan.io/address/0xba9E3b3b684719F80657af1A19DEbc3C772494a0)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| mcUSDT   | [ 0xC2A4fBA93d4120d304c94E4fd986e0f9D213eD8A ](https://etherscan.io/address/0xC2A4fBA93d4120d304c94E4fd986e0f9D213eD8A)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| mcWBTC   | [ 0xF31AC95fe692190b9C67112d8c912bA9973944F2 ](https://etherscan.io/address/0xF31AC95fe692190b9C67112d8c912bA9973944F2)  | [morpho-optimizers-vaults](https://github.com/morpho-org/morpho-optimizers-vaults)                      |\n| ma3WETH  | [ 0x39Dd7790e75C6F663731f7E1FdC0f35007D3879b ](https://etherscan.io/address/0x39Dd7790e75C6F663731f7E1FdC0f35007D3879b)  | [morpho-aave-v3](https://github.com/morpho-org/morpho-aave-v3/blob/main/src/extensions/SupplyVault.sol) |\n\n## Audits and Formal Verification\n\nMorpho is known for its industry-leading security practices and follows a multi-faceted approach to security.\n\nMorpho 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.\n\nA whole article was dedicated to the [Morpho Security Framework](https://morpho.org/blog/morpho-blue-security-framework-building-the-most-secure-lending-protocol/).\n\nThe full list of audits and formal verifications is available below.\n\n### Audits\n\n| Auditors                                                                                 | Scope                                          | Date               | Report                                                                                                       |\n| :--------------------------------------------------------------------------------------- | :--------------------------------------------- | :----------------- | :----------------------------------------------------------------------------------------------------------- |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V0 (AaveV3)                             | 2023-06-19         | [spearbit-report](https://cdn.morpho.org/documents/Spearbit_19062023.pdf)                                    |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V0 (AaveV3)                             | 2023-05-04         | [spearbit-report](https://cdn.morpho.org/documents/Spearbit_04052023.pdf)                                    |\n| [Runtime Verification](https://runtimeverification.com/)                                 | Morpho V0 (AaveV3)                             | 2023-05-02         | [runtime-verification-report](https://cdn.morpho.org/documents/Runtime_02052023.pdf)                         |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V0                                      | 2023-03-01         | [spearbit-report](https://cdn.morpho.org/documents/Spearbit_010323.pdf)                                      |\n| [Pessimistic](https://pessimistic.io/)                                                   | Morpho V0                                      | 2023-02-20         | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_200223.pdf)                                |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V0 [Draft]                              | 2022-12-06         | [spearbit-draft-report](https://cdn.morpho.org/documents/Spearbit_morpho_draft_061222.pdf)                   |\n| [Pessimistic](https://pessimistic.io/)                                                   | Morpho V0                                      | 2022-10-06         | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_061022.pdf)                                |\n| [Omniscia](https://omniscia.io/)                                                         | Morpho V0                                      | 2022-08-25         | [omniscia-report](https://omniscia.io/reports/morpho-labs-tokenized-vaults/)                                 |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V0 (AaveV2)                             | 2022-08-24         | [spearbit-report](https://cdn.morpho.org/documents/MorphoAaveV2_Audit_Spearbit.pdf)                          |\n| [Chainsecurity](https://chainsecurity.com/)                                              | Morpho V0 (AaveV3) [Non Ethereum]              | 2022-08-19         | [chainsecurity-report](https://cdn.morpho.org/documents/MorphoAaveV3_Audit_ChainSecurity.pdf)                |\n| [Omniscia](https://omniscia.io/)                                                         | Morpho Datastructures                          | 2022-08-17         | [omniscia-report](https://cdn.morpho.org/documents/MorphoAaveV2_Audit_Omniscia.pdf)                          |\n| [Pessimistic](https://pessimistic.io/)                                                   | Morpho V0 (AaveV2)                             | 2022-07-25         | [pessimistic-report](https://cdn.morpho.org/documents/MorphoAaveV2_Audit_Pessimistic.pdf)                    |\n| [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)                              |\n| [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)                              |\n| [Spearbit](https://spearbit.com/)                                                        | Morpho V0 (AaveV2)                             | 2022-09-05         | [spearbit-report](https://cdn.morpho.org/documents/Spearbit_090522.pdf)                                      |\n| [Pessimistic](https://pessimistic.io/)                                                   | [Beta] Morpho V0 (CompoundV2)                  | 2022-04-25         | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_250422.pdf)                                |\n| [Pessimistic](https://pessimistic.io/)                                                   | [Beta] Morpho V0 (AaveV2)                      | 2022-03-08         | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_080322.pdf)                                |\n| [Pessimistic](https://pessimistic.io/)                                                   | [Beta] Morpho V0 (AaveV2)                      | 2022-02-16         | [pessimistic-report](https://cdn.morpho.org/documents/pessimistic_160222.pdf)                                |\n| [Pessimistic](https://pessimistic.io/)                                                   | [Alpha] Morpho V0 (AaveV2)                     | 2022-01-11         | [pessimistic-report](https://cdn.morpho.org/documents/Pessimistic_110122.pdf)                                |\n| [Solidified](https://www.solidified.io/)                                                 | [Alpha] Morpho V0 (CompoundV2)                 | 2021-11-04         | [solidified-report](https://cdn.morpho.org/documents/Solidified_041121.pdf)                                  |\n| [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)                                        |\n| [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)          |\n\n### Formal verifications\n\n| Formally Proven                                                                                                             | Scope                              | Date          | Tool Used                                                                      |\n| :-------------------------------------------------------------------------------------------------------------------------- | :--------------------------------- | :------------ | :----------------------------------------------------------------------------- |\n| [Morpho V0 (AaveV3)](https://github.com/morpho-org/morpho-aavev3-optimizer/tree/main/why3)                                  | core logic                         | April 2023    | [Why3](https://www.why3.org/)                                                  |\n| [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                           |\n| [Morpho utils](https://github.com/morpho-org/morpho-utils/tree/main/certora)                                                | math functions                     | December 2022 | [Certora](https://www.certora.com/)                                            |\n| [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) |"
  },
  "/get-started/resources/contracts/morpho-vault-v1-adapter/": {
    "title": "MorphoVaultV1Adapter",
    "url": "https://docs.morpho.org/get-started/resources/contracts/morpho-vault-v1-adapter/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# MorphoVaultV1Adapter\n\n## Code\n\n## Introduction\n\n`MorphoVaultV1Adapter` is an adapter that connects a Morpho Vault V2 to a Morpho Vault V1. It wraps deposits and withdrawals to/from the underlying Vault V1 on behalf of the parent Vault V2.\n\nThis adapter must be used with Morpho Vaults V1 that are protected against inflation attacks with an initial supply. See [OpenZeppelin ERC4626 inflation attack](https://docs.openzeppelin.com/contracts/5.x/erc4626#inflation-attack) and Inflation Front-Running Attack Protection section [here](/curate/concepts/security-considerations/#inflation-front-running-attack-protection).\n\nMust not be used with a Morpho Vault V1 that has a market with an IRM that can re-enter the parent vault or the adapter.\n\nMorpho Vaults V1.1 do not realize bad debt, so a Vault V2 supplying through this adapter will not realize the corresponding bad debt either.\n\n## Timelock System\n\nThis adapter has no timelock system. All functions are callable directly by their respective roles with no submit/execute delay.\n\n## Immutables\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `factory` | address | The factory contract that deployed this adapter. |\n| `parentVault` | address | The Morpho Vault V2 that this adapter belongs to. |\n| `morphoVaultV1` | address | The Morpho Vault V1 (MetaMorpho) contract that this adapter deposits into. |\n| `adapterId` | bytes32 | Unique identifier for this adapter instance, computed as `keccak256(abi.encode(\"this\", address(this)))`. |\n\n## Owner Functions\n\n### `setSkimRecipient`\n\n```solidity\nfunction setSkimRecipient(address newSkimRecipient) external\n```\nSets the address that receives skimmed token balances.\n\n**Callable by:** `Owner` of the parent vault (instant — no timelock)\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newSkimRecipient` | address | The new skim recipient address. |\n\n## Other Functions\n\n### `skim`\n\n```solidity\nfunction skim(address token) external\n```\nTransfers the adapter's entire balance of `token` to `skimRecipient`.\n\nShares of the underlying Morpho Vault V1 (`morphoVaultV1`) cannot be skimmed and will revert if passed as `token`.\n\n**Callable by:** `skimRecipient`\n\nIf `skimRecipient` is not set (`address(0)`), this function will always revert.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `token` | address | The token to skim. Must not be the `morphoVaultV1` share token. |\n\n | :--- | :--- |\n| `data` | bytes | Must be empty (`0x`). |\n| `assets` | uint256 | The amount of assets to deposit. |\n\nThe `bytes4` and `address` parameters are part of the shared adapter interface but unused by this implementation.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `ids` | bytes32[] | The allocation IDs affected (contains `adapterId`). |\n| `delta` | int256 | The change in allocation (new allocation minus old allocation). |\n\n---\n\n### `deallocate`\n\n```solidity\nfunction deallocate(bytes memory data, uint256 assets, bytes4, address) external returns (bytes32[] memory, int256)\n```\nWithdraws `assets` from the underlying Morpho Vault V1 back to the parent vault.\n\n**Callable by:** `parentVault`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | Must be empty (`0x`). |\n| `assets` | uint256 | The amount of assets to withdraw. |\n\nThe `bytes4` and `address` parameters are part of the shared adapter interface but unused by this implementation.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `ids` | bytes32[] | The allocation IDs affected (contains `adapterId`). |\n| `delta` | int256 | The change in allocation (new allocation minus old allocation). |\n\n## View Functions\n\n### `realAssets`\n\n```solidity\nfunction realAssets() external view returns (uint256)\n```\nReturns the current value of the adapter's Vault V1 share balance in underlying assets. Returns `0` if the parent vault has no recorded allocation for this adapter.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The current value of held Vault V1 shares, or `0` if allocation is zero. |\n\n---\n\n### `allocation`\n\n```solidity\nfunction allocation() public view returns (uint256)\n```\nReturns the vault's current allocation for this adapter, as recorded in the parent vault (keyed by `adapterId`).\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The current allocation amount in the parent vault. |\n\n---\n\n### `ids`\n\n```solidity\nfunction ids() public view returns (bytes32[] memory)\n```\nReturns the allocation IDs used by this adapter. Contains a single entry: `adapterId`.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `ids_` | bytes32[] | Array of 1 ID: `adapterId` (`keccak256(abi.encode(\"this\", address(this)))`). |\n\n---\n\n### `skimRecipient`\n\n```solidity\naddress public skimRecipient\n```\nReturns the address that receives skimmed token balances.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `recipient` | address | The current skim recipient address. |"
  },
  "/get-started/resources/contracts/morpho-vaults-v2/": {
    "title": "Morpho Vaults V2",
    "url": "https://docs.morpho.org/get-started/resources/contracts/morpho-vaults-v2/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Morpho Vaults V2\n\n## Code\n\n## Introduction to principles\n\nBy design, Morpho Vault V2 has a non-conventional behaviour on max functions (`maxDeposit`, `maxMint`, `maxWithdraw`, `maxRedeem`): they always return zero.\n\n### Caps structure\n\n```solidity\nstruct Caps {\n    uint256 allocation;\n    uint128 absoluteCap;\n    uint128 relativeCap;\n}\n```\n\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `allocation` | uint256 | The current amount of assets allocated to this `id`. |\n| `absoluteCap`| uint128 | The maximum amount of assets that can be allocated to this `id`. |\n| `relativeCap`| uint128 | The maximum percentage of total assets that can be allocated to this `id`, scaled by 1e18. |\n\n### Function Selectors\n\nA **function selector** is a `bytes4` value that uniquely identifies a function in a smart contract. It's the first 4 bytes of the `keccak256` hash of the function's signature.\n\n**What are they used for in the vault?** Selectors are used for timelock management. The curator can configure different timelock durations for different functions, or permanently abdicate the ability to call specific functions. Functions like `timelock(bytes4 selector)`, `abdicated(bytes4 selector)`, `increaseTimelock(bytes4 selector, ...)`, and `decreaseTimelock(bytes4 selector, ...)` use selectors to identify which function's settings to modify.\n\n**Important notes:**\n- The function signature must include parameter types but not parameter names or return types\n- Example: `\"setPerformanceFee(uint256)\"` not `\"setPerformanceFee(uint256 newFee)\"`\n- Selectors are always exactly 4 bytes (shown as 10 characters in hex: `0x` + 8 hex digits)\n\n#### Timelocked Functions and Selectors\n\n| Function Name                | Selector     |\n| :--------------------------- | :----------- |\n| `setAdapterRegistry`         | `0x5b34b823` |\n| `abdicate`                   | `0xb2e32848` |\n| `setReceiveSharesGate`       | `0x2cb19f98` |\n| `setSendSharesGate`          | `0xc21ad028` |\n| `setReceiveAssetsGate`       | `0x04dbf0ce` |\n| `addAdapter`                 | `0x60d54d41` |\n| `increaseAbsoluteCap`        | `0xf6f98fd5` |\n| `increaseRelativeCap`        | `0x2438525b` |\n| `setForceDeallocatePenalty`  | `0x3e9d2ac7` |\n| `setIsAllocator`             | `0xb192a84a` |\n| `setSendAssetsGate`          | `0x871c979c` |\n| `setPerformanceFee`          | `0x70897b23` |\n| `setManagementFee`           | `0xfe56e232` |\n| `setPerformanceFeeRecipient` | `0x6a5f1aa2` |\n| `setManagementFeeRecipient`  | `0x9faae464` |\n| `removeAdapter`              | `0x585cd34b` |\n| `increaseTimelock`           | `0x47966291` |\n| `decreaseTimelock`           | `0x5c1a1a4f` |\n\n## External Functions\n\n### `deposit`\n\n```solidity\nfunction deposit(uint256 assets, address onBehalf) external returns (uint256)\n```\nDeposits `assets` of the underlying token to mint vault shares for `onBehalf`.\n\n**Callable by:** Anyone\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of the underlying asset to deposit. |\n| `onBehalf` | address | The recipient of the minted vault shares. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The amount of vault shares minted. |\n\n---\n\n### `mint`\n\n```solidity\nfunction mint(uint256 shares, address onBehalf) external returns (uint256)\n```\nMints exactly `shares` vault shares for `onBehalf` by depositing the required amount of the underlying token.\n\n**Callable by:** Anyone\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The exact amount of shares to mint. |\n| `onBehalf` | address | The recipient of the minted vault shares. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of the underlying asset deposited. |\n\n---\n\n### `withdraw`\n\n```solidity\nfunction withdraw(uint256 assets, address receiver, address onBehalf) public returns (uint256)\n```\nWithdraws `assets` of the underlying token by burning shares from `onBehalf` and sends them to `receiver`.\n\n**Callable by:** `onBehalf` or approved address\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of the underlying asset to withdraw. |\n| `receiver`| address | The recipient of the withdrawn assets. |\n| `onBehalf`| address | The owner of the shares to be burned. `msg.sender` must be approved. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The amount of vault shares burned. |\n\n---\n\n### `redeem`\n\n```solidity\nfunction redeem(uint256 shares, address receiver, address onBehalf) external returns (uint256)\n```\nBurns exactly `shares` vault shares from `onBehalf` and sends the corresponding amount of underlying assets to `receiver`.\n\n**Callable by:** `onBehalf` or approved address\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The exact amount of shares to burn. |\n| `receiver`| address | The recipient of the withdrawn assets. |\n| `onBehalf`| address | The owner of the shares to be burned. `msg.sender` must be approved. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of the underlying asset withdrawn. |\n\n---\n\n### `forceDeallocate`\n\n```solidity\nfunction forceDeallocate(address adapter, bytes memory data, uint256 assets, address onBehalf) external returns (uint256)\n```\nForcibly 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.\n\n**Callable by:** Anyone\n\nA `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.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `adapter` | address | The adapter to deallocate from. |\n| `data` | bytes | The protocol-specific data for the deallocation. |\n| `assets` | uint256 | The amount of assets to deallocate. |\n| `onBehalf`| address | The account from which the penalty shares will be burned. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `withdrawnShares` | uint256 | The amount of shares burned from `onBehalf` as a penalty. |\n\n---\n\n### `accrueInterest`\n\n```solidity\nfunction accrueInterest() public\n```\nAccrues interest for the vault by querying adapters for their current assets and updating `totalAssets`. This function is called by most state-changing functions.\n\n**Callable by:** Anyone\n\n---\n\n### `accrueInterestView`\n\n```solidity\nfunction accrueInterestView() public view returns (uint256, uint256, uint256)\n```\nReturns the view version of interest accrual without updating state.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newTotalAssets` | uint256 | The updated total assets after interest accrual. |\n| `performanceFeeShares` | uint256 | The amount of shares that would be minted as performance fee. |\n| `managementFeeShares` | uint256 | The amount of shares that would be minted as management fee. |\n\n---\n\n### `previewDeposit`\n\n```solidity\nfunction previewDeposit(uint256 assets) public view returns (uint256)\n```\nReturns previewed minted shares for a given asset amount.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of assets to preview deposit for. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The amount of shares that would be minted. |\n\n---\n\n### `previewMint`\n\n```solidity\nfunction previewMint(uint256 shares) public view returns (uint256)\n```\nReturns previewed deposited assets for a given share amount.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The amount of shares to preview mint for. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of assets that would be deposited. |\n\n---\n\n### `previewWithdraw`\n\n```solidity\nfunction previewWithdraw(uint256 assets) public view returns (uint256)\n```\nReturns previewed redeemed shares for a given asset amount.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of assets to preview withdrawal for. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The amount of shares that would be burned. |\n\n---\n\n### `previewRedeem`\n\n```solidity\nfunction previewRedeem(uint256 shares) public view returns (uint256)\n```\nReturns previewed withdrawn assets for a given share amount.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The amount of shares to preview redemption for. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of assets that would be withdrawn. |\n\n---\n\n### `convertToShares`\n\n```solidity\nfunction convertToShares(uint256 assets) external view returns (uint256)\n```\nReturns corresponding shares (rounded down) for a given asset amount. Takes into account performance and management fees.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The amount of assets to convert. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The corresponding amount of shares. |\n\n---\n\n### `convertToAssets`\n\n```solidity\nfunction convertToAssets(uint256 shares) external view returns (uint256)\n```\nReturns corresponding assets (rounded down) for a given share amount. Takes into account performance and management fees.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The amount of shares to convert. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The corresponding amount of assets. |\n\n---\n\n### `maxDeposit`\n\n```solidity\nfunction maxDeposit(address) external pure returns (uint256)\n```\nReturns the maximum amount of assets that can be deposited.\n\nAlways returns 0 as a conservative underestimate. Morpho Vault V2 can use external gate contracts for access control; because gate behavior cannot be guaranteed to be revert-free, computing a reliable maximum is not possible.\n\n---\n\n### `maxMint`\n\n```solidity\nfunction maxMint(address) external pure returns (uint256)\n```\nReturns the maximum amount of shares that can be minted.\n\nAlways returns 0 as a conservative underestimate. Morpho Vault V2 can use external gate contracts for access control; because gate behavior cannot be guaranteed to be revert-free, computing a reliable maximum is not possible.\n\n---\n\n### `maxWithdraw`\n\n```solidity\nfunction maxWithdraw(address) external pure returns (uint256)\n```\nReturns the maximum amount of assets that can be withdrawn.\n\nAlways returns 0 as a conservative underestimate. Morpho Vault V2 can use external gate contracts for access control; because gate behavior cannot be guaranteed to be revert-free, computing a reliable maximum is not possible.\n\n---\n\n### `maxRedeem`\n\n```solidity\nfunction maxRedeem(address) external pure returns (uint256)\n```\nReturns the maximum amount of shares that can be redeemed.\n\nAlways returns 0 as a conservative underestimate. Morpho Vault V2 can use external gate contracts for access control; because gate behavior cannot be guaranteed to be revert-free, computing a reliable maximum is not possible.\n\n---\n\n### `multicall`\n\n```solidity\nfunction multicall(bytes[] calldata data) external\n```\nUseful 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.\n\n**Callable by:** Anyone\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes[] | Array of encoded function calls to execute. |\n\n---\n\nAs a reminder, there are four distinct [roles](/curate/concepts/roles#morpho-vaults-v2-roles) in Morpho Vaults V2:\n\n1. **Owner**: Manages role assignments.\n2. **Curator**: The chief risk curator and strategist.\n3. **Allocator**: The active portfolio curator.\n4. **Sentinel**: A safety-oriented role for reactive risk mitigation.\n\n## Owner Functions\n\n---\n\n### `setOwner`\n\n```solidity\nfunction setOwner(address newOwner) external\n```\nTransfers ownership of the vault to `newOwner`.\n\n**Callable by:** `Owner`\n\n---\n\n### `setCurator`\n\n```solidity\nfunction setCurator(address newCurator) external\n```\nSets the vault's `Curator`.\n\n**Callable by:** `Owner`\n\n---\n\n### `setIsSentinel`\n\n```solidity\nfunction setIsSentinel(address account, bool newIsSentinel) external\n```\nGrants or revokes the `Sentinel` role for an `account`.\n\n**Callable by:** `Owner`\n\n---\n\n### `setName`\n\n```solidity\nfunction setName(string memory newName) external\n```\nSets the vault's name.\n\n**Callable by:** `Owner`\n\n---\n\n### `setSymbol`\n\n```solidity\nfunction setSymbol(string memory newSymbol) external\n```\nSets the vault's symbol.\n\n**Callable by:** `Owner`\n\n## Curator Functions\n\nThe following functions are only callable by the `Curator`. Some are subject to a **timelock** while others are **instant**. The timelock process is:\n1. `Curator` calls `submit(bytes calldata data)` with the ABI-encoded function call.\n2. After the timelock expires, anyone can execute the function directly.\n\n---\n\n### `abdicate`\n\n```solidity\nfunction abdicate(bytes4 selector) external\n```\nIrreversibly disables the ability to execute a specific type of action.\n\nThis action is irreversible. Existing pending operations submitted before abdicating cannot be executed.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0xb2e32848`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector to abdicate. |\n\n---\n\n### `addAdapter`\n\n```solidity\nfunction addAdapter(address account) external\n```\nAdds a new adapter to the vault.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x60d54d41`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The adapter address to add. |\n\n---\n\n### `decreaseAbsoluteCap`\n\n```solidity\nfunction decreaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external\n```\nDecreases 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.\n\n**Callable by:** `Curator`, `Sentinel`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `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. |\n| `newAbsoluteCap` | uint256 | The new absolute cap value. |\n\n---\n\n### `decreaseRelativeCap`\n\n```solidity\nfunction decreaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external\n```\nDecreases 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.\n\n**Callable by:** `Curator`, `Sentinel`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `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. |\n| `newRelativeCap` | uint256 | The new relative cap value (scaled by 1e18). |\n\n---\n\n### `decreaseTimelock`\n\n```solidity\nfunction decreaseTimelock(bytes4 selector, uint256 newDuration) external\n```\nDecreases a function's timelock duration. This action's timelock equals the current timelock of the function being decreased.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x5c1a1a4f`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector. |\n| `newDuration` | uint256 | The new timelock duration. |\n\n---\n\n### `increaseAbsoluteCap`\n\n```solidity\nfunction increaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external\n```\nIncreases 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.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0xf6f98fd5`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `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. |\n| `newAbsoluteCap` | uint256 | The new absolute cap value. |\n\n---\n\n### `increaseRelativeCap`\n\n```solidity\nfunction increaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external\n```\nIncreases 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.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x2438525b`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `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. |\n| `newRelativeCap` | uint256 | The new relative cap value (scaled by 1e18). |\n\n---\n\n### `increaseTimelock`\n\n```solidity\nfunction increaseTimelock(bytes4 selector, uint256 newDuration) external\n```\nIncreases a function's timelock duration.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x47966291`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector. |\n| `newDuration` | uint256 | The new timelock duration. |\n\n---\n\n### `removeAdapter`\n\n```solidity\nfunction removeAdapter(address account) external\n```\nRemoves an adapter from the vault.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x585cd34b`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The adapter address to remove. |\n\n---\n\n### `revoke`\n\n```solidity\nfunction revoke(bytes calldata data) external\n```\nRevokes a pending timelocked action.\n\n**Callable by:** `Curator`, `Sentinel`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | The ABI-encoded function call data to revoke. |\n\n---\n\n### `setAdapterRegistry`\n\n```solidity\nfunction setAdapterRegistry(address newAdapterRegistry) external\n```\nSets the adapter registry contract. The function validates that the new registry approves all currently added adapters.\nIf the new registry returns false for any existing adapter, the transaction will revert.\nThis ensures that changing the registry doesn't invalidate adapters that are already in use.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x5b34b823`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newAdapterRegistry` | address | The new adapter registry contract. |\n\n---\n\n### `setForceDeallocatePenalty`\n\n```solidity\nfunction setForceDeallocatePenalty(address adapter, uint256 newForceDeallocatePenalty) external\n```\nSets the penalty for using [`forceDeallocate`](/get-started/resources/contracts/morpho-vaults-v2/#forcedeallocate) on a specific adapter.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x3e9d2ac7`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `adapter` | address | The adapter to set penalty for. |\n| `newForceDeallocatePenalty` | uint256 | The new penalty value (scaled by 1e18). |\n\n---\n\n### `setIsAllocator`\n\n```solidity\nfunction setIsAllocator(address account, bool newIsAllocator) external\n```\nGrants or revokes the `Allocator` role for an account.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0xb192a84a`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The account to modify. |\n| `newIsAllocator` | bool | Whether the account should be an allocator. |\n\n---\n\n### `setManagementFee`\n\n```solidity\nfunction setManagementFee(uint256 newManagementFee) external\n```\nSets the vault's management fee.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0xfe56e232`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newManagementFee` | uint256 | The new management fee (scaled by 1e18). |\n\n---\n\n### `setManagementFeeRecipient`\n\n```solidity\nfunction setManagementFeeRecipient(address newManagementFeeRecipient) external\n```\nSets the management fee recipient.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x9faae464`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newManagementFeeRecipient` | address | The new management fee recipient. |\n\n---\n\n### `setPerformanceFee`\n\n```solidity\nfunction setPerformanceFee(uint256 newPerformanceFee) external\n```\nSets the vault's performance fee.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x70897b23`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newPerformanceFee` | uint256 | The new performance fee (scaled by 1e18). |\n\n---\n\n### `setPerformanceFeeRecipient`\n\n```solidity\nfunction setPerformanceFeeRecipient(address newPerformanceFeeRecipient) external\n```\nSets the performance fee recipient.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x6a5f1aa2`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newPerformanceFeeRecipient` | address | The new performance fee recipient. |\n\n---\n\n### `setReceiveAssetsGate`\n\n```solidity\nfunction setReceiveAssetsGate(address newReceiveAssetsGate) external\n```\nSets the contract for gating asset receipts.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x04dbf0ce`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newReceiveAssetsGate` | address | The new receive assets gate contract. |\n\n---\n\n### `setReceiveSharesGate`\n\n```solidity\nfunction setReceiveSharesGate(address newReceiveSharesGate) external\n```\nSets the contract for gating share receipts.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x2cb19f98`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newReceiveSharesGate` | address | The new receive shares gate contract. |\n\n---\n\n### `setSendAssetsGate`\n\n```solidity\nfunction setSendAssetsGate(address newSendAssetsGate) external\n```\nSets the contract for gating asset sends.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0x871c979c`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newSendAssetsGate` | address | The new send assets gate contract. |\n\n---\n\n### `setSendSharesGate`\n\n```solidity\nfunction setSendSharesGate(address newSendSharesGate) external\n```\nSets the contract for gating share sends.\n\n**Callable by:** `Curator` (timelocked — submit first, then anyone can execute after delay)\n\nSelector: `0xc21ad028`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newSendSharesGate` | address | The new send shares gate contract. |\n\n---\n\n### `submit`\n\n```solidity\nfunction submit(bytes calldata data) external\n```\nSubmits a timelocked action for execution after the timelock period expires.\n\n**Callable by:** `Curator`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | The ABI-encoded function call data. |\n\n## Allocator Functions\n\n### `allocate`\n\n```solidity\nfunction allocate(address adapter, bytes memory data, uint256 assets) external\n```\nAllocates `assets` from the vault's idle pool to a specific `adapter`. The allocation is subject to the caps configured for the target market.\n\n**Callable by:** `Allocator`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `adapter` | address | The adapter to allocate assets to. |\n| `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. |\n| `assets` | uint256 | The amount of assets to allocate. |\n\n---\n\n### `deallocate`\n\n```solidity\nfunction deallocate(address adapter, bytes memory data, uint256 assets) external\n```\nDeallocates `assets` from an `adapter` back to the vault's idle pool.\n\n**Callable by:** `Allocator`, `Sentinel`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `adapter` | address | The adapter to deallocate assets from. |\n| `data` | bytes | Market-specific data encoding passed to the adapter (e.g., market ID for Morpho markets). Must match the data used when allocating. |\n| `assets` | uint256 | The amount of assets to deallocate. |\n\n---\n\n### `setLiquidityAdapterAndData`\n\n```solidity\nfunction setLiquidityAdapterAndData(address newLiquidityAdapter, bytes memory newLiquidityData) external\n```\nSets the default adapter for handling user deposits and withdrawals.\n\n**Callable by:** `Allocator`\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newLiquidityAdapter` | address | The new liquidity adapter address. |\n| `newLiquidityData` | bytes | The new liquidity data for the adapter. |\n\n---\n\n### `setMaxRate`\n\n```solidity\nfunction setMaxRate(uint256 newMaxRate) external\n```\nSets the maximum rate at which `totalAssets` can grow. An allocator-controlled parameter that caps how quickly totalAssets can grow, useful for implementing fixed-rate distributions or preventing unrealistic yield spikes.\n`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))\n\n**Callable by:** `Allocator`\n\nIf `maxRate` is 0, yield does not accrue to vault's suppliers.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `newMaxRate` | uint256 | The new maximum rate per second (scaled by 1e18). |\n\n## Gating Functions\n\nGates are optional external smart contracts that implement access control for the vault.\nThe vault supports four independent gates: `receiveSharesGate`, `sendSharesGate`, `receiveAssetsGate`, and `sendAssetsGate`.\n\nGates are separate smart contracts that you (or the curator) must deploy independently.\nThey are not part of the vault contract itself. The curator configures them using functions like `setReceiveSharesGate`, `setSendSharesGate`, etc.\n\nEach gate contract must implement a function that returns `bool` to indicate whether an account is allowed to perform the action.\nThe vault calls these gates during transfers and deposits/withdrawals to enforce access control.\n\n---\n\n### `canReceiveShares`\n\n```solidity\nfunction canReceiveShares(address account) public view returns (bool)\n```\nChecks if an account can receive shares based on the receive shares gate.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The account to check. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `allowed` | bool | Whether the account can receive shares. |\n\n---\n\n### `canSendShares`\n\n```solidity\nfunction canSendShares(address account) public view returns (bool)\n```\nChecks if an account can send shares based on the send shares gate.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The account to check. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `allowed` | bool | Whether the account can send shares. |\n\n---\n\n### `canReceiveAssets`\n\n```solidity\nfunction canReceiveAssets(address account) public view returns (bool)\n```\nChecks if an account can receive assets based on the receive assets gate. The vault itself is always allowed.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The account to check. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `allowed` | bool | Whether the account can receive assets. |\n\n---\n\n### `canSendAssets`\n\n```solidity\nfunction canSendAssets(address account) public view returns (bool)\n```\nChecks if an account can send assets based on the send assets gate.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The account to check. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `allowed` | bool | Whether the account can send assets. |\n\n## View Functions\n\n### `totalAssets`\n\n```solidity\nfunction totalAssets() external view returns (uint256)\n```\nReturns the total amount of underlying assets held by the vault, including both idle assets and assets allocated to adapters.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The total assets in the vault. |\n\n---\n\n### `adaptersLength`\n\n```solidity\nfunction adaptersLength() external view returns (uint256)\n```\nReturns the number of adapters currently added to the vault.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `length` | uint256 | The number of adapters. |\n\n---\n\n### `absoluteCap`\n\n```solidity\nfunction absoluteCap(bytes32 id) external view returns (uint256)\n```\nReturns 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.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `id` | bytes32 | The allocation identifier (keccak256 hash of idData). |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `cap` | uint256 | The absolute cap value. |\n\n---\n\n### `relativeCap`\n\n```solidity\nfunction relativeCap(bytes32 id) external view returns (uint256)\n```\nReturns 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.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `id` | bytes32 | The allocation identifier (keccak256 hash of idData). |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `cap` | uint256 | The relative cap value (scaled by 1e18). |\n\n---\n\n### `allocation`\n\n```solidity\nfunction allocation(bytes32 id) external view returns (uint256)\n```\nReturns 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.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `id` | bytes32 | The allocation identifier (keccak256 hash of idData). |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `amount` | uint256 | The current allocation amount. |\n\n---\n\n### `owner`\n\n```solidity\nfunction owner() external view returns (address)\n```\nReturns the current owner address of the vault.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `owner` | address | The owner address. |\n\n---\n\n### `curator`\n\n```solidity\nfunction curator() external view returns (address)\n```\nReturns the current curator address of the vault.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `curator` | address | The curator address. |\n\n---\n\n### `isSentinel`\n\n```solidity\nfunction isSentinel(address account) external view returns (bool)\n```\nChecks if an account has the Sentinel role.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The account to check. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `isSentinel` | bool | Whether the account is a sentinel. |\n\n---\n\n### `isAllocator`\n\n```solidity\nfunction isAllocator(address account) external view returns (bool)\n```\nChecks if an account has the Allocator role.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The account to check. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `isAllocator` | bool | Whether the account is an allocator. |\n\n---\n\n### `receiveSharesGate`\n\n```solidity\nfunction receiveSharesGate() external view returns (address)\n```\nReturns the address of the receive shares gate contract.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `gate` | address | The receive shares gate address. |\n\n---\n\n### `sendSharesGate`\n\n```solidity\nfunction sendSharesGate() external view returns (address)\n```\nReturns the address of the send shares gate contract.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `gate` | address | The send shares gate address. |\n\n---\n\n### `receiveAssetsGate`\n\n```solidity\nfunction receiveAssetsGate() external view returns (address)\n```\nReturns the address of the receive assets gate contract.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `gate` | address | The receive assets gate address. |\n\n---\n\n### `sendAssetsGate`\n\n```solidity\nfunction sendAssetsGate() external view returns (address)\n```\nReturns the address of the send assets gate contract.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `gate` | address | The send assets gate address. |\n\n---\n\n### `adapterRegistry`\n\n```solidity\nfunction adapterRegistry() external view returns (address)\n```\nReturns the address of the adapter registry contract.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `registry` | address | The adapter registry address. |\n\n---\n\n### `adapters`\n\n```solidity\nfunction adapters(uint256 index) external view returns (address)\n```\nReturns the adapter address at a specific index (index list retrievable via the [`adaptersLength`](/get-started/resources/contracts/morpho-vaults-v2/#adapterslength) function).\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `index` | uint256 | The index in the adapters array. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `adapter` | address | The adapter address at the given index. |\n\n---\n\n### `isAdapter`\n\n```solidity\nfunction isAdapter(address account) external view returns (bool)\n```\nChecks if an account is a registered adapter.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `account` | address | The account to check. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `isAdapter` | bool | Whether the account is an adapter. |\n\n---\n\n### `liquidityAdapter`\n\n```solidity\nfunction liquidityAdapter() external view returns (address)\n```\nReturns the default adapter used for handling user deposits and withdrawals.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `adapter` | address | The liquidity adapter address. |\n\n---\n\n### `liquidityData`\n\n```solidity\nfunction liquidityData() external view returns (bytes memory)\n```\nReturns the data associated with the liquidity adapter.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | The liquidity adapter data. |\n\n---\n\n### `forceDeallocatePenalty`\n\n```solidity\nfunction forceDeallocatePenalty(address adapter) external view returns (uint256)\n```\nReturns the penalty for using `forceDeallocate` on a specific adapter.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `adapter` | address | The adapter to check. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `penalty` | uint256 | The force deallocate penalty (scaled by 1e18). |\n\n---\n\n### `virtualShares`\n\n```solidity\nfunction virtualShares() external view returns (uint256)\n```\nReturns the virtual shares used for avoiding initial share inflation attacks.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `shares` | uint256 | The virtual shares amount. |\n\n---\n\n### `firstTotalAssets`\n\n```solidity\nfunction firstTotalAssets() external view returns (uint256)\n```\nReturns the total assets after the first interest accrual of the current transaction. Used to prevent bypassing relative caps with flashloans.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint256 | The total assets after the first interest accrual of the transaction. |\n\n---\n\n### `_totalAssets`\n\n```solidity\nfunction _totalAssets() external view returns (uint128)\n```\nReturns the internal cached total assets value.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `assets` | uint128 | The cached total assets. |\n\n---\n\n### `lastUpdate`\n\n```solidity\nfunction lastUpdate() external view returns (uint64)\n```\nReturns the timestamp of the last interest accrual.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `timestamp` | uint64 | The last update timestamp. |\n\n---\n\n### `maxRate`\n\n```solidity\nfunction maxRate() external view returns (uint64)\n```\nReturns the maximum rate at which `totalAssets` can grow.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `rate` | uint64 | The maximum rate per second (scaled by 1e18). |\n\n---\n\n### `performanceFee`\n\n```solidity\nfunction performanceFee() external view returns (uint96)\n```\nReturns the current performance fee.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `fee` | uint96 | The performance fee (scaled by 1e18). |\n\n---\n\n### `performanceFeeRecipient`\n\n```solidity\nfunction performanceFeeRecipient() external view returns (address)\n```\nReturns the recipient address of performance fees.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `recipient` | address | The performance fee recipient address. |\n\n---\n\n### `managementFee`\n\n```solidity\nfunction managementFee() external view returns (uint96)\n```\nReturns the current management fee.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `fee` | uint96 | The management fee (scaled by 1e18). |\n\n---\n\n### `managementFeeRecipient`\n\n```solidity\nfunction managementFeeRecipient() external view returns (address)\n```\nReturns the recipient address of management fees.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `recipient` | address | The management fee recipient address. |\n\n---\n\n### `timelock`\n\n```solidity\nfunction timelock(bytes4 selector) external view returns (uint256)\n```\nReturns the timelock duration for a specific function selector.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `duration` | uint256 | The timelock duration in seconds. |\n\n---\n\n### `abdicated`\n\n```solidity\nfunction abdicated(bytes4 selector) external view returns (bool)\n```\nChecks if the curator has abdicated the ability to execute a specific action.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `selector` | bytes4 | The function selector. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `abdicated` | bool | Whether the action has been abdicated. |\n\n---\n\n### `executableAt`\n\n```solidity\nfunction executableAt(bytes memory data) external view returns (uint256)\n```\nReturns the timestamp when a submitted timelocked action becomes executable.\n\n#### Parameters:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `data` | bytes | The ABI-encoded function call data. |\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `timestamp` | uint256 | The timestamp when the action becomes executable. |\n\n---\n\n### `DOMAIN_SEPARATOR`\n\n```solidity\nfunction DOMAIN_SEPARATOR() external view returns (bytes32)\n```\nReturns the EIP-712 domain separator used for permit signatures.\n\n#### Return Values:\n| Name | Type | Description |\n| :--- | :--- | :--- |\n| `separator` | bytes32 | The domain separator. |"
  },
  "/get-started/resources/contracts/morpho-vaults/": {
    "title": "Morpho Vaults",
    "url": "https://docs.morpho.org/get-started/resources/contracts/morpho-vaults/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Morpho Vaults\n\n## Code\n\n## Market\n\nThose following 3 elements are defined in the [Morpho related section](/get-started/resources/contracts/morpho#market-parameters).\n\n- `MarketParams` struct,\n\n- `market` struct,\n\n- `Id` of markets.\n\nAlso we have:\n\n```solidity\n      struct MarketAllocation {\n          MarketParams marketParams;\n          uint256 assets;\n      }\n```\n\n| Name           | Type                                                                      | Description                       |\n| :------------- | :------------------------------------------------------------------------ | :-------------------------------- |\n| `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The market to allocate funds to.  |\n| `assets`       | uint256                                                                   | The amount of assets to allocate. |\n\n## External Functions\n\n### deposit\n\n```solidity\nfunction deposit(uint256 assets, address receiver) public override returns (uint256 shares) {}\n```\n\nDeposits `assets` of underlying token into the vault to mint vault shares to `receiver`.\n\n#### Parameters:\n\n| Name       | Type    | Description                                          |\n| :--------- | :------ | :--------------------------------------------------- |\n| `assets`   | uint256 | The quantity of asset to deposit.                    |\n| `receiver` | address | The address that will own the position on the vault. |\n\n#### Return Values:\n\n| Name     | Type    | Description                        |\n| :------- | :------ | :--------------------------------- |\n| `shares` | uint256 | The amount of vault shares minted. |\n\n### mint\n\n```solidity\nfunction mint(uint256 shares, address receiver) public override returns (uint256 assets) {}\n```\n\nMints exactly `shares` vault shares to receiver by depositing underlying tokens into the vault.\n\n#### Parameters:\n\n| Name       | Type    | Description                                          |\n| :--------- | :------ | :--------------------------------------------------- |\n| `shares`   | uint256 | The quantity of shares to mint.                      |\n| `receiver` | address | The address that will own the position on the vault. |\n\n#### Return Values:\n\n| Name     | Type    | Description                               |\n| :------- | :------ | :---------------------------------------- |\n| `assets` | uint256 | The amount of underlying token deposited. |\n\n### withdraw\n\n```solidity\nfunction withdraw(uint256 assets, address receiver, address owner) public override returns (uint256 shares) {}\n```\n\nWithdraws `assets` of underlying token by burning vault shares of `owner`, and sends the withdrawn assets to `receiver`.\n\n`msg.sender` must be authorized to manage `owner`'s vault balance.\n\n#### Parameters:\n\n| Name       | Type    | Description                                                           |\n| :--------- | :------ | :-------------------------------------------------------------------- |\n| `assets`   | uint256 | The quantity of asset to withdraw.                                    |\n| `receiver` | address | The address that will receive the withdrawn assets.                   |\n| `owner`    | address | The address that will see its position burnt of the amount of assets. |\n\n#### Return Values:\n\n| Name     | Type    | Description                  |\n| :------- | :------ | :--------------------------- |\n| `shares` | uint256 | The amount of shares burned. |\n\n### redeem\n\n```solidity\nfunction redeem(uint256 shares, address receiver, address owner) public override returns (uint256 assets) {}\n```\n\nBurns exactly `shares` vault shares from `owner` and sends the withdrawn assets of underlying tokens to `receiver`.\n\n`msg.sender` must be authorized to manage `owner`'s vault balance.\n\n#### Parameters:\n\n| Name       | Type    | Description                                                           |\n| :--------- | :------ | :-------------------------------------------------------------------- |\n| `shares`   | uint256 | The quantity of shares to burn.                                       |\n| `receiver` | address | The address that will receive the minted shares.                      |\n| `owner`    | address | The address that will see its position burnt of the amount of shares. |\n\n#### Return Values:\n\n| Name     | Type    | Description                               |\n| :------- | :------ | :---------------------------------------- |\n| `assets` | uint256 | The amount of underlying token withdrawn. |\n\n### acceptTimelock\n\n```solidity\nfunction acceptTimelock() external;\n```\n\nAccepts the pending timelock.\n\nThis function is timelocked, which means `timelock` must have passed since the pending timelock submission for this function to be successfully called.\n\n### acceptGuardian\n\n```solidity\nfunction acceptGuardian() external afterTimelock(pendingGuardian.validAt) {}\n```\n\nAccepts the pending guardian.\n\nThis function is timelocked, which means `timelock` must have passed since the pending guardian submission for this function to be successfully called.\n\n### acceptCap\n\n```solidity\nfunction acceptCap(MarketParams memory marketParams) external;\n```\n\nAccepts the pending cap of the market defined by `marketParams`.\n\nThis function is timelocked, which means `timelock` must have passed since the pending cap submission for this function to be successfully called.\n\n#### Parameters:\n\n| Name | Type                                                 | Description                             |\n| :--- | :--------------------------------------------------- | :-------------------------------------- |\n| `id` | [Id](/get-started/resources/contracts/morpho#market-id) | The id of the market to accept the cap. |\n\n### skim\n\n```solidity\nfunction skim(address token) external {}\n```\n\nSkims the vault `token` balance to `skimRecipient`.\n\n#### Parameters:\n\n| Name    | Type    | Description                                      |\n| :------ | :------ | :----------------------------------------------- |\n| `token` | address | The address of the token to skim the balance of. |\n\nThe following functions are inheriting the [IERC4626 interface](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/interfaces/IERC4626.sol)\n\nAs a reminder, there are specific types of [roles](/curate/concepts/roles/) in Morpho Vaults:\n\n1. **Owner**,\n2. **Curator**,\n3. **Allocator**,\n4. **Guardian**.\n\n## OnlyOwner Functions\n\n### setName (V1.1)\n\n```solidity\nfunction setName(string memory newName) external onlyOwner {}\n```\n\nSets the vault's name to `newName`.\n\n#### Parameters:\n\n| Name      | Type   | Description               |\n| :-------- | :----- | :------------------------ |\n| `newName` | string | The new name of the vault |\n\n### setSymbol (V1.1)\n\n```solidity\nfunction setSymbol(string memory newSymbol) external onlyOwner {}\n```\n\nSets the vault's symbol to `newSymbol`.\n\n#### Parameters:\n\n| Name        | Type   | Description                 |\n| :---------- | :----- | :-------------------------- |\n| `newSymbol` | string | The new symbol of the vault |\n\n### setCurator\n\n```solidity\nfunction setCurator(address newCurator) external onlyOwner {};\n```\n\nSets `curator` to `newCurator`.\n\n#### Parameters:\n\n| Name         | Type    | Description                     |\n| :----------- | :------ | :------------------------------ |\n| `newCurator` | address | The address of the new curator. |\n\n### setIsAllocator\n\n```solidity\nfunction setIsAllocator(address newAllocator, bool newIsAllocator) external onlyOwner {};\n```\n\nSets `newAllocator` as an allocator or not (`newIsAllocator`).\n\n#### Parameters:\n\n| Name             | Type    | Description                                                                 |\n| :--------------- | :------ | :-------------------------------------------------------------------------- |\n| `newAllocator`   | address | The address of the new allocator.                                           |\n| `newIsAllocator` | bool    | A boolean (true or false) indicating if the address is an allocator or not. |\n\n### setSkimRecipient\n\n```solidity\nfunction setSkimRecipient(address newSkimRecipient) external onlyOwner {};\n```\n\nSets `skimRecipient` to `newSkimRecipient`.\n\n#### Parameters:\n\n| Name               | Type    | Description                                  |\n| :----------------- | :------ | :------------------------------------------- |\n| `newSkimRecipient` | address | The address of the new recipient parameters. |\n\n### submitTimelock\n\n```solidity\nfunction submitTimelock(uint256 newTimelock) external onlyOwner {};\n```\n\nSubmits a `newTimelock`.\n\n- Warning: Reverts if a timelock is already pending. Revoke the pending timelock to overwrite it.\n\n- In case the new timelock is higher than the current one, the timelock is set immediately.\n\n#### Parameters:\n\n| Name          | Type    | Description                                 |\n| :------------ | :------ | :------------------------------------------ |\n| `newTimelock` | uint256 | The value of the new timelock (in seconds). |\n\n### setFee\n\n```solidity\nfunction setFee(uint256 newFee) external onlyOwner {};\n```\n\nSets the `fee` to `newFee`.\n\n#### Parameters:\n\n| Name     | Type    | Description                             |\n| :------- | :------ | :-------------------------------------- |\n| `newFee` | uint256 | The value of the new fee scaled in wad. |\n\n### setFeeRecipient\n\n```solidity\nfunction setFeeRecipient(address newFeeRecipient) external onlyOwner {};\n```\n\nSets `feeRecipient` to `newFeeRecipient`.\n\n#### Parameters:\n\n| Name              | Type    | Description                           |\n| :---------------- | :------ | :------------------------------------ |\n| `newFeeRecipient` | address | The address of the new fee recipient. |\n\n### submitGuardian\n\n```solidity\nfunction submitGuardian(address newGuardian) external onlyOwner {};\n```\n\nSubmits a `newGuardian`.\n\n- Warning: a malicious guardian could disrupt the vault's operation, and would have the power to revoke any pending guardian.\n\n- In case there is no guardian, the gardian is set immediately.\n\n- Warning: Submitting a gardian will overwrite the current pending gardian.\n\n#### Parameters:\n\n| Name          | Type    | Description                      |\n| :------------ | :------ | :------------------------------- |\n| `newGuardian` | address | The address of the new guardian. |\n\n## onlyCuratorRole Functions\n\nNote that owner and curator has the `onlyCuratorRole`.\n\n### submitCap\n\n```solidity\nfunction submitCap(MarketParams memory marketParams, uint256 newSupplyCap) external onlyCuratorRole {};\n```\n\nSubmits a `newSupplyCap` for the market defined by `marketParams`.\n\n- Warning: Reverts if a cap is already pending. Revoke the pending cap to overwrite it.\n\n- Warning: Reverts if a market removal is pending.\n\n- In case the new cap is lower than the current one, the cap is set immediately.\n\n#### Parameters:\n\n| Name           | Type                                                                      | Description                             |\n| :------------- | :------------------------------------------------------------------------ | :-------------------------------------- |\n| `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The market parameters.                  |\n| `newSupplyCap` | uint256                                                                   | The new supply cap in underlying units. |\n\n### submitMarketRemoval\n\n```solidity\nfunction submitMarketRemoval(Id id) external onlyCuratorRole {};\n```\n\nSubmits a forced market removal from the vault, eventually losing all funds supplied to the market.\n\n- 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.\n\n- 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`).\n\n- Warning: Removing a market with non-zero supply will instantly impact the vault's price per share.\n\n- Warning: Reverts for non-zero cap or if there is a pending cap. Successfully submitting a zero cap will prevent such reverts.\n\n#### Parameters:\n\n| Name           | Type                                                                      | Description            |\n| :------------- | :------------------------------------------------------------------------ | :--------------------- |\n| `marketParams` | [MarketParams](/get-started/resources/contracts/morpho/#marketparams-struct) | The market parameters. |\n\n## onlyAllocatorRole Functions\n\nNote that owner, curator and an address that has been set as an allocator has the `onlyAllocatorRole`.\n\n### setSupplyQueue\n\n```solidity\nfunction setSupplyQueue(Id[] calldata newSupplyQueue) external onlyAllocatorRole {};\n```\n\nSets `supplyQueue` to `newSupplyQueue`.\n\n#### Parameters:\n\n| Name             | Type                                                     | Description                                                                                                                                       |\n| :--------------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `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. |\n\n### updateWithdrawQueue\n\n```solidity\nfunction updateWithdrawQueue(uint256[] calldata indexes) external onlyAllocatorRole {};\n```\n\nUpdates the withdraw queue. Some markets can be removed, but no market can be added.\n\n- 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`).\n\n- 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`.\n\n- 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).\n\n- Warning: `updateWithdrawQueue` is not idempotent. Submitting twice the same tx will change the queue twice.\n\n#### Parameters:\n\n| Name      | Type        | Description                                                                                   |\n| :-------- | :---------- | :-------------------------------------------------------------------------------------------- |\n| `indexes` | uint256 [ ] | The indexes of each market in the previous withdraw queue, in the new withdraw queue's order. |\n\n### reallocate\n\n```solidity\nfunction reallocate(MarketAllocation[] calldata allocations) external onlyAllocatorRole {};\n```\n\nReallocates the vault's liquidity so as to reach a given allocation of assets on each given market.\n\n- 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.\n\n- The behavior of the reallocation can be altered by state changes, including:\n\n  - Deposits on the vault that supplies to markets that are expected to be supplied to during reallocation.\n  - Withdrawals from the vault that withdraws from markets that are expected to be withdrawn from during\n    reallocation.\n  - Donations to the vault on markets that are expected to be supplied to during reallocation.\n  - Withdrawals from markets that are expected to be withdrawn from during reallocation.\n\n- Sender is expected to pass `assets = type(uint256).max` with the last MarketAllocation of `allocations` to\n  supply all the remaining withdrawn liquidity, which would ensure that `totalWithdrawn` = `totalSupplied`.\n\n#### Parameters:\n\n| Name          | Type                                                                   | Description                                       |\n| :------------ | :--------------------------------------------------------------------- | :------------------------------------------------ |\n| `allocations` | [MarketAllocation](/get-started/resources/contracts/morpho-vaults#market) | The respective allocations in each market chosen. |\n\n## onlyGuardianRole Functions\n\nNote that owner and guardian has the `onlyAllocatorRole`.\n\n### revokePendingTimelock\n\n```solidity\nfunction revokePendingTimelock() external onlyGuardianRole {};\n```\n\nRevokes the pending timelock.\n\n- Does not revert if there is no pending timelock.\n\n### revokePendingGuardian\n\n```solidity\nfunction revokePendingGuardian() external onlyGuardianRole {};\n```\n\nRevokes the pending guardian.\n\n## onlyCuratorOrGuardianRole Functions\n\nNote that owner, curator and guardian has the `onlyAllocatorRole`.\n\n### revokePendingCap\n\n```solidity\nfunction revokePendingCap(Id id) external onlyCuratorOrGuardianRole {};\n```\n\nRevokes the pending cap of the market defined by `id`.\n\n- Does not revert if there is no pending cap.\n\n#### Parameters:\n\n| Name | Type                                                 | Description                                     |\n| :--- | :--------------------------------------------------- | :---------------------------------------------- |\n| `id` | [Id](/get-started/resources/contracts/morpho#market-id) | The id of the market to revoke the pending cap. |\n\n### revokePendingMarketRemoval\n\n```solidity\nfunction revokePendingMarketRemoval(Id id) external onlyCuratorOrGuardianRole {};\n```\n\nRevokes the pending removal of the market defined by `id`.\n\n- Does not revert if there is no pending market removal.\n\n#### Parameters:\n\n| Name | Type                                                 | Description                                         |\n| :--- | :--------------------------------------------------- | :-------------------------------------------------- |\n| `id` | [Id](/get-started/resources/contracts/morpho#market-id) | The id of the market to revoke the pending removal. |\n\n# Errors Codes\n\nBelow is a list of the different **Errors** that can be thrown when executing transactions on Morpho Vaults.\n\n**E.g**: One can try to execute an action on Morpho Vaults' contracts, and get:\n\n```solidity\nreverted with an unrecognized custom error (return data: 0x46fedb57)\n```\n\nAccording to the following tables, this is an error that emitted the **AboveMaxTimelock()** function.\n\n| Custom Error                                    | Error Signature (returned data) |\n| ----------------------------------------------- | ------------------------------- |\n| `AboveMaxTimelock()`                            | 0x46fedb57                      |\n| `AlreadyPending()`                              | 0x49b204ce                      |\n| `AlreadySet()`                                  | 0xa741a045                      |\n| `AllCapsReached()`                              | 0xded0652d                      |\n| `BelowMinTimelock()`                            | 0x342b27be                      |\n| `DuplicateMarket(Id id)`                        | 0x074e4d4b                      |\n| `InconsistentAsset(Id id)`                      | 0xf17887ec                      |\n| `InconsistentReallocation()`                    | 0x9e36b890                      |\n| `InvalidMarketRemovalNonZeroCap(Id id)`         | 0xd2575d1a                      |\n| `InvalidMarketRemovalNonZeroSupply(Id id)`      | 0x6316104f                      |\n| `InvalidMarketRemovalTimelockNotElapsed(Id id)` | 0x813435c5                      |\n| `MarketNotCreated()`                            | 0x96e13529                      |\n| `MarketNotEnabled(Id id)`                       | 0x11b0e0ab                      |\n| `MaxFeeExceeded()`                              | 0xf4df6ae5                      |\n| `MaxQueueLengthExceeded()`                      | 0x80f2f7ae                      |\n| `NonZeroCap()`                                  | 0xc48e3172                      |\n| `NoPendingValue()`                              | 0xe5f408a5                      |\n| `NotAllocatorRole()`                            | 0xf7137c0f                      |\n| `NotCuratorNorGuardianRole()`                   | 0xd080fa31                      |\n| `NotCuratorRole()`                              | 0xca899cec                      |\n| `NotEnoughLiquidity()`                          | 0x4323a555                      |\n| `NotGuardianRole()`                             | 0xf9f2fc9a                      |\n| `PendingCap(Id id)`                             | 0x42288ef1                      |\n| `PendingRemoval()`                              | 0x4bec0146                      |\n| `SupplyCapExceeded(Id id)`                      | 0xd018394f                      |\n| `TimelockNotElapsed()`                          | 0x6677a596                      |\n| `UnauthorizedMarket(Id id)`                     | 0x9cd14834                      |\n| `ZeroAddress()`                                 | 0x867915ab                      |\n| `ZeroFeeRecipient()`                            | 0xcff9f194                      |"
  },
  "/get-started/resources/contracts/morpho/": {
    "title": "Morpho",
    "url": "https://docs.morpho.org/get-started/resources/contracts/morpho/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Morpho\n\n## Code\n\n## Market Parameters\n\n### Market id\n\nThe 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.\n\n```solidity\ntype Id is bytes32;\n```\n\nTo 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.\n\n### Market struct\n\nThe market struct is defined as follows:\n\n```solidity\nstruct Market {\n    uint128 totalSupplyAssets;\n    uint128 totalSupplyShares;\n    uint128 totalBorrowAssets;\n    uint128 totalBorrowShares;\n    uint128 lastUpdate;\n    uint128 fee;\n}\n```\n\nIt contains the state of a market.\n`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.\n\n### MarketParams struct\n\nThe majority of the entrypoints accept a `MarketParams` struct as parameter. This struct is defined as follows:\n\n```solidity\nstruct MarketParams {\n    address loanToken;\n    address collateralToken;\n    address oracle;\n    address irm;\n    uint256 lltv;\n}\n```\n\nAs an integrator, you need to recover these 5 parameters to interact with Morpho.\nYou can also use the [idToMarketParams](#idtomarketparams) view function to recover the parameters of a given market from the bytes32 id.\n\n## Functions\n\n### setOwner\n\n```solidity\n    function setOwner(address newOwner) external;\n```\n\nSets `newOwner` as `owner` of the contract.\n\n- Warning: No two-step transfer ownership.\n- Warning: The owner can be set to the zero address.\n\n#### Parameters:\n\n| Name       | Type    | Description            |\n| :--------- | :------ | :--------------------- |\n| `newOwner` | address | The new owner address. |\n\n### enableIrm\n\n```solidity\n   function enableIrm(address irm) external;\n```\n\nEnables `irm` as a possible IRM for market creation.\n\n- Warning: It is not possible to disable an IRM.\n\n#### Parameters:\n\n| Name  | Type    | Description                |\n| :---- | :------ | :------------------------- |\n| `irm` | address | The irm address to enable. |\n\n### enableLltv\n\n```solidity\n    function enableLltv(uint256 lltv) external;\n```\n\nEnables `lltv` as a possible LLTV for market creation.\n\n- Warning: It is not possible to disable a LLTV.\n\n#### Parameters:\n\n| Name   | Type    | Description                             |\n| :----- | :------ | :-------------------------------------- |\n| `lltv` | uint256 | The lltv value to enable (18 decimals). |\n\n### setFee\n\n```solidity\n    function setFee(MarketParams memory marketParams, uint256 newFee) external;\n```\n\nSets the `newFee` for the given market `marketParams`.\n\n- Warning: The recipient can be the zero address.\n\n#### Parameters:\n\n| Name           | Type                                 | Description            |\n| :------------- | :----------------------------------- | :--------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market parameters. |\n| `newFee`       | uint256                              | The new fee value.     |\n\n### setFeeRecipient\n\n```solidity\n    function setFeeRecipient(address newFeeRecipient) external;\n```\n\nSets `newFeeRecipient` as `feeRecipient` of the fee.\n\n- Warning: If the fee recipient is set to the zero address, fees will accrue there and will be lost.\n- 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.\n\n#### Parameters:\n\n| Name              | Type    | Description                           |\n| :---------------- | :------ | :------------------------------------ |\n| `newFeeRecipient` | address | The address of the new fee recipient. |\n\n### createMarket\n\n```solidity\nfunction createMarket(MarketParams memory marketParams) external;\n```\n\nCreates the market defined by `marketParams`.\n\nHere is the list of assumptions on the market's dependencies (tokens, IRM and oracle) that guarantees\nMorpho behaves as expected:\n\n- The token should be ERC20 compliant, except that it can omit return values on `transfer` and `transferFrom`.\n- The token balance of Morpho should only decrease on `transfer` and `transferFrom`. In particular, tokens with burn functions are not supported.\n- The token should not re-enter Morpho on `transfer` nor `transferFrom`.\n- 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.\n- The IRM should not re-enter Morpho.\n- The oracle should return a price with the correct scaling.\n\nHere is a list of properties on the market's dependencies that could break Morpho's liveness properties:\n\n- The token can revert on `transfer` and `transferFrom` for a reason other than an approval or balance issue.\n- A very high amount of assets (~1e35) supplied or borrowed can make the computation of `toSharesUp` and `toSharesDown` overflow.\n- The IRM can revert on `borrowRate`.\n- A very high borrow rate returned by the IRM can make the computation of `interest` in `_accrueInterest` overflow.\n- 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.\n- 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.\n- 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.\n\n#### Parameters:\n\n| Name           | Type                                 | Description           |\n| :------------- | :----------------------------------- | :-------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market parameters |\n\n### supply\n\n```solidity\nfunction supply(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        bytes memory data\n    ) external returns (uint256 assetsSupplied, uint256 sharesSupplied);\n```\n\nSupplies `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's `onMorphoSupply` function with the given `data`.\n\n- 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.\n\n- Supplying a large amount can revert for overflow.\n- 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.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                                                             |\n| :------------- | :----------------------------------- | :-------------------------------------------------------------------------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to supply assets to.                                                         |\n| `assets`       | uint256                              | The amount of assets to supply.                                                         |\n| `shares`       | uint256                              | The amount of shares to mint.                                                           |\n| `onBehalf`     | address                              | The address that will own the increased supply position.                                |\n| `data`         | bytes                                | Arbitrary data to pass to the `onMorphoSupply` callback. Pass empty data if not needed. |\n\n#### Return Values:\n\n| Name             | Type    | Description                    |\n| :--------------- | :------ | :----------------------------- |\n| `assetsSupplied` | uint256 | The amount of assets supplied. |\n| `sharesSupplied` | uint256 | The amount of shares minted.   |\n\n### withdraw\n\n```solidity\nfunction withdraw(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        address receiver\n    ) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);\n```\n\nWithdraws `assets` or `shares` on behalf of `onBehalf` to `receiver`.\n\n- Either `assets` or `shares` should be zero. To withdraw max, pass the `shares`'s balance of `onBehalf`.\n\n- `msg.sender` must be authorized to manage `onBehalf`'s positions.\n\n- Withdrawing an amount corresponding to more shares than supplied will revert for underflow.\n\n- It is advised to use the `shares` input when withdrawing the full position to avoid reverts due to conversion roundings between `shares` and `assets`.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                         |\n| :------------- | :----------------------------------- | :-------------------------------------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to withdraw assets from.                 |\n| `assets`       | uint256                              | The amount of assets to withdraw.                   |\n| `shares`       | uint256                              | The amount of shares to burn.                       |\n| `onBehalf`     | address                              | The address of the owner of the supply position.    |\n| `receiver`     | address                              | The address that will receive the withdrawn assets. |\n\n#### Return Values:\n\n| Name              | Type    | Description                     |\n| :---------------- | :------ | :------------------------------ |\n| `assetsWithdrawn` | uint256 | The amount of assets withdrawn. |\n| `sharesWithdrawn` | uint256 | The amount of shares burned.    |\n\n### borrow\n\n```solidity\nfunction borrow(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        address receiver\n    ) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed);\n```\n\nBorrows `assets` or `shares` on behalf of `onBehalf` to `receiver`.\n\n- 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.\n\n- `msg.sender` must be authorized to manage `onBehalf`'s positions.\n\n- Borrowing a large amount can revert for overflow.\n\n- Borrowing an amount of shares may lead to borrow fewer assets than expected due to slippage. Consider using the `assets` parameter to avoid this.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                              |\n| :------------- | :----------------------------------- | :------------------------------------------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to borrow assets from.                        |\n| `assets`       | uint256                              | The amount of assets to borrow.                          |\n| `shares`       | uint256                              | The amount of shares to mint.                            |\n| `onBehalf`     | address                              | The address that will own the increased borrow position. |\n| `receiver`     | address                              | The address that will receive the borrowed assets.       |\n\n#### Return Values:\n\n| Name             | Type    | Description                    |\n| :--------------- | :------ | :----------------------------- |\n| `assetsBorrowed` | uint256 | The amount of assets borrowed. |\n| `sharesBorrowed` | uint256 | The amount of shares minted.   |\n\n### repay\n\n```solidity\nfunction repay(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        bytes memory data\n    ) external returns (uint256 assetsRepaid, uint256 sharesRepaid);\n```\n\nRepays `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's `onMorphoRepay` function with the given `data`.\n\n- Either `assets` or `shares` should be zero. To repay max, pass the `shares`'s balance of `onBehalf`.\n\n- Repaying an amount corresponding to more shares than borrowed will revert for underflow.\n\n- It is advised to use the `shares` input when repaying the full position to avoid reverts due to conversion roundings between shares and assets.\n\n- An attacker can front-run a repay with a small repay making the transaction revert for underflow.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                                                                           |\n| :------------- | :----------------------------------- | :---------------------------------------------------------------------------------------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to repay assets from.                                                                      |\n| `assets`       | uint256                              | The amount of assets to repay.                                                                        |\n| `shares`       | uint256                              | The amount of shares to burn.                                                                         |\n| `onBehalf`     | address                              | The address of the owner of the debt position.                                                        |\n| `data`         | bytes                                | Arbitrary data (example `0x`) to pass to the `onMorphoRepay` callback. Pass empty data if not needed. |\n\n#### Return Values:\n\n| Name           | Type    | Description                  |\n| :------------- | :------ | :--------------------------- |\n| `assetsRepaid` | uint256 | The amount of assets repaid. |\n| `sharesRepaid` | uint256 | The amount of shares burned. |\n\n### supplyCollateral\n\n```solidity\nfunction supplyCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, bytes memory data)\n        external;\n```\n\nSupplies `assets` of collateral on behalf of `onBehalf`, optionally calling back the caller's `onMorphoSupplyCollateral` function with the given `data`.\n\n- Interest are not accrued since it's not required and it saves gas.\n\n- Supplying a large amount can revert for overflow.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                                                                       |\n| :------------- | :----------------------------------- | :------------------------------------------------------------------------------------------------ |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to supply collateral to.                                                               |\n| `assets`       | uint256                              | The amount of assets to supply.                                                                   |\n| `onBehalf`     | address                              | The address that will own the increased collateral position.                                      |\n| `data`         | bytes                                | Arbitrary data to pass to the `onMorphoSupplyCollateral` callback. Pass empty data if not needed. |\n\n### withdrawCollateral\n\n```solidity\nfunction withdrawCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, address receiver)\n        external;\n```\n\nWithdraws `assets` of collateral on behalf of `onBehalf` to `receiver`.\n\n- `msg.sender` must be authorized to manage `onBehalf`'s positions.\n\n- Withdrawing an amount corresponding to more collateral than supplied will revert for underflow.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                          |\n| :------------- | :----------------------------------- | :--------------------------------------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to withdraw collateral from.              |\n| `assets`       | uint256                              | The amount of assets to withdraw.                    |\n| `onBehalf`     | address                              | The address that owns the collateral position.       |\n| `receiver`     | address                              | The address that will receive the collateral assets. |\n\n### liquidate\n\n```solidity\nfunction liquidate(\n        MarketParams memory marketParams,\n        address borrower,\n        uint256 seizedAssets,\n        uint256 repaidShares,\n        bytes memory data\n    ) external returns (uint256, uint256);\n```\n\nLiquidates the given `repaidShares` of debt asset or seize the given `seizedAssets` of collateral on the\ngiven market `marketParams` of the given `borrower`'s position, optionally calling back the caller's\n`onMorphoLiquidate` function with the given `data`.\n\n- Either `seizedAssets` or `repaidShares` should be zero.\n\n- Seizing more than the collateral balance will underflow and revert without any error message.\n\n- Repaying more than the borrow balance will underflow and revert without any error message.\n\n- An attacker can front-run a liquidation with a small repay making the transaction revert for underflow.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                                                                |\n| :------------- | :----------------------------------- | :----------------------------------------------------------------------------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market of the position.                                                                |\n| `borrower`     | address                              | The owner of the position.                                                                 |\n| `seizedAssets` | uint256                              | The amount of collateral to seize.                                                         |\n| `repaidShares` | uint256                              | The amount of shares to repay.                                                             |\n| `data`         | bytes                                | Arbitrary data to pass to the `onMorphoLiquidate` callback. Pass empty data if not needed. |\n\n#### Return Values:\n\n| Name           | Type    | Description                  |\n| :------------- | :------ | :--------------------------- |\n| `assetsSeized` | uint256 | The amount of assets seized. |\n| `assetsRepaid` | uint256 | The amount of assets repaid. |\n\n### flashLoan\n\n```solidity\nfunction flashLoan(address token, uint256 assets, bytes calldata data) external;\n```\n\nExecutes a flash loan.\n\n- Flash loans have access to the whole balance of the contract (the liquidity and deposited collateral of all markets combined, plus donations).\n- Warning: Not ERC-3156 compliant but compatibility is easily reached:\n  a. `flashFee` is zero.\n  b. `maxFlashLoan` is the token's balance of this contract.\n  c. The receiver of `assets` is the caller.\n\n#### Parameters:\n\n| Name     | Type    | Description                                                 |\n| :------- | :------ | :---------------------------------------------------------- |\n| `token`  | address | The token to flash loan.                                    |\n| `assets` | uint256 | The amount of assets to flash loan.                         |\n| `data`   | bytes   | Arbitrary data to pass to the `onMorphoFlashLoan` callback. |\n\n### setAuthorization\n\n```solidity\nfunction setAuthorization(address authorized, bool newIsAuthorized) external;\n```\n\nSets the authorization for `authorized` to manage `msg.sender`'s positions.\n\n#### Parameters:\n\n| Name              | Type    | Description                   |\n| :---------------- | :------ | :---------------------------- |\n| `authorized`      | address | The authorized address.       |\n| `newIsAuthorized` | bool    | The new authorization status. |\n\n### setAuthorizationWithSig\n\n```solidity\n\nstruct Authorization {\n    address authorizer;\n    address authorized;\n    bool isAuthorized;\n    uint256 nonce;\n    uint256 deadline;\n}\n\nstruct Signature {\n    uint8 v;\n    bytes32 r;\n    bytes32 s;\n}\n\nfunction setAuthorizationWithSig(Authorization calldata authorization, Signature calldata signature) external;\n```\n\nSets the authorization for `authorization.authorized` to manage `authorization.authorizer`'s positions.\n\n- Warning: Reverts if the signature has already been submitted.\n\n- The signature is malleable, but it has no impact on the security here.\n\n- The nonce is passed as argument to be able to revert with a different error message.\n\nWhile both functions achieve the same outcome (managing operator permissions), they serve different use cases:\n\n- **`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.\n- **`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.\n\n#### Authorization struct\n\n| Name           | Type    | Description                                        |\n| :------------- | :------ | :------------------------------------------------- |\n| `authorizer`   | address | The address authorizing the authorization.         |\n| `authorized`   | address | The address to authorize.                          |\n| `isAuthorized` | bool    | The new authorization status.                      |\n| `nonce`        | uint256 | The nonce of the authorizer.                       |\n| `deadline`     | uint256 | The deadline after which the signature is invalid. |\n\n#### Parameters:\n\n| Name            | Type                                   | Description                |\n| :-------------- | :------------------------------------- | :------------------------- |\n| `authorization` | [Authorization](#authorization-struct) | The authorization to set.  |\n| `signature`     | Signature                              | The signature to validate. |\n\n### accrueInterest\n\n```solidity\nfunction accrueInterest(MarketParams memory marketParams) external;\n```\n\nAccrues interest for the given market `marketParams`.\n\n#### Parameters:\n\n| Name           | Type                                 | Description            |\n| :------------- | :----------------------------------- | :--------------------- |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market parameters. |\n\n## Views Functions\n\n### DOMAIN_SEPARATOR\n\n```solidity\nfunction DOMAIN_SEPARATOR() external view returns (bytes32);\n```\n\nThe EIP-712 domain separator.\n\n- 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.\n\n#### Return Values:\n\n| Type    | Description                   |\n| :------ | :---------------------------- |\n| bytes32 | The EIP-712 domain separator. |\n\n### owner\n\n```solidity\n    function owner() external view returns (address);\n```\n\nThe owner of the contract.\n\n- It has the power to change the owner.\n- It has the power to set fees on markets and set the fee recipient.\n- It has the power to enable but not disable IRMs and LLTVs.\n\n#### Return Values:\n\n| Type    | Description                |\n| :------ | :------------------------- |\n| address | The owner of the contract. |\n\n### feeRecipient\n\n```solidity\n    function feeRecipient() external view returns (address);\n```\n\nThe fee recipient of all markets.\n\n- The recipient receives the fees of a given market through a supply position on that market.\n\n#### Return Values:\n\n| Type    | Description                |\n| :------ | :------------------------- |\n| address | The fee recipient address. |\n\n### isIrmEnabled\n\n```solidity\n    function isIrmEnabled(address irm) external view returns (bool);\n```\n\nWhether the `irm` is enabled.\n\n#### Parameters:\n\n| Name  | Type    | Description      |\n| :---- | :------ | :--------------- |\n| `irm` | address | The irm address. |\n\n#### Return Values:\n\n| Type | Description                                                    |\n| :--- | :------------------------------------------------------------- |\n| bool | Boolean equals to `true` if irm is enabled, `false` otherwise. |\n\n### isLltvEnabled\n\n```solidity\n    function isLltvEnabled(uint256 lltv) external view returns (bool);\n```\n\nWhether the `lltv` is enabled.\n\n#### Parameters:\n\n| Name   | Type    | Description       |\n| :----- | :------ | :---------------- |\n| `lltv` | address | The lltv address. |\n\n#### Return Values:\n\n| Type | Description                                                     |\n| :--- | :-------------------------------------------------------------- |\n| bool | Boolean equals to `true` if lltv is enabled, `false` otherwise. |\n\n### isAuthorized\n\n```solidity\n    function isAuthorized(address authorizer, address authorized) external view returns (bool);\n```\n\nWhether `authorized` is authorized to modify `authorizer`'s position on all markets.\n\n- Anyone is authorized to modify their own positions, regardless of this variable.\n\n#### Parameters:\n\n| Name         | Type    | Description             |\n| :----------- | :------ | :---------------------- |\n| `authorizer` | address | The authorizer address. |\n| `authorized` | address | The authorized address. |\n\n#### Return Values:\n\n| Type | Description                                                                                                          |\n| :--- | :------------------------------------------------------------------------------------------------------------------- |\n| bool | Boolean equals to `true` if `authorized` address is authorized to modify `authorizer`'s position, `false` otherwise. |\n\n### nonce\n\n```solidity\n    function nonce(address authorizer) external view returns (uint256);\n```\n\nThe `authorizer`'s current nonce. Used to prevent replay attacks with EIP-712 signatures.\n\n#### Parameters:\n\n| Name         | Type    | Description             |\n| :----------- | :------ | :---------------------- |\n| `authorizer` | address | The authorizer address. |\n\n#### Return Values:\n\n| Type    | Description              |\n| :------ | :----------------------- |\n| uint256 | The current nonce value. |\n\n### extSloads\n\n```solidity\nfunction extSloads(bytes32[] memory slots) external view returns (bytes32[] memory);\n```\n\nReturns the data stored on the different `slots`.\n\n#### Parameters:\n\n| Name    | Type      | Description                                          |\n| :------ | :-------- | :--------------------------------------------------- |\n| `slots` | bytes32[] | The array of slots to retrieve the data stored into. |\n\n#### Return Values:\n\n| Type      | Description      |\n| :-------- | :--------------- |\n| bytes32[] | The data stored. |\n\n### idToMarketParams\n\n```solidity\nfunction idToMarketParams(Id id)\n        external\n        view\n        returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv);\n```\n\nThe market params corresponding to `id`.\n\n- 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`.\n\n#### Parameters:\n\n| Name | Type | Description   |\n| :--- | :--- | :------------ |\n| `id` | Id   | The market id |\n\n#### Return Values:\n\n| Name              | Type    | Description                         |\n| :---------------- | :------ | :---------------------------------- |\n| `loanToken`       | address | The loan token of the market.       |\n| `collateralToken` | address | The collateral token of the market. |\n| `oracle`          | address | The oracle of the market.           |\n| `irm`             | address | The IRM of the market.              |\n| `lltv`            | uint256 | The LLTV of the market.             |\n\n### market\n\n```solidity\nfunction market(Id id)\n        external\n        view\n        returns (\n            uint128 totalSupplyAssets,\n            uint128 totalSupplyShares,\n            uint128 totalBorrowAssets,\n            uint128 totalBorrowShares,\n            uint128 lastUpdate,\n            uint128 fee\n        );\n```\n\nThe market state corresponding to `id`.\n\n- Interest are not accrued, and assets values are not updated. Their values are the one at the last update.\n\n- One can use the [MorphoBalancesLib](#morphobalanceslib) to accrue interests\n\n#### Parameters:\n\n| Name | Type | Description   |\n| :--- | :--- | :------------ |\n| `id` | Id   | The market id |\n\n#### Return Values:\n\n| Name                | Type    | Description                              |\n| :------------------ | :------ | :--------------------------------------- |\n| `totalSupplyAssets` | uint128 | The total supply assets of the market.   |\n| `totalSupplyShares` | uint128 | The total supply shares of the market.   |\n| `totalBorrowAssets` | uint128 | The total borrow assets of the market.   |\n| `totalBorrowShares` | uint128 | The total borrow shares of the market.   |\n| `lastUpdate`        | uint128 | The last update timestamp of the market. |\n| `fee`               | uint128 | The fee of the market.                   |\n\n### position\n\n```solidity\nfunction position(Id id, address user)\n        external\n        view\n        returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral);\n```\n\nThe state of the position of `user` on the market corresponding to `id`.\n\n#### Parameters:\n\n| Name   | Type    | Description       |\n| :----- | :------ | :---------------- |\n| `id`   | Id      | The market id.    |\n| `user` | address | The user address. |\n\n#### Return Values:\n\n| Name           | Type    | Description                                                |\n| :------------- | :------ | :--------------------------------------------------------- |\n| `supplyShares` | uint256 | The total supply shares of the user on a given market.     |\n| `borrowShares` | uint128 | The total borrow shares of the user on a given market.     |\n| `collateral`   | uint128 | The total collateral assets of the user on a given market. |\n\n## MorphoBalancesLib\n\nThe MorphoBalancesLib is a library that allows you to accrue interest and\n  update the assets values of a market. You can easily retrieve market amounts\n  and user balances with interests.\n\n> The Github code is available [**here**](https://github.com/morpho-org/morpho-blue/blob/be2306afd655232d2cf16547c18be0077014bae0/src/libraries/periphery/MorphoBalancesLib.sol)\n\n### expectedMarketBalances\n\n```solidity\nfunction expectedMarketBalances(IMorpho morpho, MarketParams memory marketParams)\n        internal\n        view\n        returns (\n            uint256 totalSupplyAssets,\n            uint256 totalSupplyShares,\n            uint256 totalBorrowAssets,\n            uint256 totalBorrowShares\n            );\n```\n\nReturns the expected market balances of a market after having accrued interests, defined in [Market](#market-struct).\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                          |\n| :------------- | :----------------------------------- | :--------------------------------------------------- |\n| `morpho`       | IMorpho                              | The Morpho contract (injected when used as library). |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected balances from.        |\n\n#### Return Values:\n\n| Name                | Type    | Description                                                     |\n| :------------------ | :------ | :-------------------------------------------------------------- |\n| `totalSupplyAssets` | uint256 | The total supply assets of the market (with interests accrued). |\n| `totalSupplyShares` | uint256 | The total supply shares of the market.                          |\n| `totalBorrowAssets` | uint256 | The total borrow assets of the market (with interests accrued). |\n| `totalBorrowShares` | uint256 | The total borrow shares of the market.                          |\n\n### expectedTotalSupplyAssets\n\n```solidity\nfunction expectedTotalSupplyAssets(IMorpho morpho, MarketParams memory marketParams)\n        internal\n        view\n        returns (uint256 totalSupplyAssets);\n```\n\nReturns the expected total supply assets of a market after having accrued interests.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                          |\n| :------------- | :----------------------------------- | :--------------------------------------------------- |\n| `morpho`       | IMorpho                              | The Morpho contract (injected when used as library). |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected total supply from.    |\n\n#### Return Values:\n\n| Name                | Type    | Description                                                     |\n| :------------------ | :------ | :-------------------------------------------------------------- |\n| `totalSupplyAssets` | uint256 | The total supply assets of the market (with interests accrued). |\n\n### expectedTotalBorrowAssets\n\n```solidity\nfunction expectedTotalBorrowAssets(IMorpho morpho, MarketParams memory marketParams)\n        internal\n        view\n        returns (uint256 totalBorrowAssets);\n```\n\nReturns the expected total borrow assets of a market after having accrued interests.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                          |\n| :------------- | :----------------------------------- | :--------------------------------------------------- |\n| `morpho`       | IMorpho                              | The Morpho contract (injected when used as library). |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected total borrow from.    |\n\n#### Return Values:\n\n| Name                | Type    | Description                                                     |\n| :------------------ | :------ | :-------------------------------------------------------------- |\n| `totalBorrowAssets` | uint256 | The total borrow assets of the market (with interests accrued). |\n\n### expectedTotalSupplyShares\n\n```solidity\nfunction expectedTotalSupplyShares(IMorpho morpho, MarketParams memory marketParams)\n        internal\n        view\n        returns (uint256 totalSupplyShares);\n```\n\nReturns the expected total supply shares of a market after having accrued interests.\n\n- It can grow only if fees > 0\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                          |\n| :------------- | :----------------------------------- | :--------------------------------------------------- |\n| `morpho`       | IMorpho                              | The Morpho contract (injected when used as library). |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected total supply from.    |\n\n#### Return Values:\n\n| Name                | Type    | Description                                                     |\n| :------------------ | :------ | :-------------------------------------------------------------- |\n| `totalSupplyShares` | uint256 | The total supply shares of the market (with interests accrued). |\n\n### expectedSupplyAssets\n\n```solidity\nfunction expectedSupplyAssets(IMorpho morpho, MarketParams memory marketParams, address user)\n        internal\n        view\n        returns (uint256)\n```\n\nReturns the expected supply assets of a user on a market after having accrued interests.\n\n- Warning: Wrong for `feeRecipient` because their supply shares increase is not taken into account.\n\n- Warning: Withdrawing using the expected supply assets can lead to a revert due to conversion roundings from assets to shares.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                          |\n| :------------- | :----------------------------------- | :--------------------------------------------------- |\n| `morpho`       | IMorpho                              | The Morpho contract (injected when used as library). |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected supply assets from.   |\n| `user`         | address                              | The user to get the expected supply assets from.     |\n\n#### Return Values:\n\n| Name           | Type    | Description                                             |\n| :------------- | :------ | :------------------------------------------------------ |\n| `supplyAssets` | uint256 | The supply assets of the user (with interests accrued). |\n\n### expectedBorrowAssets\n\n```solidity\nfunction expectedBorrowAssets(IMorpho morpho, MarketParams memory marketParams, address user)\n        internal\n        view\n        returns (uint256)\n```\n\nReturns the expected borrow assets of a user on a market after having accrued interests.\n\n- Warning: The expected balance is rounded up, so it may be greater than the market's expected total borrow\n  assets.\n\n#### Parameters:\n\n| Name           | Type                                 | Description                                          |\n| :------------- | :----------------------------------- | :--------------------------------------------------- |\n| `morpho`       | IMorpho                              | The Morpho contract (injected when used as library). |\n| `marketParams` | [MarketParams](#marketparams-struct) | The market to get the expected borrow assets from.   |\n| `user`         | address                              | The user to get the expected borrow assets from.     |\n\n#### Return Values:\n\n| Name            | Type    | Description                                             |\n| :-------------- | :------ | :------------------------------------------------------ |\n| `borrowBalance` | uint256 | The borrow assets of the user (with interests accrued). |\n\n## Errors Codes\n\nThe 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).\n\nBelow is the list of the different **Errors** that can be thrown, along with their explanations:\n\n| Errors Message (returned data) | Error Natspec                                                                   |\n| ------------------------------ | ------------------------------------------------------------------------------- |\n| \"already set\"                  | Thrown when the value is already set.                                           |\n| \"healthy position\"             | Thrown when the position to liquidate is healthy.                               |\n| \"inconsistent input\"           | Thrown when not exactly one of the input amount is zero.                        |\n| \"insufficient collateral\"      | Thrown when the collateral is insufficient to `borrow` or `withdrawCollateral`. |\n| \"insufficient liquidity\"       | Thrown when the liquidity is insufficient to `withdraw` or `borrow`.            |\n| \"invalid nonce\"                | Thrown when the nonce is invalid.                                               |\n| \"invalid signature\"            | Thrown when the authorization signature is invalid.                             |\n| \"irm not enabled\"              | Thrown when the IRM is not enabled at market creation.                          |\n| \"lltv not enabled\"             | Thrown when the LLTV is not enabled at market creation.                         |\n| \"market already created\"       | Thrown when the market is already created.                                      |\n| \"market not created\"           | Thrown when the market is not created.                                          |\n| \"max fee exceeded\"             | Thrown when the fee to set exceeds the maximum fee.                             |\n| \"max lltv exceeded\"            | Thrown when the LLTV to enable exceeds the maximum LLTV.                        |\n| \"max uint128 exceeded\"         | Thrown when the maximum uint128 is exceeded.                                    |\n| \"no code\"                      | Thrown when a token to transfer doesn't have code.                              |\n| \"not owner\"                    | Thrown when the caller is not the owner.                                        |\n| \"signature expired\"            | Thrown when the authorization signature is expired.                             |\n| \"transfer from reverted\"       | Thrown when a token transferFrom reverted.                                      |\n| \"transfer from returned false\" | Thrown when a token transferFrom returned false.                                |\n| \"transfer returned false\"      | Thrown when a token transfer returned false.                                    |\n| \"transfer reverted\"            | Thrown when a token transfer reverted.                                          |\n| \"unauthorized\"                 | Thrown when the caller is not authorized to conduct an action.                  |\n| \"zero address\"                 | Thrown when a zero address is passed as input.                                  |\n| \"zero assets\"                  | Thrown when zero assets is passed as input.                                     |"
  },
  "/get-started/resources/contracts/oracles/": {
    "title": "Oracles",
    "url": "https://docs.morpho.org/get-started/resources/contracts/oracles/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Oracles\n\n## Code\n\n## Basics\n\nOracles 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).\n\nThey return the price of 1 asset of collateral token quoted in 1 asset of loan token.\n\n## price\n\n```solidity\nfunction price() external view returns (uint256);\n```\n\nReturns the price of 1 asset of collateral token quoted in 1 asset of loan token, scaled by 1e36.\n\n- 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.\n\n### Return values:\n\n| Name    | Type    | Description                                                                                     |\n| :------ | :------ | :---------------------------------------------------------------------------------------------- |\n| `price` | uint256 | The price rate of 1 asset of collateral token quoted in 1 asset of loan token (scaled by 1e36). |\n\n## MorphoChainlinkOracleV2\n\nThis is an oracle that uses Chainlink-interface-compliant feeds to provide price data.\n\nThis oracle handles the following cases among others (let's say that our pair is A/B):\n\n- A/B is a feed (typically, stETH/ETH).\n- B/A is a feed (typically, ETH/USDC).\n- A/C and B/C are feeds (typically, stETH/ETH and USDC/ETH).\n- A/C, C/D and B/D are feeds (typically, WBTC/BTC, BTC/USD, USDC/USD).\n- A/D, and B/C, C/D are feeds (typically, USDC/USD, WBTC/BTC, BTC/USD).\n- A/C, C/D and B/E, E/D are feeds.\n- A/C and C/B are feeds (typically, WBTC/BTC and BTC/ETH).\n- A'/C and B/C are feeds, and there is an exchange rate between A and A'. (typically A=sDAI and A'=DAI).\n\n## WstETH/stETH Exchange Rate Adapter\n\nA specific implementation, the `WstEthStEthExchangeRateChainlinkAdapter`, provides the exchange rate between wstETH and stETH as a Chainlink-interface-compliant feed.\n\nThis adapter is deployed on Ethereum Mainnet at the address [0x905b7dAbCD3Ce6B792D874e303D336424Cdb1421](https://etherscan.io/address/0x905b7dabcd3ce6b792d874e303d336424cdb1421#code).\n\n## MorphoChainlinkOracleV2Factory\n\nThis factory deploys `MorphoChainlinkOracleV2` instances.\n\nThe 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.\n\n## Implementation\n\n> [Morpho Chainlink Oracle V2 Github repository](https://github.com/morpho-org/morpho-blue-oracles/tree/main/src/morpho-chainlink)\n\nThe contract implements the [Oracle interface](https://github.com/morpho-org/morpho-blue/blob/main/src/interfaces/IOracle.sol) to fit Morpho specifications:\n\n## Immutables\n\n- `BASE_VAULT`: baseVault. Pass address zero to omit this parameter.\n- `BASE_VAULT_CONVERSION_SAMPLE`: Base vault conversion sample.\n- `BASE_FEED_1`: First base feed. Pass address zero if the price = 1.\n- `BASE_FEED_2`: Second base feed. Pass address zero if the price = 1.\n- `BASE_TOKEN_DECIMALS`: Base token decimals.\n- `QUOTE_VAULT`: Quote vault. Pass address zero to omit this parameter.\n- `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.\n- `QUOTE_FEED_1`: First quote feed. Pass address zero if the price = 1.\n- `QUOTE_FEED_2`: Second quote feed. Pass address zero if the price = 1.\n- `QUOTE_TOKEN_DECIMALS`: Quote token decimals.\n\n## Assumptions\n\nHere is the list of assumptions that guarantees the oracle behaves as expected:\n\n- The vaults, if set, are ERC4626-compliant.\n- The feeds, if set, are Chainlink-interface-compliant.\n- Decimals passed as argument are correct.\n- The base vaults's sample shares quoted as assets and the base feed prices don't overflow when multiplied.\n- The quote vault's sample shares quoted as assets and the quote feed prices don't overflow when multiplied."
  },
  "/get-started/resources/contracts/public-allocator/": {
    "title": "Public Allocator",
    "url": "https://docs.morpho.org/get-started/resources/contracts/public-allocator/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Public Allocator\n\n## Code\n\n## Overview\n\nThe `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.\n\n**Fee Collection**\nThe 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.\n\n## Constants\n\n### MAX_SETTABLE_FLOW_CAP\n\nThe 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`.\n\n## Structs\n\n### FlowCaps\n\nThe `FlowCaps` struct is defined as follows:\n\n```solidity\nstruct FlowCaps {\n    uint128 maxIn;\n    uint128 maxOut;\n}\n```\n\nIt contains the maximum allowed inflow and outflow for a market.\n\n### FlowCapsConfig\n\nThe `FlowCapsConfig` struct is defined as follows:\n\n```solidity\nstruct FlowCapsConfig {\n    Id id;\n    FlowCaps caps;\n}\n```\n\nIt is used to configure the flow caps for a market.\n\n### Withdrawal\n\nThe `Withdrawal` struct is defined as follows:\n\n```solidity\nstruct Withdrawal {\n    MarketParams marketParams;\n    uint128 amount;\n}\n```\n\nIt specifies the market and the amount to withdraw.\n\n## Functions\n\n### setAdmin\n\n```solidity\nfunction setAdmin(address vault, address newAdmin) external;\n```\n\nSets `newAdmin` as the admin for the specified vault.\n\n#### Parameters:\n\n| Name       | Type    | Description               |\n| :--------- | :------ | :------------------------ |\n| `vault`    | address | The address of the vault. |\n| `newAdmin` | address | The new admin address.    |\n\n### setFee\n\n```solidity\nfunction setFee(address vault, uint256 newFee) external;\n```\n\nSets the `newFee` for the specified vault.\n\n#### Parameters:\n\n| Name     | Type    | Description               |\n| :------- | :------ | :------------------------ |\n| `vault`  | address | The address of the vault. |\n| `newFee` | uint256 | The new fee value.        |\n\n### setFlowCaps\n\n```solidity\nfunction setFlowCaps(address vault, FlowCapsConfig[] calldata config) external;\n```\n\nSets the maximum inflow and outflow for the specified markets in the given vault.\n\n#### Parameters:\n\n| Name     | Type                      | Description                        |\n| :------- | :------------------------ | :--------------------------------- |\n| `vault`  | address                   | The address of the vault.          |\n| `config` | FlowCapsConfig[] calldata | The flow caps configuration array. |\n\n### transferFee\n\n```solidity\nfunction transferFee(address vault, address payable feeRecipient) external;\n```\n\nTransfers the accrued fee to the specified recipient for the given vault.\n\n#### Parameters:\n\n| Name           | Type    | Description                   |\n| :------------- | :------ | :---------------------------- |\n| `vault`        | address | The address of the vault.     |\n| `feeRecipient` | address | The address of the recipient. |\n\n### reallocateTo\n\n```solidity\nfunction reallocateTo(\n    address vault,\n    Withdrawal[] calldata withdrawals,\n    MarketParams calldata supplyMarketParams\n) external payable;\n```\n\nReallocates assets from a list of markets to one market in the specified vault.\n\n#### Parameters:\n\n| Name                 | Type                  | Description                                              |\n| :------------------- | :-------------------- | :------------------------------------------------------- |\n| `vault`              | address               | The address of the vault.                                |\n| `withdrawals`        | Withdrawal[] calldata | The markets and amounts to withdraw.                     |\n| `supplyMarketParams` | MarketParams calldata | The market to which total withdrawn assets are supplied. |\n\n## Events\n\n### PublicWithdrawal\n\n```solidity\nevent PublicWithdrawal(address indexed sender, address indexed vault, Id indexed id, uint256 withdrawnAssets);\n```\n\nEmitted during a public reallocation for each withdrawn-from market.\n\n### PublicReallocateTo\n\n```solidity\nevent PublicReallocateTo(address indexed sender, address indexed vault, Id indexed supplyMarketId, uint256 suppliedAssets);\n```\n\nEmitted at the end of a public reallocation.\n\n### SetAdmin\n\n```solidity\nevent SetAdmin(address indexed sender, address indexed vault, address admin);\n```\n\nEmitted when the admin is set for a vault.\n\n### SetFee\n\n```solidity\nevent SetFee(address indexed sender, address indexed vault, uint256 fee);\n```\n\nEmitted when the fee is set for a vault.\n\n### TransferFee\n\n```solidity\nevent TransferFee(address indexed sender, address indexed vault, uint256 amount, address indexed feeRecipient);\n```\n\nEmitted when the fee is transferred for a vault.\n\n### SetFlowCaps\n\n```solidity\nevent SetFlowCaps(address indexed sender, address indexed vault, FlowCapsConfig[] config);\n```\n\nEmitted when the flow caps are set for a vault.\n\n## Error Handling\n\n### ErrorsLib\n\nThe `ErrorsLib` library defines various error messages used by the `PublicAllocator` contract.\n\n- `NotAdminNorVaultOwner()`: Thrown when the caller is not the admin nor the owner of the vault.\n- `IncorrectFee()`: Thrown when the reallocation fee given is wrong.\n- `AlreadySet()`: Thrown when the value is already set.\n- `EmptyWithdrawals()`: Thrown when `withdrawals` is empty.\n- `InconsistentWithdrawals()`: Thrown when `withdrawals` contains a duplicate or is not sorted.\n- `DepositMarketInWithdrawals()`: Thrown when the deposit market is in `withdrawals`.\n- `MarketNotEnabled(Id id)`: Thrown when attempting to reallocate or set flows to non-zero values for a non-enabled market.\n- `WithdrawZero(Id id)`: Thrown when attempting to withdraw zero of a market.\n- `MaxSettableFlowCapExceeded()`: Thrown when attempting to set max inflow/outflow above the `MAX_SETTABLE_FLOW_CAP`.\n- `NotEnoughSupply(Id id)`: Thrown when attempting to withdraw more than the available supply of a market.\n- `MaxOutflowExceeded(Id id)`: Thrown when attempting to withdraw more than the max outflow of a market.\n- `MaxInflowExceeded(Id id)`: Thrown when attempting to supply more than the max inflow of a market.\n\n## Interfaces\n\n### IPublicAllocatorBase\n\nDefines the basic interface for the `PublicAllocator`.\n\n### IPublicAllocatorStaticTyping\n\nInherits from `IPublicAllocatorBase` and includes a function to get flow caps.\n\n### IPublicAllocator\n\nThe primary interface for the `PublicAllocator`.\n\n## Conclusion\n\nThe `PublicAllocator` contract is a crucial component for managing asset reallocations within Morpho Vaults, ensuring efficient liquidity management while adhering to set flow caps."
  },
  "/get-started/resources/contracts/rewards/": {
    "title": "Universal Rewards Distributors",
    "url": "https://docs.morpho.org/get-started/resources/contracts/rewards/",
    "section": "Get Started",
    "content": "[← Back to contracts](/get-started/resources/contracts/)\n\n# Universal Rewards Distributors\n\n## Code\n\n## Contract Overview\n\nThe [`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.\n\nThe 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.\n\n## Functions\n\n### submitRoot\n\n```solidity\nfunction submitRoot(bytes32 newRoot, bytes32 newIpfsHash) external onlyUpdaterRole;\n```\n\nSubmits a new merkle root for the distribution of rewards.\n\n- Can only be called by an address with updater role.\n- Emits a `PendingRootSet` event.\n\n#### Parameters:\n\n| Name          | Type    | Description                                                |\n| :------------ | :------ | :--------------------------------------------------------- |\n| `newRoot`     | bytes32 | The new merkle root.                                       |\n| `newIpfsHash` | bytes32 | The optional ipfs hash containing metadata about the root. |\n\n### acceptRoot\n\n```solidity\nfunction acceptRoot() external;\n```\n\nAccepts and sets the current pending merkle root after the timelock has expired.\n\n- Can be called by any address.\n- Reverts if no pending root is set or if the timelock has not expired.\n- Emits a `RootSet` event upon successful execution.\n\n### revokePendingRoot\n\n```solidity\nfunction revokePendingRoot() external onlyUpdaterRole;\n```\n\nRevokes the current pending merkle root.\n\n- Can only be called by an address with updater role.\n- Reverts if no pending root is set.\n- Emits a `PendingRootRevoked` event.\n\n### claim\n\n```solidity\nfunction claim(address account, address reward, uint256 claimable, bytes32[] calldata proof) external returns (uint256 amount);\n```\n\nClaims rewards for a specific account.\n\n- Reverts if the root is not set, if the proof is invalid, or if the claimable amount is less than the amount already claimed.\n- Emits a `Claimed` event upon successful execution.\n\n#### Parameters:\n\n| Name        | Type      | Description                                    |\n| :---------- | :-------- | :--------------------------------------------- |\n| `account`   | address   | The address to claim rewards for.              |\n| `reward`    | address   | The address of the reward token.               |\n| `claimable` | uint256   | The overall claimable amount of token rewards. |\n| `proof`     | bytes32[] | The merkle proof that validates this claim.    |\n\n#### Return values:\n\n| Name     | Type    | Description                         |\n| :------- | :------ | :---------------------------------- |\n| `amount` | uint256 | The amount of reward token claimed. |\n\n### setRoot\n\n```solidity\nfunction setRoot(bytes32 newRoot, bytes32 newIpfsHash) external onlyUpdaterRole;\n```\n\nForces update of the distribution's merkle root, bypassing the timelock.\n\n- Can only be called by the owner of the distribution or by updaters if there is no timelock.\n- Reverts if the new root is the same as the current root and if the caller is unauthorized to change the root.\n- Emits a `RootSet` event upon successful execution.\n\n#### Parameters:\n\n| Name          | Type    | Description                                                |\n| :------------ | :------ | :--------------------------------------------------------- |\n| `newRoot`     | bytes32 | The new merkle root.                                       |\n| `newIpfsHash` | bytes32 | The optional ipfs hash containing metadata about the root. |\n\n### setTimelock\n\n```solidity\nfunction setTimelock(uint256 newTimelock) external onlyOwner;\n```\n\nSets a new timelock for the distribution.\n\n- Can only be called by the owner of the distribution.\n- Reverts if the new timelock is the same as the current timelock.\n- Emits a `TimelockSet` event upon successful execution.\n\n#### Parameters:\n\n| Name          | Type    | Description       |\n| :------------ | :------ | :---------------- |\n| `newTimelock` | uint256 | The new timelock. |\n\n### setRootUpdater\n\n```solidity\nfunction setRootUpdater(address updater, bool active) external onlyOwner;\n```\n\nSets or unsets an address as a root updater.\n\n#### Parameters:\n\n| Name      | Type    | Description                                       |\n| :-------- | :------ | :------------------------------------------------ |\n| `updater` | address | The address of the root updater.                  |\n| `active`  | bool    | Whether the root updater should be active or not. |\n\n- Can only be called by the owner of the distribution.\n- Reverts if the updater status is already set as specified.\n- Emits a `RootUpdaterSet` event upon successful execution.\n\n### setOwner\n\n```solidity\nfunction setOwner(address newOwner) external onlyOwner;\n```\n\nTransfers ownership of the distribution to a new address.\n\n- Can only be called by the current owner.\n- Reverts if the new owner is the same as the current owner.\n- Emits an `OwnerSet` event upon successful execution.\n\n#### Parameters:\n\n| Name       | Type    | Description                   |\n| :--------- | :------ | :---------------------------- |\n| `newOwner` | address | The address of the new owner. |\n\n## Events\n\nThe contract emits events to signify important actions and state changes. Here are the events associated with the `UniversalRewardsDistributor` contract:\n\n- `PendingRootSet`: Emitted when a new pending root is submitted.\n- `PendingRootRevoked`: Emitted when a pending root is revoked.\n- `RootSet`: Emitted when a new root is accepted and set.\n- `Claimed`: Emitted when rewards are successfully claimed.\n- `RootUpdaterSet`: Emitted when a root updater's status is changed.\n- `OwnerSet`: Emitted when a new owner is set for the distribution.\n- `TimelockSet`: Emitted when the timelock is updated.\n\n## Roles\n\nThere are only 2 roles:\n\n- **Owner**: owner of the contract that has access to the updater's functions and [`setTimelock`](#settimelock), [`setRootUpdater`](#setrootupdater), and [`setOwner`](#setowner) functions.\n- **Updater**: addresses that can trigger the [`submitRoot`](#submitroot), [`setRoot`](#setroot), and [`revokePendingRoot`](#revokependingroot) functions."
  },
  "/get-started/resources/disclaimer/": {
    "title": "Legal Disclaimer",
    "url": "https://docs.morpho.org/get-started/resources/disclaimer/",
    "section": "Get Started",
    "content": "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.\n\nMorpho 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.\n\nTo 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.\n\nUsers 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."
  },
  "/learn/": {
    "title": "Morpho Overview",
    "url": "https://docs.morpho.org/learn/",
    "section": "Learn",
    "content": "## Introduction\n\n**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.\n\n- **The Morpho Protocol**:  \n  A decentralized, noncustodial lending protocol implemented for the Ethereum Virtual Machine.\n\n- **The Morpho Interfaces**:  \n  Multiple web interfaces allowing easy interaction with the Morpho protocol. Those interfaces are ways to interact with the Morpho protocol.\n\n- **Morpho Governance**:  \n  A governance system for governing the Morpho Protocol, enabled by the [MORPHO token](/learn/governance/morpho-token/#1).\n\n- **Morpho Association**:  \n  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.\n\n## Morpho\n\nMorpho is a simple lending primitive layer that allows the creation of immutable and efficient lending markets in a permissionless way.\n\nThe protocol comes with EVM smart contracts which facilitate interactions and integrations.\n\n### Overview\n\nMorpho 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.\n\nMorpho 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.\n\n### Key Concepts\n\nOvercollateralized lending in Morpho involves:\n\n- **Collateralization**: Users provide collateral to borrow other assets\n- **Risk Protection**: Liquidation mechanisms protect the protocol through loan-to-value ratios\n- **Interest Accrual**: Dynamic interest rates based on market conditions\n- **Open Participation**: Anyone can lend or borrow through the protocol\n- **Non-custodial Design**: Users maintain ownership of their assets at all times"
  },
  "/learn/concepts/bundlers/": {
    "title": "Morpho Bundlers",
    "url": "https://docs.morpho.org/learn/concepts/bundlers/",
    "section": "Learn",
    "content": "  \n\n## What are Bundlers?\n\nBundlers 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.\n\nBundler3 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).\n\n## What Bundler3 Allows You To Do\n\nWith Bundler3, you can:\n\n1. **Streamline Complex Workflows** - Complete lending, borrowing, swapping, and more in one transaction\n2. **Save on Gas Fees** - Pay for one transaction instead of many\n3. **Avoid Failed Transactions** - If any part of your operation would fail, the entire transaction reverts safely\n4. **Perform Advanced Operations** - Combine actions that normally require multiple steps.\n\n## Practical Examples:\n\n- **One-Click Leverage**: Convert ETH to wstETH, deposit as collateral, and borrow USDC—all in one transaction\n- **Instant Refinancing**: Borrow from one market, repay another, and adjust collateral positions simultaneously\n- **Portfolio Rebalancing**: Withdraw, swap, and redeposit assets across multiple markets without waiting for confirmations"
  },
  "/learn/concepts/curator/": {
    "title": "Curator",
    "url": "https://docs.morpho.org/learn/concepts/curator/",
    "section": "Learn",
    "content": "  \n\nA **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.\n\nCurators 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.\n\n## The Curator's Responsibilities\n\nA 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:\n\n-   **Strategic Curation**: Defining the vault's overall investment thesis. This includes selecting which protocols, markets, or asset types are permissible for allocation.\n-   **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.\n-   **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.\n-   **Setting Core Vault Mechanics**: In Vault V2, the Curator also controls crucial mechanisms like fees and compliance gating.\n\nCrucially, 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.\n\n## The Curator's Toolkit: V1 vs. V2\n\nThe tools available to a Curator have significantly expanded with Vaults V2, enabling far more sophisticated and granular risk curation.\n\n| Feature / Tool         | **In Morpho Vault V1**                                                                      | **In Morpho Vault V2**                                                                                                                                                                                                                         |\n| :--------------------- | :------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **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... ).                                                                                                   |\n| **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\"). |\n| **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.                                                                                             |\n| **Fee Structure**      | N/A. Fees were managed by the `Owner`.                                                      | Sets the **performance and management fees** and their respective recipients.                                                                                                                                                                  |\n| **Compliance**         | Not natively supported.                                                                     | Can implement onchain compliance by setting **Gate Contracts** to control deposits, withdrawals, and share transfers.                                                                                                                          |\n\n## Curation within the Vault Role System\n\nThe Curator role is designed to be distinct from other vault management functions, creating a clear separation of duties.\n\n-   The **Owner** is the ultimate authority, with the power to appoint the `Curator` and `Sentinels`. The Owner's role is primarily administrative.\n-   The **Curator** defines the *strategy* and *risk boundaries*. They decide **what** is possible within the vault (which protocols, what max exposure).\n-   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.\n-   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.\n\nThis structure ensures that strategic risk curation is separate from daily portfolio management (Allocation), leading to a more robust and secure system."
  },
  "/learn/concepts/flashloans/": {
    "title": "Flash Loans",
    "url": "https://docs.morpho.org/learn/concepts/flashloans/",
    "section": "Learn",
    "content": "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.\n\n## What Are Flash Loans in Morpho?\n\nMorpho's flash loans are similar to other DeFi protocols where these:\n\n- Allow borrowing without prior collateral\n- Require repayment within the same transaction\n- Execute in a single block\n- Are primarily meant for developers and advanced users\n\n## How Morpho Flash Loans Work\n\nThe core flash loan functionality is implemented through the `flashLoan` function in the Morpho contract with a corresponding callback mechanism.\n\n### The Flash Loan Flow in Morpho\n\n1. **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)\n2. **Asset Transfer**: Morpho transfers the requested token amount to the calling contract\n3. **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)\n4. **Execution of Logic**: The user's contract executes its intended operations\n5. **Repayment**: The user's contract must approve Morpho to pull back the borrowed amount\n6. **Completion**: Morpho pulls the funds back from the caller contract\n\nIf at any point the flow fails (especially if the repayment fails), the entire transaction reverts.\n\n## Implementing a Flash Loan in Morpho\n\nTo use a flash loan with Morpho, you need to:\n\n1. Create a contract that implements the `IMorphoFlashLoanCallback` interface\n2. Implement the `onMorphoFlashLoan` function that will handle your logic\n3. Ensure your callback function approves the Morpho contract to pull back the borrowed amount\n\n## Flash Loan Use Cases with Morpho\n\n1. **Arbitrage**: Execute trades across different protocols to profit from price discrepancies\n2. **Collateral Swaps**: Replace one collateral type with another in a single transaction\n3. **Self-Liquidation**: Liquidate your own position to avoid liquidation penalties\n4. **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\n5. **Flash Actions**: Combine multiple Morpho operations in a single transaction\n\n## Security Considerations for Morpho Flash Loans\n\n1. **Transaction Atomicity**: If your callback fails to approve the repayment, the entire transaction will revert\n2. **Contract Security**: Never leave funds in your flash loan contract permanently\n3. **Reentrancy**: Be careful about calling external contracts within your flash loan logic\n4. **Gas Management**: Flash loans are complex operations that consume significant gas\n\n## Example Implementation\n\nThe [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:\n\n```solidity\n// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"./interfaces/IERC20.sol\";\nimport {IMorpho} from \"../interfaces/IMorpho.sol\";\nimport {IMorphoFlashLoanCallback} from \"../interfaces/IMorphoCallbacks.sol\";\n\ncontract FlashBorrowerMock is IMorphoFlashLoanCallback {\n    IMorpho private immutable MORPHO;\n\n    constructor(IMorpho newMorpho) {\n        MORPHO = newMorpho;\n    }\n\n    function flashLoan(address token, uint256 assets, bytes calldata data) external {\n        MORPHO.flashLoan(token, assets, data);\n    }\n\n    function onMorphoFlashLoan(uint256 assets, bytes calldata data) external {\n        require(msg.sender == address(MORPHO));\n        address token = abi.decode(data, (address));\n        IERC20(token).approve(address(MORPHO), assets);\n\n        // Add your logic here.\n        // e.g. swap, liquidate, leverage, and much more...\n    }\n}\n```\n\nThis minimal implementation demonstrates the key components:\n\n- **Constructor**: Stores the Morpho contract address\n- **flashLoan function**: External entry point that initiates the flash loan\n- **onMorphoFlashLoan callback**: Implements the required callback interface where you add your custom logic (arbitrage, swaps, leverage, etc.)\n- **Security check**: Verifies the caller is the Morpho contract\n- **Repayment approval**: Approves Morpho to pull back the borrowed assets\n\n## Morpho-Specific Callbacks\n\nMorpho implements a broader callback system:\n\n- `IMorphoLiquidateCallback`: For liquidation operations\n- `IMorphoRepayCallback`: For repayment operations\n- `IMorphoSupplyCallback`: For supply operations\n- `IMorphoSupplyCollateralCallback`: For supplying collateral\n\nThis 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.\n\nhttps://dune.com/morpho/morpho-blue-dashboard#flashloans"
  },
  "/learn/concepts/irm/": {
    "title": "Interest Rate Model",
    "url": "https://docs.morpho.org/learn/concepts/irm/",
    "section": "Learn",
    "content": "  \n\nMorpho 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.\n\nThe only IRM that has been governance-approved is the [AdaptiveCurveIRM](#the-adaptivecurveirm), which is described in more detail later in this page.\n\n## Understanding Borrow and Supply APY\n\nThe **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:\n\n- **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.\n\n- **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).\n\n### How Are These APYs Calculated?\n\n#### Borrow APY Calculation\n\nThe Borrow APY is obtained by compounding the per-second borrow rate over the entire year. The formula is:\n\n```math\n\\text{borrowAPY} = \\left(e^{\\left(\\text{borrowRate} \\times \\text{secondsPerYear}\\right)} - 1\\right)\n```\n\nHere, `borrowRate` is the rate provided by the IRM and `secondsPerYear` equals 31,536,000.\n\n#### Supply APY Calculation\n\nThe Supply APY is obtained by adjusting the Borrow APY like this:\n\n```math\n\\text{supplyAPY} = \\text{borrowAPY} \\times \\text{utilization} \\times (1 - \\text{fee})\n```\n\nWhere:\n\n- **Utilization:** Is the ratio of the total borrowed assets to the total supplied assets.\n- **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))\n\nBelow is a basic typescript snippet showcasing the rate calculus with a rate returned by the IRM of `1512768697`\n\n```typescript\n/**\n * Calculate borrow APY using the exponential formula: exp(rate * seconds) - 1\n * Where:\n * - rate is the interest rate per second (in Wei with 18 decimals)\n * - seconds is the number of seconds (typically for a year: 31536000)\n *\n * @param ratePerSecond Interest rate per second in Wei (18 decimals)\n * @param seconds Number of seconds (typically a year: 31536000)\n * @returns The borrow APY as a decimal (e.g., 0.0489 for 4.89%)\n */\nfunction calculateBorrowRate(ratePerSecond: string, seconds: number): number {\n  // Convert rate to a number with 18 decimal precision\n  const rate = Number(ratePerSecond) / 1e18;\n\n  // Calculate exp(rate * seconds) - 1\n  const result = Math.exp(rate * seconds) - 1;\n\n  return result;\n}\n\n/**\n * Calculate supply APY based on borrow APY, utilization, and fee\n * Formula: supplyAPY = borrowAPY * utilization * (1 - fee)\n *\n * @param borrowAPY The calculated borrow APY as a decimal (e.g., 0.0489 for 4.89%)\n * @param utilization The utilization rate as a decimal (e.g., 0.8 for 80%)\n * @param fee The fee rate in Wei (18 decimals, e.g., \"0\" for no fee)\n * @returns The supply APY as a decimal (e.g., 0.0416 for 4.16%)\n */\nfunction calculateSupplyAPY(\n  borrowAPY: number,\n  utilization: number,\n  fee: string\n): number {\n  // Convert fee from Wei to decimal (1e18 denominator)\n  const feeRate = Number(fee) / 1e18;\n\n  // Calculate supply APY using the formula: borrowAPY * utilization * (1 - fee)\n  return borrowAPY * utilization * (1 - feeRate);\n}\n\n// Shared example values\nconst secondsInYear = 31536000;\nconst ratePerSecond = \"1512768697\"; // Rate per second in Wei (18 decimals)\nconst utilization = 0.85; // 85% utilization\nconst fee = \"0\"; // No fee (0 in Wei / 18 decimals)\n\n// Calculate borrow APY\nconst borrowAPY = calculateBorrowRate(ratePerSecond, secondsInYear);\n\n// Calculate supply APY\nconst supplyAPY = calculateSupplyAPY(borrowAPY, utilization, fee);\n\n// Display results\nconsole.log(`Borrow APY: ${(borrowAPY * 100).toFixed(2)}%`);\nconsole.log(\n  `Supply APY: ${(supplyAPY * 100).toFixed(2)}% at ${(\n    utilization * 100\n  ).toFixed(0)}% utilization with ${(Number(fee) / 1e18) * 100}% fee`\n);\n```\n\nThe output here is:\n\n```\nBorrow APY: 4.89%\nSupply APY: 4.15% at 85% utilization with 0% fee\n```\n\n### Resources\n\nFor a deeper dive into the mechanics and the code behind these calculations, refer to the following resources:\n\n- [**Interest Rate Model Repository**](https://github.com/morpho-org/morpho-blue-irm): Explore the implementation and the smart contracts that power the IRM.\n- [**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.\n- [**Introducing the AdaptiveCurveIRM**](https://morpho.org/blog/introducing-the-adaptivecurveirm-efficient-and-autonomous/) article\n\nThis 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.\n\nInitially, this set is composed of one immutable IRM, the AdaptiveCurveIRM.\n\n## The AdaptiveCurveIRM\n\n### Overview\n\nThe AdaptiveCurveIRM is engineered to maintain the ratio of borrowed assets over supplied assets, commonly called utilization, close to a target of 90%.\n\nIn 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.\n\nAs 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.\n\nIts adaptability enables it to perform effectively across any asset, market, and condition, making it highly suitable for Morpho's permissionless market creation.\n\n### How It Works\n\nThe model can be broken down into two complementary mechanisms:\n\n1.  **The Curve Mechanism**\n    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.\n\n    \n      \n    \n\n```math\nr_{90\\%}\n```\n\nis the target rate at utilization target\n\n```math\nu_{target}=0.9\n```\n\nExample with the interest rate currently at 4% at\n\n```math\nu_{target}=0.9\n```\n\n    - If utilization rate goes to 100% following a market event, the interest rate will instantly go to 16% in this example (x4)\n\n    - 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)\n\n2.  **The Adaptive Mechanism**\n    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:\n\n    - When utilization exceeds the target, the curve continuously shifts upward. This incentivizes loan repayment and thus decreases utilization.\n    - When utilization falls below the target, the curve continuously shifts downward. This incentivizes borrowing and thus increases utilization.\n\n    \n      \n    \n\n    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.\n    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.\n\nSome examples are given below about the target\n\n```math\nr_{90\\%}\n```\n\n    - If the utilization remains at 45%, it will progressively decrease until it is divided by 2 after 10 days.\n    - If the utilization remains at 95%, it will progressively increase until it doubles after 10 days.\n    - 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.\n\nHere's a video showing how the two mechanisms combine to adjust interest rates:\n\nFor more on the AdaptiveCurveIRM, explore the [technical reference](/get-started/resources/contracts/irm)."
  },
  "/learn/concepts/liquidation/": {
    "title": "Liquidation on Morpho",
    "url": "https://docs.morpho.org/learn/concepts/liquidation/",
    "section": "Learn",
    "content": "  \n\n## Overview\n\nLiquidation is a critical mechanism in the Morpho protocol that protects lenders' capital by ensuring borrowers maintain healthy collateral positions. Morpho offers two liquidation approaches:\n\n1. **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.\n\n2. **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.\n\n## Understanding Loan-To-Value (LTV)\n\nBefore exploring the liquidation mechanisms, it's essential to understand how LTV is calculated and what it represents.\n\n### How to Calculate LTV\n\nThe 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:\n\n```math\n\\text{LTV} = \\frac{\\text{BORROWED\\_AMOUNT}}{\\text{COLLATERAL\\_VALUE\\_IN\\_LOAN\\_TOKEN}} \\times 100\\%\n```\n\nWhere:\n\n- **`BORROWED_AMOUNT`**: The amount of borrowed assets of the user (in token base units)\n- **`COLLATERAL_VALUE_IN_LOAN_TOKEN`**: The value of the collateral in terms of the loan token\n\nThe collateral value in loan token units is calculated as:\n\n```math\n\\text{COLLATERAL\\_VALUE\\_IN\\_LOAN\\_TOKEN} = \\frac{\\text{COLLATERAL\\_AMOUNT } \\times \\text{ ORACLE\\_PRICE}}{\\text{ORACLE\\_PRICE\\_SCALE}}\n```\n\nWhere:\n\n- **`COLLATERAL_AMOUNT`**: The amount of collateral assets provided by the user (in token base units)\n- **`ORACLE_PRICE`**: The oracle price returned by the oracle of the market (scaled by ORACLE_PRICE_SCALE)\n- **`ORACLE_PRICE_SCALE`**: A scaling factor of 10^36 used by the protocol for price normalization\n\n### Health Factor\n\nThe Health Factor is another crucial metric that indicates how close a position is to liquidation:\n\n```math\n\\text{HEALTH\\_FACTOR} = \\frac{\\text{COLLATERAL\\_VALUE\\_IN\\_LOAN\\_TOKEN} \\times \\text{LLTV}}{\\text{BORROWED\\_AMOUNT}}\n```\n\nWhere:\n\n- **`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)\n\nA position is healthy when the Health Factor is greater than 1.0. When it falls below 1.0, the position becomes eligible for liquidation.\n\n- For oracle implementation details, see the [dedicated oracle section](/learn/concepts/oracle/)\n- WAD represents a common scaling factor in DeFi of 10^18 used for representing decimal numbers in integer arithmetic\n\nLet's walk through a concrete example of calculating LTV and Health Factor for a position on Morpho:\n\n**Given values (with assumptions):**\n\n- Borrowed amount: 150,000 USDC (150,000,000,000 base units with 6 decimals)\n- Collateral amount: 2 cbBTC (200,000,000 base units with 8 decimals)\n- 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\n- Oracle price scale: 10^36\n- LLTV: 86% (expressed as 0.86 × 10^18 or 860,000,000,000,000,000 in WAD units)\n\n#### Calculate the collateral value in loan token units\n\n```typescript\n// All calculations use BigInt (suffixed with 'n') to handle large numbers precisely\nconst collateralValueInLoanToken =\n  (collateralAmount * oraclePrice) / ORACLE_PRICE_SCALE;\n// = (200,000,000n * 1,000,000,000,000,000,000,000,000,000,000,000,000,000n) / 10n**36n\n// = 200,000,000,000 base units of loan token (USDC)\n```\n\n#### Calculate the current LTV\n\n```typescript\n// Constants\nconst WAD = 10n ** 18n; // Standard scaling factor (10^18)\n\n// Example values\nconst borrowedAmount = 150_000_000_000n; // 150 billion units (e.g., USDC with 6 decimals)\nconst collateralValueInLoanToken = 200_000_000_000n; // 200 billion units\n\n/**\n * Current LTV Calculation\n * ----------------------\n *\n * Step 1: Calculate the raw LTV ratio, preserving precision with WAD\n */\nconst currentLTV = (borrowedAmount * WAD) / collateralValueInLoanToken;\n// = (150,000,000,000n * 10n**18n) / 200,000,000,000n\n// = 750,000,000,000,000,000n (scaled by WAD, representing 0.75 or 75%)\n\n/**\n * Option 1: Theoretical Formula\n * ----------------------------\n * In theory, the conversion to percentage is simply:\n */\n// Theoretical formula (doesn't work directly with BigInt)\n// currentLTVPercentage = (currentLTV / WAD) * 100\n\n// Implementation of theoretical formula (using Number conversion)\nconst theoreticalLTVPercentage = (Number(currentLTV) / Number(WAD)) * 100;\n// = 75.0000%\n\n/**\n * Option 2: Practical Display Implementation\n * ----------------------------------------\n * For precise display with 4 decimal places, we:\n * 1. Scale up by the display factor (percentage * decimal precision)\n * 2. Divide by WAD to normalize\n * 3. Convert to Number and adjust for decimal places\n */\n// Scale factor = 100 (for percentage) * 10000 (for 4 decimal places) = 1,000,000\nconst displayScaleFactor = 1_000_000n;\nconst currentLTVPercentageScaled = (currentLTV * displayScaleFactor) / WAD;\n// = 750_000n (represents 75.0000%)\n\n// Convert the scaled BigInt result to a human-readable number\nconst displayLTVPercentage = Number(currentLTVPercentageScaled) / 10000;\n// = 75.0000% (when displayed with 4 decimal places)\n```\n\n#### Calculate the health factor\n\n```typescript\n// Since LLTV is stored as a WAD, we need to account for scaling\nconst healthFactor = (collateralValueInLoanToken * lltv) / borrowedAmount;\n// = (200,000,000,000,000n * 860,000,000,000,000,000n) / 150,000,000,000n\n// = 1,146,666,666,666,666,666 (scaled by WAD)\n\n// Convert to decimal\nconst healthFactorDisplay = Number(healthFactor) / Number(WAD);\n// = 1.1467 (when converted to a human-readable decimal)\n```\n\nSince the Health Factor is greater than 1.0 (1.1467), this position is healthy and has a safety margin before liquidation could occur.\n\n#### Summary of Position:\n\n- Current LTV: 75.00%\n- Max LTV (LLTV): 86.00%\n- Health Factor: 1.1467\n- Status: Healthy\n- Liquidation Buffer: 11.00% (difference between current LTV and max LTV)\n\nThis 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.\n\n- For oracle implementation details, see the [dedicated oracle section](/learn/concepts/oracle/)\n- 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)\n\n## Standard Liquidation\n\nThe standard liquidation mechanism is the primary defense against borrower defaults and is built directly into the Morpho core contracts.\n\n### When Is a Position Liquidatable?\n\nA position becomes liquidatable when its LTV exceeds the market's Liquidation Loan-To-Value (LLTV) which can happen due to:\n\n- Collateral value decreasing\n- Debt increasing due to accrued interest\n- A combination of both factors\n\n**Example**\nIf a borrower provides $100 of collateral in a market with an LLTV of 86%:\n\n- The position is safe when borrowed value ≤ $86\n- The position becomes liquidatable when borrowed value > $86 (LTV > 86%)\n\n### How Standard Liquidation Works\n\nWhen 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.\n\n#### Liquidation Incentive Factor (LIF)\n\nThe liquidation bonus is determined by the Liquidation Incentive Factor (LIF), which depends on the market's LLTV:\n\n```math\n\\text{LIF} = \\min(M, \\frac{1}{\\beta*\\text{LLTV}+(1-\\beta)}), \\text{ with } \\beta = 0.3 \\text{ and } M= 1.15.\n```\n\n  \n  \n    Liquidation Incentive Factor in relation to the Liquidation Loan-To-Value\n\n- The entire LIF goes to the liquidator; Morpho protocol doesn't take a fee\n- For an 86% LLTV market, the LIF is approximately 1.05 (5% bonus)\n\n### Standard Liquidation Step-by-Step\n\n#### Initial Position\n\nA 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.\n\n- Position status: LTV = 86.01% > LLTV (86%) → **Liquidatable**\n\n#### Liquidation Process\n\n- Liquidator identifies the unhealthy position\n- Liquidator repays the $86.01k debt\n- LIF calculation: 1.05 (for 86% LLTV market)\n- Seized collateral: $86.01k × 1.05 = $90.31k\n\n#### After Liquidation\n\n- Borrower: Debt cleared, retains $9.69k of collateral\n- Liquidator: Spent $86.01k, received $90.31k in collateral\n- Profit for liquidator: $4.3k minus gas fees and any swap costs\n\n#### Practical Consideration\n\nFor this liquidation to be profitable, the liquidator must ensure:\n$4.3k > (Gas fees + potential swap fees + potential price slippage costs)\n\n### Key Features of Standard Liquidation\n\n- **Liquidation Amount**: Liquidators can repay up to 100% of the borrower's debt in a single transaction\n- **Trigger**: Only activates when LTV > LLTV\n- **Incentive**: Fixed LIF based on the market's LLTV\n- **Borrower Impact**: Potentially significant one-time liquidation\n- **Implementation**: Built into the Morpho core contract\n\n## Pre-Liquidation\n\nThe pre-liquidation mechanism, also called Auto-Deleverage, is an optional, opt-in feature that provides a safety buffer between healthy positions and standard liquidation.\n\n### What Is Pre-Liquidation (also known as Auto-Deleverage)\n\nPre-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.\n\nIf a borrower provides $100 of collateral in a market with LLTV = 80% and preLLTV = 75%:\n\n- The position is safe when LTV ≤ 75%\n- The position is pre-liquidatable when 75% < LTV < 80%\n- The position is fully liquidatable (following the standard liquidation process) when LTV > 80%\n\n### How Pre-Liquidation Parameters Work\n\nPre-liquidation operates with 6 key parameters:\n\n#### Pre-Liquidation Loan-To-Value (preLLTV)\n\nThe threshold at which pre-liquidation becomes possible\n\n#### Pre-Liquidation Close Factors (preLCF₁ & preLCF₂)\n\nThe 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:\n\n```math\npreLCF = \\frac{LLTV - LTV}{LLTV - preLLTV} * preLCF_1 + \\frac{LTV - preLLTV}{LLTV - preLLTV} * preLCF_2\n```\n\n#### Pre-Liquidation Incentive Factors (preLIF₁ & preLIF₂)\n\nThe bonus received by pre-liquidators, which can scale linearly between preLIF₁ and preLIF₂ based on position health.\n\n#### Pre-Liquidation Oracle (PRE_LIQUIDATION_ORACLE)\n\nThe oracle used to assess whether or not a position can be preliquidated.\nIt could be the same oracle of the market, or another oracle.\n\n### Pre-Liquidation Step-by-Step\n\nLet's walk through an example of how pre-liquidation works in practice:\n\n#### Step-by-Step Process\n\n##### Case 1: Pre-Liquidation\n\n#### Initial Position Setup\n\nAlice deposits 1 WBTC as collateral valued at 100k USDC and borrows 70k USDC.  \nHer initial LTV is calculated as:\n\n```math\nLTV = 70,000 / 100,000 = 0.70  \\quad (70\\%)\n```\n\n#### Subscription to Pre-Liquidation\n\nAlice opts into the pre-liquidation feature. Her position is set to be pre-liquidated when her LTV exceeds the preLLTV threshold of approximately 83%.\n\n#### Market Price Movement to Pre-Liquidation Range\n\nWhen the price of 1 WBTC falls to 84k USDC, the new collateral value becomes 84k USDC.  \nHer LTV then becomes:\n\n```math\nLTV = 70,000 / 84,000 \\approx 0.83  \\quad (83\\%)\n```\n\nAt 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.\n\n#### Price Drops Further and Pre-Liquidation Becomes Profitable\n\nThe market continues to move and 1 WBTC reaches 83k USDC, so the collateral value now is 83k USDC.  \nHer updated LTV is:\n\n```math\nLTV = 70,000 / 83,000 \\approx 0.84  \\quad (84\\%)\n```\n\nNow the position is clearly in the pre-liquidation range. Under these conditions, the pre-liquidation close factor is recalculated using the formula:\n\n```math\npreLCF = \\frac{LLTV - LTV}{LLTV - preLLTV} \\times preLCF_1 + \\frac{LTV - preLLTV}{LLTV - preLLTV} \\times preLCF_2 \\approx 0.12\n```\n\nUnder some assumptions, this means that approximately 12% of the debt becomes eligible for liquidation.\n\n#### Executing the Pre-Liquidation\n\nA liquidator repays 12% of Alice’s outstanding debt:\n\n```math\nDebt\\ Repaid = 0.12 \\times 70,000 = 8,400 \\, \\text{USDC}\n```\n\nWith a pre-liquidation incentive factor (preLIF) of roughly 1.04, the seized collateral is calculated as:\n\n```math\nCollateral\\ Seized = 8,400 \\times 1.04 \\approx 8,736 \\, \\text{USDC} \\quad (\\approx 8.7k \\, \\text{USDC})\n```\n\nAfter 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%.\n\n-------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |\n| **Trigger Point**             | LTV climbs to ≈84% (with preLLTV at 83%)                                                      | LTV reaches 86% (LLTV threshold)                              |\n| **Liquidated Debt Portion**   | Partial: 12% of the debt (8.4k USDC)                                                          | Full: 100% of the debt (70k USDC)                             |\n| **Liquidation Incentive**     | PreLIF ≈ 1.04 (4% bonus)                                                                      | Standard LIF ≈ 1.05 (5% bonus)                                |\n| **Collateral Seized**         | ≈8.7k USDC worth for the liquidated portion                                                   | ≈73.5k USDC worth of collateral seized total                  |\n| **Post-Liquidation Position** | Position remains open; new debt ~61.6k USDC with ~74.3k USDC collateral; LTV restored to ≈83% | Position is fully closed                                      |\n| **Borrower’s Loss**           | Approximately $300 loss during partial liquidation                                            | Higher loss; approximately $3.5k incurred at full liquidation |\n| **Potential Future Outcome**  | If price recovers, Alice’s position may improve                                               | No recovery as the position is closed                         |\n\n## Comparing Liquidation Mechanisms\n\n| Aspect            | Pre-Liquidation                                        | Standard Liquidation    |\n| ----------------- | ------------------------------------------------------ | ----------------------- |\n| Trigger Threshold | preLLTV ≤ LTV < LLTV                                   | LTV ≥ LLTV              |\n| Position Closure  | Limited by preLCF (typically less than 50% at preLLTV) | Up to 100% of debt      |\n| Incentive         | Can be dynamic, typically lower than LIF               | Fixed LIF               |\n| Borrower Impact   | Smaller, incremental losses                            | Full one-time loss      |\n| Position After    | Partially deleveraged, returns to healthier LTV        | Usually fully closed    |\n| Implementation    | Opt-in via PreLiquidation contract                     | Built into Morpho core  |\n| Oracle            | Market oracle or specialized oracle                    | Market oracle           |\n| Opt-in Required   | Yes (additional protection)                            | No (default protection) |\n\n## Bad Debt Consideration\n\nMorpho has different mechanisms for accounting for bad debts depending on the vault version.\n\n### Morpho Vaults V2 - Loss Socialization\n\nMorpho 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.\n\n#### How It Works\n\n1. **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.\n\n2. **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.\n\n 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.   \n\n#### Important Considerations\n\n- **Management fee** continue to accrue even during loss periods.\n- **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.\n- **Flash loan protection:** The vault includes safeguards against share price manipulation around loss realization events, as losses are only accounted for once per transaction.\n\n### Morpho Vaults V1.0 - Bad Debt Realization\n\nThe 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.\n\nTypically, 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.\n\nMorpho 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.\n\nAs bad debt is realized at the time it occurs, a market can be used in perpetuity.\n\n### Morpho Vaults V1.1 - No Bad Debt Realization\n\nThe 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.\n\n## Liquidation FAQ\n\n#### At what price are liquidations done?\n\nLiquidations 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.\n\n#### What happens if the collateral price continues to fall?\n\nIf the collateral price continues to fall after a position becomes liquidatable:\n\n- The position becomes increasingly attractive for liquidators as they can seize a larger percentage of the collateral relative to its real market value\n- Liquidators are incentivized to act quickly to capture this value\n- The protocol's design encourages prompt liquidations to minimize systemic risk\n- There is no price floor - the position remains liquidatable until someone repays the debt\n\n#### What happens if the price recovers before liquidation happens?\n\nIf the collateral price recovers sufficiently before liquidation occurs:\n\n- The position's LTV may drop below the LLTV threshold\n- The position will no longer be liquidatable\n- The borrower retains their full collateral and remains responsible for their debt\n- This scenario highlights why borrowers should maintain a safety buffer below the LLTV\n\n#### How do competing liquidators interact? Is it first-come-first-served?\n\nYes, liquidations operate on a first-come-first-served basis:\n\n- The first transaction that successfully executes the liquidation claims the opportunity\n- There is no auction or bidding mechanism\n- In competitive environments, this can lead to MEV (Maximal Extractable Value) opportunities and potential gas price wars\n- Advanced liquidators may use flashbots or other private transaction methods to secure their liquidation\n\n#### Is there partial liquidation?\n\nYes. 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.\n\n#### How are liquidations guaranteed for assets like cbBTC/stETH?\n\nLiquidations 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.\n\nFor 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.\n\n#### Who are the liquidators and what tools do they use?\n\nLiquidators 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.\n\nAt 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.\n\nSome 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.\n\n## Pre-Liquidation FAQ\n\n#### Do I need to enable pre-liquidation manually?\n\nYes, pre-liquidation is an opt-in feature. Borrowers must explicitly authorize it and set their preferred parameters.\n\n#### How much capital can pre-liquidation save?\n\nThe capital savings depend on several factors including market volatility and pre-liquidation parameters.\n\n#### Can anyone perform pre-liquidations?\n\nYes, 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.\n\n#### How are pre-liquidation parameters determined?\n\nPre-liquidation parameters are fully customizable within their respective range. They should be determined using formulas that optimize for:\n\n- Creating a sufficient cushion zone between preLLTV and LLTV\n- Minimizing borrower losses while maintaining liquidator incentives\n- Ensuring the position returns to a healthy state after pre-liquidation\n\n#### What happens if no one pre-liquidates my position?\n\nIf no pre-liquidation occurs and your position's LTV reaches the LLTV, it becomes eligible for standard liquidation, which may result in higher losses.\n\n## Liquidation Tools\n\nSome community members have contributed and provided liquidation bots that could be deployed to liquidate positions.\n\n- 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.\n- Users are advised to conduct their own research and exercise caution when applying any strategies or methods described herein.\n\nIf you are comfortable with these conditions, you can explore the liquidation community section [here](/tools/community/liquidations/)\n\n---\n\nBy understanding both standard liquidation and pre-liquidation mechanisms, users can better manage their risk on Morpho and protect their positions from adverse market movements."
  },
  "/learn/concepts/market/": {
    "title": "Morpho Market V1",
    "url": "https://docs.morpho.org/learn/concepts/market/",
    "section": "Learn",
    "content": "  \n\n## What is a Morpho Market (V1)?\n\nA 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.\nCreating a Morpho Market is **permissionless**.\n\n## Key Features\n\n- **Simple Structure**: One collateral asset, one loan asset per market\n- **Permanent Parameters**: Once created, rules never change\n- **Isolated Risk**: Each market operates independently\n- **Permission-less**: New market doesn’t require governance vote to be created - more [here](/learn/concepts/market/#permissionless-market-creation)\n- **Transparent Rules**: Clear conditions for lending and borrowing\n\n## Market Identification\n\nMarkets follow this naming format:\n\n`CollateralAsset/LoanAsset (LLTV%, OracleAddress, IRMAddress)`\n\nFor example: `wstETH/WETH (94.5%, ChainlinkOracleV2-wstETHToWETH, AdaptiveCurveIRM)`\n\n## The Five Parameters\n\n1. **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`.)\n2. **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).\n3. **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.\n4. **Oracle**: Smart contract address pricing the collateral against the loan asset.\n5. **IRM (Interest Rate Model)**: Smart contract address containing the formula for determining interest rate paid by borrowers.\n\n## Governance-Approved LLTV & IRM\n\n### LLTVs\n\n| LLTV (%) | Solidity Values (scaled by 1e18) |\n| -------- | -------------------------------- |\n| 0        | 0                                |\n| 38.5     | 385000000000000000               |\n| 62.5     | 625000000000000000               |\n| 77.0     | 770000000000000000               |\n| 86.0     | 860000000000000000               |\n| 91.5     | 915000000000000000               |\n| 94.5     | 945000000000000000               |\n| 96.5     | 965000000000000000               |\n| 98.0     | 980000000000000000               |\n\n### IRM\n\nThe only Interest Rate Model (IRM) that has been governance-approved is the\n[AdaptiveCurveIRM](/learn/concepts/irm/).\n\n## Market ID Generator\n\nUse this tool to generate a unique market ID from your market parameters:\n\n## Permissionless market creation\n\nA distinctive feature of Morpho is permissionless market creation: the protocol allows users to create isolated markets consisting of the five aforementioned parameters.\n\nThis a departure from the existing paradigm and traditional lending platforms which:\n\n1. Require governance approval for asset listing and parameter changes.\n2. Pool assets into a single lending pool, sharing risk across the entire protocol.\n\nIn 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.\n\n## Core Interactions\n\n-   **Supply**: Lenders deposit loan assets into a specific market to earn interest.\n-   **Borrow**: Borrowers supply collateral to the same market and borrow loan assets against it, up to the LLTV limit.\n-   **Withdraw**: Lenders can withdraw their supplied assets and accrued interest, provided there is enough liquidity in the market.\n-   **Repay**: Borrowers can repay their loan to reclaim their collateral.\n-   **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."
  },
  "/learn/concepts/oracle/": {
    "title": "Oracle",
    "url": "https://docs.morpho.org/learn/concepts/oracle/",
    "section": "Learn",
    "content": "  \n\n## What is an Oracle?\n\nOracles 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?”\n\n## Oracles in Lending Markets\n\nTraditional lending protocols rely on oracles to:\n\n- Determine the value of collateral assets\n- Calculate borrowing capacity\n- Trigger liquidations when positions become undercollateralized\n- Enable accurate interest rate calculations\n\n## Oracle Implementation in Morpho\n\nMorpho 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.\n\nAll oracles used in Morpho markets implement the `IOracle` [interface](/get-started/resources/contracts/oracles#price), which has a single, standardized function:\n\n```solidity\nfunction price() external view returns (uint256);\n```\n\nThis 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.\n\n## Types of Oracles Compatible with Morpho\n\nVarious oracle implementations can be used with Morpho markets:\n\n1. **Price Feed Oracles**: Utilize external price feeds (like Chainlink, Redstone, API3, Pyth, Chronicle) to calculate asset exchange rates.\n2. **Exchange Rate Oracles**: Specialized for wrapped tokens or rebasing tokens where the exchange rate is deterministic (like wstETH/stETH).\n3. **Fixed-Price Oracles**: Used for assets with known or predefined exchange rates, such as stablecoins pegged to the same value.\n\n## MorphoChainlinkOracleV2: A Reference Implementation\n\nOne reference implementation available is `MorphoChainlinkOracleV2`, which leverages Chainlink-compliant price feeds while supporting multiple routing configurations:\n\n- Direct feeds (e.g., stETH/ETH)\n- Inverse feeds (e.g., ETH/USDC → USDC/ETH)\n- Multiple feed routes (e.g., stETH/USD and USDC/USD)\n- Complex routing with multiple hops\n\nThis implementation demonstrates the flexibility of the oracle system within Morpho, allowing markets to maintain accurate pricing even when direct price feeds aren't available.\n\n## Deploy an Oracle\n\nPlease refer to this section of the documentation to deploy a new oracle:\n[Deploy an Oracle](/curate/tutorials-market-v1/deploying-oracle/)\n\n## Key Oracle Characteristics in Morpho Markets\n\n- **Purpose-Built**: Each oracle returns the specific exchange rate between a collateral asset and a loan asset\n- **Immutable**: Once a market is deployed, its oracle address cannot be modified\n- **Independent**: Each oracle operates autonomously and can use different pricing sources\n- **Flexible Implementation**: Curators can leverage various data sources while maintaining a consistent interface\n\n## Oracle Selection by Market Curators\n\nMarket curators (not Morpho) are responsible for selecting and implementing appropriate oracles for their markets. Each Morpho market specifies its oracle in the market parameters:\n\n`CollateralAsset/LoanAsset (LLTV%, OracleAddress, IRMAddress)`\n\n## Oracle Security Considerations\n\nThe security of an oracle is critical to the safety of a Morpho Market. Users should:\n\n- Verify the oracle implementation for any market they interact with\n- Understand the price sources being used\n- Consider potential manipulation vectors or failure modes\n\nThe immutable nature of Morpho Markets means oracle selection is a permanent decision that defines the market's [risk profile](/learn/resources/risks/)\n\n## Oracle community section\n\nSome community members contributed to adapters that could be plugged into oracles.\n\n- 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.\n- Users are advised to conduct their own research and exercise caution when applying any strategies or methods described herein.\n\nIf you are fine with it, jump on the liquidation community section [here](/tools/community/oracles/)"
  },
  "/learn/concepts/public-allocator/": {
    "title": "Public Allocator",
    "url": "https://docs.morpho.org/learn/concepts/public-allocator/",
    "section": "Learn",
    "content": "  \n\n## What is the Public Allocator?\n\nThe 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:\n\n## How It Works\n\nWhen 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.\n\n## Benefits\n\n**For Borrowers:**\n\n- Access significantly more liquidity in one transaction\n- Borrow larger amounts without hunting for fragmented liquidity\n- Experience the simplicity of pool-based lending with the efficiency of Morpho\n\n**For the Ecosystem:**\n\n- Creates liquidity network effects across vaults\n- Reduces the need for excessive capital concentration\n- Maintains the security of isolated markets while offering pool-like convenience\n\n## Implementation\n\nVault curators control how the Public Allocator can move their funds by setting the Public Allocator contract with the Allocator role, and then sets:\n\n- **Flow Caps**: Maximum amounts that can flow in or out of specific markets\n- **Market Preferences**: Which markets can send or receive funds\n- **Fee Parameters**: Optional fees that curators can set and collect for reallocations (these fees go to the curator, not to Morpho)\n\nThese controls ensure that while liquidity becomes more accessible, risk curation remains intact.\n\nBy 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."
  },
  "/learn/concepts/rewards/": {
    "title": "Rewards on Morpho",
    "url": "https://docs.morpho.org/learn/concepts/rewards/",
    "section": "Learn",
    "content": "  \n\n## What are Rewards?\n\nRewards 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:\n\n- The Morpho governance\n- Market creators bootstrapping liquidity\n- Vault curators attracting depositors\n- Token issuers promoting asset usage\n\n## Types of Rewards\n\n### Vault Rewards\n\nVault depositors can earn rewards from two sources:\n\n- **Vault Campaigns**: Direct rewards for depositing into a specific vault\n- **Market Campaigns**: Rewards automatically forwarded from underlying markets where the vault allocates\n\nThis dual-source structure allows vault depositors to benefit from multiple incentive programs simultaneously.\n\n### Market Rewards\n\nMarket participants can earn rewards based on their activity:\n\n- **Supply Rewards**: For supplying assets to a market\n- **Borrow Rewards**: For borrowing from a market\n\nIt is also possible to incentivize a simple collateral deposit (without the borrow action required).\n\nBorrowers can earn rewards on their borrow position, potentially offsetting or exceeding their borrowing costs.\n\n## How It Works\n\n1. **Earning**: Rewards accrue automatically while you participate in incentivized vaults or markets\n2. **Computation**: Rewards are calculated offchain based on your onchain activity\n3. **Distribution**: Rewards become claimable through Merkl (current) or URD (legacy) systems\n4. **Claiming**: Claim your earned rewards anytime with no deadline\n\n## Distribution Systems\n\nMorpho rewards are distributed through two systems:\n\n- **Merkl** (Current): Updates every 8 hours, handles new programs\n- **Morpho URD** (Legacy): Handled historical programs, rewards still claimable\n\nUsers simply need to participate in the protocol to earn rewards. No special actions required beyond claiming when convenient.\n\n## Learn More\n\n**For Users:**\n- Rewards accumulate automatically while you use Morpho\n- Claim rewards anytime through the Morpho interface\n- Tutorial: [How to Claim Rewards](https://help.morpho.org/en/articles/12032660-rewards-on-the-morpho-app)\n\n**For Developers:**\n- Complete integration guide: [Rewards Integration](/build/rewards/get-started)\n- Technical concepts: [Reward Campaigns](/build/rewards/concepts/reward-campaigns)\n- Distribution details: [Distribution System](/build/rewards/concepts/distribution-system)"
  },
  "/learn/concepts/vault-v2/": {
    "title": "Morpho Vault V2",
    "url": "https://docs.morpho.org/learn/concepts/vault-v2/",
    "section": "Learn",
    "content": "  \n\n**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.\n\nWhile 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**.\n\n## Key Feature Comparison: Morpho Vaults V1 vs. Morpho Vaults V2\n\n| Feature                 | Morpho Vault V1                                                  | Morpho Vault V2                                                                                            |\n| ----------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| **Protocol Support**    | Exclusively Morpho Market V1.                                    | **Future-Proof**. Can add support to Morpho yield sources via Adapters.                                    |\n| **Interest Accrual**    | **Automatic**. Calculated onchain from Morpho Market V1.         | **Automatic aggregation**. Each adapter reports current assets via `realAssets()`.                         |\n| **Risk Curation**       | **Simple**. Absolute supply cap per market.                      | **Granular**. Absolute and relative caps on abstract `ids` (e.g., collateral type, oracle, protocol).      |\n| **Roles & Permissions** | Owner is powerful; Guardian is a safety net.                     | **Separated roles** (Owner, Curator, Allocator, Sentinel) for better separation of duties.                 |\n| **Bad Debt**            | (V1.1) Not realized by the vault; remains in Morpho Market V1.   | **Automatically tracked**. Adapters report losses in real-time through `realAssets()`.                     |\n| **Liquidity**           | Liquidity is a single pool across all markets.                   | Distinct **idle assets** and an optional, dedicated **`liquidityAdapter`**.                                |\n| **Compliance / Gating** | Not natively supported.                                          | Native support for onchain **Gating** via gate contracts for shares and asset transfers.                   |\n| **ERC-4626 Compliance** | Fully compliant.                                                 | Mostly compliant, with shares remaining fully ERC-20.                                                      |\n\n## The Evolution from V1 to V2\n\nMorpho Vault V2 is a significant leap forward, designed for maximum flexibility and control.\n\n-   **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.\n-   **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.\n-   **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.\n\n## Core Concepts of Morpho Vault V2\n\n### 1. The Adapter Model: A Universal Gateway to Yield\n\nThe 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.\n\n-   **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).\n-   **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.\n-   **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`.\n\n### 2. Granular Risk Curation: The ID & Cap System\n\nMorpho 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.\n\nFor example, the `MorphoMarketV1AdapterV2` can generate `ids` for:\n-   A specific collateral asset (e.g., `keccak256(\"collateralToken\", stETH_address)`)\n-   A specific market configuration (e.g., `keccak256(\"collateralToken/oracle/lltv\", ...)`).\n\nThe `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:\n-   Max total exposure to `stETH` as collateral: 15M (absolute cap on the collateral `id`).\n-   Max 20% of the vault allocated to any market using a specific, new oracle (relative cap).\n\n### 3. Advanced Liquidity Curation\n\nMorpho Vault V2 separates idle liquidity from allocated capital more explicitly.\n\n-   **Idle Assets**: All user deposits and withdrawals flow through the main vault contract, which holds the idle assets.\n-   **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.\n-   **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.\n\nSome gate implementations can affect noncustodiality guarantees by preventing certain users from depositing to or withdrawing from the vault.\n\n## Advanced Role System\n\nMorpho Vault V2 refines the role system for greater security and flexibility:\n\n-   **Owner**: Manages top-level permissions. Can appoint the Curator and Sentinels. Has no direct control over funds or risk parameters.\n-   **Curator**: The primary risk manager. Sets adapters, caps, fees, and interest rate limits. Most actions are timelocked.\n-   **Allocator**: The active portfolio manager. Allocates funds to enabled adapters and manages the `liquidityAdapter`.\n-   **Sentinel**: The safety-focused role that can reactively reduce risk by deallocating funds, decreasing caps, or revoking pending timelocked actions.\n\n## Other Key Features\n\n-   **New Fee Structure**: Supports both a **performance fee** (up to 50% on yield) and a **management fee** (up to 5% on total assets).\n-   **Interest Rate Controls**: The Curator can set a `maxRate` that caps how quickly `totalAssets` can grow, useful for implementing fixed-rate distributions.\n-   **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).\n\n## Is Morpho Vault V2 Non-Custodial?\n\n**Yes, Morpho Vault V2 maintains noncustodial guarantees through three fundamental mechanisms: in-kind redemptions, timelocks, and role-based access control.**\n\nSome [gate](#gates-optional-access-control) implementations can affect noncustodiality guarantees by preventing certain users from depositing to or withdrawing from the vault.\n\n### Core Non-Custodial Mechanisms\n\n#### 1. In-Kind Redemptions with `forceDeallocate`\n\nIn-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).\nIt 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.\n\nThis transition happens through the permissionless `forceDeallocate` function. This mechanism enables:\n\n- **Guaranteed exits**: Users can redeem their Morpho Vault V2 shares directly for underlying positions in protocols, similar to ETF redemptions\n- **Permissionless operation**: Anyone can call `forceDeallocate` to move assets from adapters back to the vault's idle assets\n- **Flashloan-enabled exits**: Users can flashloan liquidity, supply it to an adapter's market, then withdraw through `forceDeallocate` before repaying the flashloan\n\n**Complete In-Kind Redemption Workflow:**\n\nWhen a vault lacks sufficient idle liquidity for withdrawals, users can perform an in-kind redemption through flashloan-enabled exits:\n\n1. **User flashloans the required liquidity amount**\n2. **User deposits flashloaned assets directly into the underlying market/protocol**\n3. **User calls `forceDeallocate` to withdraw equivalent assets from the adapter**\n4. **User withdraws their vault shares for the deallocated assets**\n5. **User repays the flashloan with the withdrawn assets**\n6. **User retains their position in the underlying market as compensation**\n\nA small penalty (up to 2%) may apply to discourage manipulation, but this doesn't prevent exits—it only adds a minor cost.\n\nThis 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.\n\n#### 2. Comprehensive Timelock System\n\nAll potentially harmful curator actions are protected by configurable timelocks (0 to 3 weeks), giving users time to react:\n\n**Timelocked actions include:**\n\n- Increasing allocation caps (absolute and relative)\n- Enabling new adapters or allocators\n- Setting performance/management fees (capped at 50% and 5% respectively)\n- Configuring access gates\n- Modifying fee recipients\n\n**Timelock properties:**\n\n- Users can monitor pending changes via the `submit` function, which records proposal timestamps in the `executableAt` mapping\n- Sentinels can revoke malicious proposals before execution\n- Emergency functions like decreasing caps can be called immediately by curators or sentinels for protective risk management\n- Some timelocks can be made infinite through `abdicate`, permanently preventing certain actions\n\n**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.\n\n#### 3. Role Separation and Limitations\n\nMorpho 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.\n\nCheck the roles declination on the related [section](/curate/concepts/roles/#morpho-vaults-v2-roles).\n\n### Additional Safety Mechanisms\n\n#### Caps and Risk Controls\n\n- **Absolute caps**: Hard limits on allocation to specific protocols/markets\n- **Relative caps**: Percentage-based limits relative to total vault assets\n- **Id system**: Groups related risks (e.g., same collateral) under unified caps\n\n#### Gates (Optional Access Control)\n\nWhen enabled, gates control:\n\n- Share transfers (who can send/receive vault shares)\n- Asset deposits (who can deposit into vault)\n- Asset withdrawals (who can receive assets from vault)\n\nGates are timelocked and can be permanently disabled through abdication.\n\n### Adapter Registry\n\n**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.\n\nWhen the curator locks (abdicates) the registry, it can never be changed—giving users a strong, permanent guarantee about where their funds can be allocated.\n\nMorpho Vaults V2 benefit from the full support of Morpho's infrastructure:\n- **Full app integration**: Listed in the [Morpho app](https://app.morpho.org) (subject to listing process).\n- **Curation tools**: Configurable through the [Curator app](https://curator.morpho.org).\n- **Data utilities**: [Morpho GraphQL API](https://api.morpho.org/graphql), [Dune Analytics Dashboards](https://dune.com/morpho).\n- [Security audits](/get-started/resources/audits/) for all supported contracts and flows.\n- Thorough product and technical documentation.\n- Peripheral utilities like the [Oracle tester and decoder](https://oracles.morpho.dev/).\n\n#### Immutable Contracts\n\nAll vault contracts are immutable—no upgrades can change the core noncustodial guarantees after deployment.\n\n### Why This Matters\n\nThese mechanisms ensure that:\n\n1. **No entity can permanently lock user funds** (guaranteed via `forceDeallocate`)\n2. **No surprise changes can harm users** (guaranteed via timelocks)\n3. **No single party controls user assets** (guaranteed via role separation)\n\nThe 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."
  },
  "/learn/concepts/vault/": {
    "title": "Morpho Vault V1",
    "url": "https://docs.morpho.org/learn/concepts/vault/",
    "section": "Learn",
    "content": "  \n\n**Morpho Vault V1** is a protocol for permissionless lending vaults built on top of the [Morpho Markets V1](/learn/concepts/market/).\n\n## What is a Morpho Vault V1?\n\nA 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.\n\n## Key Features\n\n- **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.\n\n- **Simplified Yield Generation**: Vaults abstract away the complexity of managing positions across multiple lending markets, allowing users to deposit once and earn optimized yields.\n\n- **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.\n\n- **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.\n\n- **Transparent Operations**: All vault actions and allocations are visible onchain, with role-based management to ensure proper oversight and risk control.\n\nMorpho 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.\n\n## How It Works\n\n1.  **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**.\n2.  **Capital Allocation**: The `Allocator` is responsible for optimizing yield. They manage two queues:\n    *   **Supply Queue**: Defines the priority order for depositing new capital into the enabled markets.\n    *   **Withdraw Queue**: Defines the priority order for withdrawing capital to meet user redemption requests.\n    The allocator can also `reallocate` funds between enabled markets to optimize utilization and yield.\n3.  **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`.\n\n## Roles and Responsibilities\n\nMorpho Vaults V1 use a system of distinct roles to separate powers and responsibilities:\n\n-   **Owner**: The highest level of control. The owner can appoint the Curator and Allocators and set vault-level parameters like fees.\n-   **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.\n-   **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.\n-   **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.\n\n## A Note on V1.0 vs V1.1\n\nThe 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.\n\n-   **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.\n-   **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."
  },
  "/learn/governance/": {
    "title": "Morpho Governance",
    "url": "https://docs.morpho.org/learn/governance/",
    "section": "Learn",
    "content": ""
  },
  "/learn/governance/morpho-token/": {
    "title": "The MORPHO token",
    "url": "https://docs.morpho.org/learn/governance/morpho-token/",
    "section": "Learn",
    "content": "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.\n\nMORPHO 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.\n\n## Legacy and Wrapped MORPHO\n\nThe 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).\n\nIn 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.\n\nAlthough 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.\n\n## MORPHO Token Addresses\n\nYou can find MORPHO token contracts, related contracts addresses as well as Github repositories in the [addresses section](/get-started/resources/addresses/#morpho-token).\n\nThe MORPHO token has a maximum supply of 1,000,000,000 MORPHO.\n\n## Token Distribution & Vesting\n\nThe overall distribution of MORPHO tokens, including vested and unvested allocations, as of 7 November 2024.\n\n  \n\n### Morpho governance\n\n35.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.\n\n### Users & Launch Pools\n\n4.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.\n\n### Morpho Association\n\n6.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.\n\n### Reserve for Contributors\n\n5.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.\n\n### Strategic Partners\n\n27.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.\n\n**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.\n\n**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.\n\n**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.\n\n### Founders\n\n15.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.\n\n### Early Contributors\n\n4.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:\n\n- A 3-year vesting schedule with a 6-month lockup, or\n- A 4-year vesting schedule with a 4-month lockup.\n\n## Circulating Supply\n\nThe circulating supply on transferability date is expected to be approximately 11.2%.\n\nThe chart below shows how the circulating supply of MORPHO tokens might evolve over time:\n\n  \n\n*Note: the evolution of the MORPHO circulating supply over time is subject to change\nas the governance makes future decisions on use of reserves and rate of distributions.*\n\n## Initial Non-Transferability Phase\n\nWhile 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.\n\nThe 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.\n\nUnder this vision, a good equilibrium for the control of a governance is a clear distribution between:\n\n1. Users: To own a share of the network and to provide a positive feedback loop on the product.\n2. Contributors: To keep improving and building based on the user's feedback and on their technical vision.\n3. Strategic Partners: To provide capital and guidance to fuel those contributions.\n\nThe 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).\n\n## Morpho governance Voted to Enable Token Transferability\n\nAlthough 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.\n\nAs 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.\n\nMORPHO token transferability was enabled on November 21, 2024.\n\n## FAQ\n\n### Why are there two MORPHO tokens? What’s the difference between them?\n\nThe 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).\n\nIn 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.\n\nAlthough 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)).\n\n### How to wrap the Legacy MORPHO token on the Morpho interface\n\nIf 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.\nClick on the `Wrap` button at the top right of the Morpho interface.\n\n  \n\nClicking on the `Wrap` button will trigger a modal, showing your Legacy MORPHO token balance and proposing you to wrap it.\n\n  \n\nThen click on the `Wrap MORPHO` button and it will trigger:\n\n1. A transaction to approve the bundler to wrap the Legacy MORPHO tokens.\n2. A transaction to wrap the Legacy MORPHO tokens into the wrapped MORPHO token.\n\n### How to wrap the Legacy MORPHO token at contract level\n\nIf 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.\n\nTo do so, you will have to:\n\n- **Connect** your wallet to Etherscan.\n\n- **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).\n  E.g: - Wrapper address: 0x9D03bb2092270648d7480049d0E58d2FcF0E5123 - 1000000000000000000\n  for 1 Legacy MORPHO Token (18 decimals)\n\n  \n\n- **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).\n\n  \n\nFeel free to get in touch via the chatbox on **[help.morpho.org](https://help.morpho.org)**."
  },
  "/learn/governance/organization/": {
    "title": "Morpho Governance",
    "url": "https://docs.morpho.org/learn/governance/organization/",
    "section": "Learn",
    "content": "Morpho Protocol governance is intentionally limited in scope. The core smart contract code is immutable. The powers of the governance include:\n\n- Control over the MORPHO tokens in the governance treasury\n- Ownership of the upgradeable MORPHO token contract\n- 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\n- Whitelisting new [LLTVs and IRMs](/learn/concepts/market/#dao-approved-lltv--irm) for use in the Morpho Protocol\n- Granting licenses of the Morpho Protocol code by updating the ENS record at morpho-blue-core-license-grants.morpho.eth\n- Ownership of the morpho.eth ENS domain and subdomains, which are used for clearly labelling relevant protocol addresses\n\nThe governance discussions happen on [the Morpho governance forum](https://forum.morpho.org/). This discussions can lead to proposals that will be voted on.\n\nMORPHO 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.\n\n## Morpho Association\n\nThe 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.\n\nIn practice, the Morpho Association:\n- Supports the development, growth, security and adoption of the Morpho protocol\n- Hosts a front end to the Morpho protocol to facilitate the access of new users to Morpho: [morpho.org](http://morpho.org/)\n- Hosts technical documentation to facilitate the work of new Morpho developers\n- 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.\n\n## Multisig and Addresses\n\n| Name                                   | Address/Details                                                                                                                                           |\n| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Morpho Contracts**                   | See the [Addresses](/get-started/resources/addresses/#1) section                                                                                             |\n| **Morpho governance** (Ethereum)       | morpho.eth (5/9 multisig): [0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa](https://etherscan.io/address/0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa)          |\n| **Morpho governance** (Base)           | morpho.eth (5/9 multisig): [0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa](https://basescan.org/address/0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa)          |\n| **MORPHO Rewards Multisig** (Ethereum) | [0xF057afeEc22E220f47AD4220871364e9E828b2e9](https://etherscan.io/address/0xF057afeEc22E220f47AD4220871364e9E828b2e9) (3/5)                               |\n| **MORPHO Rewards Multisig** (Base)     | [0x5Eb982bb1E620cC3927E5CF8A5D207e667643297](https://basescan.org/address/0x5Eb982bb1E620cC3927E5CF8A5D207e667643297) (3/5)                               |"
  },
  "/learn/resources/risks/": {
    "title": "Risk & Security Documentation",
    "url": "https://docs.morpho.org/learn/resources/risks/",
    "section": "Learn",
    "content": "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.\nMorpho 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.\n\n## Morpho Security practices\n\nMorpho is known for its industry-leading security practices and follows a multi-faceted approach to security.\n\nMorpho 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.\n\nA whole article was dedicated to the [Morpho Security Framework](https://morpho.org/blog/morpho-blue-security-framework-building-the-most-secure-lending-protocol/).\n\nThe 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.\n\n## Smart Contract Risk\n\nThere is an inherent risk that the protocol could contain a smart contract vulnerability or bug.\n\nSeveral security measures are employed to mitigate this risk:\n\n- Core contracts are immutable\n- It is a simple and open-sourced [code base](/get-started/resources/contracts/) that avoids complexities\n- The code has been audited by multiple auditors, refer to the [security reviews](/get-started/resources/audits/) section\n- [Formal verification](/learn/resources/risks/#formal-verifications) has been applied using [Certora](https://www.certora.com/)\n- One ongoing bug bounty program: [Cantina - $2,500,000](https://cantina.xyz/bounties/35a5f0a1-2ffd-432c-8f3b-77d169add8c3) (Morpho & Morpho vaults)\n\n## Oracle Risk\n\nEvery 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.\n\nWhen 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.\n\nMarkets 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.\n\n## Counterparty Risk\n\nBefore 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.\n\n## Liquidation Risk\n\n### Liquidation Risk (for borrowers)\n\nEach 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.\n\n### Bad Debt Risk (for lenders)\n\nThere 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).\n\n### Liquidity Risk (for lenders)\n\nLiquidity 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.\n\n## Morpho Vaults Specific Risks\n\n### Vault Governance Risks\n\nKey [roles](/curate/concepts/roles/) within a Morpho Vault wield significant power, impacting user interests. Governance structures differ between Vaults V1 and Vaults V2.\n\n#### Vaults V2 Governance\n\nVaults V2 introduces a refined role system with clear separation of concerns:\n\n- 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.\n- 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.\n- 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.\n- The **Sentinels** provide emergency de-risking capabilities. They can revoke pending timelocked actions, decrease caps, and deallocate funds without being allocators.\n\n**Key governance mechanisms in V2:**\n\n- **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.\n- **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.\n- **Gates**: [Gate contracts](/curate/concepts/gates/) can restrict share and asset transfers. A misconfigured gate could lock users out of deposits or withdrawals.\n- **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.\n- **Fee Caps**: Performance fees are capped at 50% of interest, and management fees at 5% annually, providing depositor protection against excessive fees.\n\n#### Vaults V1 Governance\n\n- 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.\n- 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.\n- The [Allocators](https://github.com/morpho-org/metamorpho#allocator) determine markets supply/withdrawal order, influencing returns and liquidity for suppliers.\n- The [Guardian](https://github.com/morpho-org/metamorpho#guardian) has the ability to revoke timelocked actions, providing an additional layer of protection for users.\n\nWhen 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/": {
    "title": "Build Earn & Borrow Products on Morpho",
    "url": "https://docs.morpho.org/build/",
    "section": "Build",
    "content": "Welcome to the Morpho developer hub. Build powerful DeFi applications with our comprehensive suite of tools, SDKs, and APIs.\n\nOn Morpho, you can leverage Morpho Vaults to build earn products and Morpho Markets to build borrow products. Select what you expect to integrate below:\n\n    \n      Earn - Morpho Vaults\n      Put your crypto to work\n  \n    \n      +\n      Simple\n    +\n      Optimized\n    +\n      Tailored\n    +\n      Non-custodial\n  \n  \n  \n      Build → \n    \n    \n      Earn on App ↗︎\n    \n\n  \n  \n      Borrow - Morpho Markets\n      Provide collateral to borrow any asset\n  \n    \n      +\n      Low costs\n    +\n      Higher collateralization factors\n    +\n      Per market rates\n    +\n      Zero fees\n  \n  \n  \n      Build →\n    \n    \n      Borrow on App ↗︎\n    \n\n  \n\n## Get Started\n\n1. **Choose your product**: Start with [Earn](/build/earn/get-started) or [Borrow](/build/borrow/get-started)\n2. **Select your tools**: Review our [development tools](/tools) to choose the best integration approach\n3. **Follow the guides**: Use our step-by-step tutorials and reference applications\n4. **Get in touch**: Get support via the chatbox on **[help.morpho.org](https://help.morpho.org)**"
  },
  "/build/borrow/concepts/interest-rates/": {
    "title": "Interest Rates",
    "url": "https://docs.morpho.org/build/borrow/concepts/interest-rates/",
    "section": "Build",
    "content": "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)**.\n\n## The Role of the Interest Rate Model (IRM)\n\nEach 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**.\n\n-   **Utilization Rate:** The ratio of total borrowed assets to total supplied assets in a market.\n    ```math\n      \\text{Utilization} = \\frac{\\text{Total Borrows}}{\\text{Total Supply}}\n    ```\n\n-   **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`.\n\n### The AdaptiveCurveIRM\nThe `AdaptiveCurveIRM` is designed to maintain market utilization around a target of **90%**.\n\n-   **When utilization < 90%:** The borrow rate gradually decreases to incentivize more borrowing.\n-   **When utilization > 90%:** The borrow rate rapidly increases to encourage repayments and attract more supply.\n\nThis mechanism ensures that markets remain capital-efficient while having enough liquidity for withdrawals.\n\nFor a deeper dive into the mathematical formulas and adaptive mechanics, see the **[IRM Concept Page](/learn/concepts/irm/)**.\n\n## How Interest Accrues on Debt\n\nFor 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.\n\nThe process is as follows:\n\n#### 1. Rate Calculation\nThe IRM calculates the instantaneous `borrowRate` based on the market's current utilization.\n\n#### 2. Interest Accrual\nThis 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`.\n\n#### 3. Impact on Health Factor\nAs 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.\n\n```math\n  \\text{Health Factor} = \\frac{\\text{Collateral Value} \\times \\text{LLTV}}{\\text{Initial Debt} + \\text{Accrued Interest}}\n```\n\nThis is a critical concept to communicate to users: their position can become riskier over time simply from interest accrual.\n\n## Onchain State and `accrueInterest`\n\nThe 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`.\n\n**What this means for your integration:**\n\nWhen 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.\n\nJump on the tutorials to learn how to accrue the interests up to the last block. \n\nSee the [Get Data Tutorial](/build/borrow/tutorials/get-data#onchain--sdk-required-for-real-time-accuracy) for a practical example.\n\n## Integration Best Practices\n\n-   **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.\n-   **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.\n-   **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.\n\nBy correctly implementing and displaying interest rate mechanics, you empower users to manage their borrow positions effectively and safely."
  },
  "/build/borrow/concepts/liquidation/": {
    "title": "Liquidation",
    "url": "https://docs.morpho.org/build/borrow/concepts/liquidation/",
    "section": "Build",
    "content": "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.\n\nWhen 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.\n\n## When Does Liquidation Occur?\n\nA position becomes eligible for liquidation the moment its **Health Factor drops to 1 or below**.\n\nAs 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.\n\n```math\n  \\text{If} \\quad \\frac{\\text{Debt Value}}{\\text{Collateral Value}} \\ge \\text{LLTV} \\quad \\implies \\quad \\text{Position is Liquidatable}\n```\n\nThis can be caused by:\n-   A decrease in the price of the collateral asset.\n-   An increase in the value of the debt due to accrued interest.\n\n## The Liquidation Process\n\nLiquidation 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.\n\n#### 1. An Unhealthy Position is Identified\nA liquidator (typically an automated bot) detects a position where the Health Factor is ≤ 1.\n\n#### 2. Liquidator Repays the Debt\nThe liquidator calls the `liquidate` function on the Morpho contract, repaying a portion or all of the borrower's debt using the loan asset.\n\n#### 3. Liquidator Seizes Collateral at a Discount\nIn 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.\n\n#### 4. The Borrower's Position is Updated\nThe borrower's debt is reduced or eliminated, and their collateral is reduced by the amount seized.\n\n### The Liquidation Incentive Factor (LIF)\n\nThe \"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.\n\n  \n\nFor 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.\n\n### Example: A Liquidation Scenario\n\n-   **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**.\n-   **Health Check**: The LTV is 87% (`87k / 100k`), which is greater than the 86% LLTV. The position is liquidatable.\n-   **Liquidation**: A liquidator repays the full **$87,000** debt.\n-   **Collateral Seized**: The liquidator seizes `$87,000 * 1.05` (LIF) = **$91,350** worth of the borrower's collateral.\n-   **Outcome**:\n    -   **Borrower**: Their debt is cleared, but they lose $91,350 of their $100,000 collateral, incurring a loss of **$4,350**.\n    -   **Liquidator**: Profits by **$4,350** (minus gas and transaction costs).\n\n### Bad Debt\nIn 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.\n\n## Integration Best Practices for Developers\n\nYour primary goal as an integrator is to help your users avoid liquidation.\n\n1.  **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.\n\n2.  **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.\n\n3.  **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).\n\n4.  **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.\n\nBy treating liquidation as a core part of the user experience, you can build a safer and more trustworthy borrowing platform.\n\n## Protection Options for Borrowers\n\nJump to the following section to understand how you can protect your users when offering a borrow product by integrating the pre-liquidation mechanism."
  },
  "/build/borrow/concepts/ltv/": {
    "title": "Collateral, LTV & Health",
    "url": "https://docs.morpho.org/build/borrow/concepts/ltv/",
    "section": "Build",
    "content": "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.\n\nThis page explains the core concepts of Collateral, Loan-to-Value (LTV), and Health Factor.\n\n## Collateral\n\nIn 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.\n\nA 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.\n\n## Understanding Loan-To-Value (LTV)\n\nIt's essential to understand how LTV is calculated and what it represents.\n\n### How to Calculate LTV\n\nThe 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:\n\n```math\n\\text{LTV} = \\frac{\\text{BORROWED\\_AMOUNT}}{\\text{COLLATERAL\\_VALUE\\_IN\\_LOAN\\_TOKEN}} \\times 100\\%\n```\n\nWhere:\n\n- **`BORROWED_AMOUNT`**: The amount of borrowed assets of the user (in token base units)\n- **`COLLATERAL_VALUE_IN_LOAN_TOKEN`**: The value of the collateral in terms of the loan token\n\nThe collateral value in loan token units is calculated as:\n\n```math\n\\text{COLLATERAL\\_VALUE\\_IN\\_LOAN\\_TOKEN} = \\frac{\\text{COLLATERAL\\_AMOUNT } \\times \\text{ ORACLE\\_PRICE}}{\\text{ORACLE\\_PRICE\\_SCALE}}\n```\n\nWhere:\n\n- **`COLLATERAL_AMOUNT`**: The amount of collateral assets provided by the user (in token base units)\n- **`ORACLE_PRICE`**: The oracle price returned by the oracle of the market (scaled by ORACLE_PRICE_SCALE)\n- **`ORACLE_PRICE_SCALE`**: A scaling factor of 10^36 used by the protocol for price normalization\n\n### Liquidation Loan-to-Value (LLTV)\n\nThe **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.\n\nThe rule is simple and absolute:\n**If `LTV` ≥ `LLTV`, the position can be liquidated.**\n\nFor 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%.\n\n### Health Factor\n\nThe Health Factor is another crucial metric that indicates how close a position is to liquidation:\n\n```math\n\\text{HEALTH\\_FACTOR} = \\frac{\\text{COLLATERAL\\_VALUE\\_IN\\_LOAN\\_TOKEN} \\times \\text{LLTV}}{\\text{BORROWED\\_AMOUNT}}\n```\n\nWhere:\n\n- **`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)\n\nA position is healthy when the Health Factor is greater than 1.0. When it falls below 1.0, the position becomes eligible for liquidation.\n\n- For oracle implementation details, see the [dedicated oracle section](/curate/tutorials-market-v1/deploying-oracle/)\n- WAD represents a common scaling factor in DeFi of 10^18 used for representing decimal numbers in integer arithmetic\n\nLet's walk through a concrete example of calculating LTV and Health Factor for a position on Morpho:\n\n**Given values (with assumptions):**\n\n- Borrowed amount: 150,000 USDC (150,000,000,000 base units with 6 decimals)\n- Collateral amount: 2 cbBTC (200,000,000 base units with 8 decimals)\n- 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\n- Oracle price scale: 10^36\n- LLTV: 86% (expressed as 0.86 × 10^18 or 860,000,000,000,000,000 in WAD units)\n\n#### Calculate the collateral value in loan token units\n\n```typescript\n// All calculations use BigInt (suffixed with 'n') to handle large numbers precisely\nconst collateralValueInLoanToken =\n  (collateralAmount * oraclePrice) / ORACLE_PRICE_SCALE;\n// = (200,000,000n * 1,000,000,000,000,000,000,000,000,000,000,000,000,000n) / 10n**36n\n// = 200,000,000,000 base units of loan token (USDC)\n```\n\n#### Calculate the current LTV\n\n```typescript\n// Constants\nconst WAD = 10n ** 18n; // Standard scaling factor (10^18)\n\n// Example values\nconst borrowedAmount = 150_000_000_000n; // 150 billion units (e.g., USDC with 6 decimals)\nconst collateralValueInLoanToken = 200_000_000_000n; // 200 billion units\n\n/**\n * Current LTV Calculation\n * ----------------------\n *\n * Step 1: Calculate the raw LTV ratio, preserving precision with WAD\n */\nconst currentLTV = (borrowedAmount * WAD) / collateralValueInLoanToken;\n// = (150,000,000,000n * 10n**18n) / 200,000,000,000n\n// = 750,000,000,000,000,000n (scaled by WAD, representing 0.75 or 75%)\n\n/**\n * Option 1: Theoretical Formula\n * ----------------------------\n * In theory, the conversion to percentage is simply:\n */\n// Theoretical formula (doesn't work directly with BigInt)\n// currentLTVPercentage = (currentLTV / WAD) * 100\n\n// Implementation of theoretical formula (using Number conversion)\nconst theoreticalLTVPercentage = (Number(currentLTV) / Number(WAD)) * 100;\n// = 75.0000%\n\n/**\n * Option 2: Practical Display Implementation\n * ----------------------------------------\n * For precise display with 4 decimal places, we:\n * 1. Scale up by the display factor (percentage * decimal precision)\n * 2. Divide by WAD to normalize\n * 3. Convert to Number and adjust for decimal places\n */\n// Scale factor = 100 (for percentage) * 10000 (for 4 decimal places) = 1,000,000\nconst displayScaleFactor = 1_000_000n;\nconst currentLTVPercentageScaled = (currentLTV * displayScaleFactor) / WAD;\n// = 750_000n (represents 75.0000%)\n\n// Convert the scaled BigInt result to a human-readable number\nconst displayLTVPercentage = Number(currentLTVPercentageScaled) / 10000;\n// = 75.0000% (when displayed with 4 decimal places)\n```\n\n#### Calculate the health factor\n\n```typescript\n// Since LLTV is stored as a WAD, we need to account for scaling\nconst healthFactor = (collateralValueInLoanToken * lltv) / borrowedAmount;\n// = (200,000,000,000,000n * 860,000,000,000,000,000n) / 150,000,000,000n\n// = 1,146,666,666,666,666,666 (scaled by WAD)\n\n// Convert to decimal\nconst healthFactorDisplay = Number(healthFactor) / Number(WAD);\n// = 1.1467 (when converted to a human-readable decimal)\n```\n\nSince the Health Factor is greater than 1.0 (1.1467), this position is healthy and has a safety margin before liquidation could occur.\n\n#### Summary of Position:\n\n- Current LTV: 75.00%\n- Max LTV (LLTV): 86.00%\n- Health Factor: 1.1467\n- Status: Healthy\n- Liquidation Buffer: 11.00% (difference between current LTV and max LTV)\n\nThis 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.\n\n- For oracle implementation details, see the [dedicated oracle section](/curate/tutorials-market-v1/deploying-oracle/)\n- 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)\n\n## The Role of Oracles\n\nThe accuracy of LTV and Health Factor calculations depends on the **Oracle Price**.\n\n-   **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.\n-   **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.\n-   **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.\n\nWhen displaying market information, it is crucial to also provide transparency about the oracle being used.\n\n## Integration Best Practices\n\nFor any application with a borrow interface, a primary goal should be to help users avoid liquidation.\n\n1.  **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.\n\n2.  **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`.\n\n3.  **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.\n\n4.  **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.\n\n5.  **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.\n\nBy following these best practices, you can build a borrow experience that is not only functional but also safe and transparent for your users.\n\n**Next Up:** Learn what happens when the Health Factor drops below 1.0 in the **[Liquidation concept page](/learn/concepts/liquidation/)**."
  },
  "/build/borrow/concepts/market-mechanics/": {
    "title": "Market Mechanics",
    "url": "https://docs.morpho.org/build/borrow/concepts/market-mechanics/",
    "section": "Build",
    "content": "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.\n\nThis page explains the fundamental mechanics you need to understand to build a robust borrowing integration.\n\n## Core Data Structures\n\nAt the heart of Morpho are two key structs that define the state of every market and every user's position within it.\n\n### `Market` Struct\nThis struct tracks the overall state of a single, isolated market.\n\n```solidity\nstruct Market {\n    uint128 totalSupplyAssets;\n    uint128 totalSupplyShares;\n    uint128 totalBorrowAssets;\n    uint128 totalBorrowShares;\n    uint128 lastUpdate;\n    uint128 fee;\n}\n```\n-   `totalSupply/BorrowAssets`: The total amount of the underlying token supplied or borrowed. This value changes as interest accrues.\n-   `totalSupply/BorrowShares`: The total number of internal accounting units (shares) held by suppliers or borrowers. This value only changes with user interactions.\n\n### `Position` Struct\nThis struct tracks an individual user's position within a specific market.\n\n```solidity\nstruct Position {\n    uint256 supplyShares;\n    uint128 borrowShares;\n    uint128 collateral;\n}\n```\n- `collateral`: The amount of collateral the user has supplied *to this specific market*.\n\n## Assets vs. Shares: The Core Mechanic\n\nThe most critical concept to grasp is the relationship between **Assets** and **Shares**. This dual-accounting system is how Morpho manages positions and accrues interest.\n\n### Assets\n-   **Definition**: The actual, underlying tokens (e.g., USDC, WETH) that users interact with.\n-   **Use Case**: Ideal for user-facing interactions where a specific token amount is desired (e.g., \"I want to borrow 1,000 USDC\").\n\n### Shares\n-   **Definition**: Internal, non-transferable accounting units that represent a user's proportional stake in the market's total supply or debt.\n-   **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.\n-   **Use Case**: Ideal for protocol-level interactions and for ensuring full repayment or withdrawal, as it avoids rounding errors (\"dust\").\n\n### The Relationship: Share Price\nThe \"price\" of a share is its exchange rate to the underlying asset. This price is dynamic and increases as interest accrues.\n\n```solidity\n// This is a conceptual calculation; the contract uses SharesMathLib for precision.\nsharePrice = totalAssets / totalShares;\n```\n- For **suppliers**, the value of their shares grows over time, representing their earned yield.\n- For **borrowers**, the asset value of their debt grows over time, representing the interest they owe.\n\n## Core Functions & Their Dual Nature\n\nMost 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.\n\n### `supply` and `borrow`\n```solidity\nfunction supply(uint256 assets, uint256 shares, ...);\nfunction borrow(uint256 assets, uint256 shares, ...);\n```\n- **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.\n- **Use `assets` = 0, `shares` > 0:** For advanced use cases where you need to mint a precise number of shares.\n\n### `repay` and `withdraw`\n```solidity\nfunction repay(uint256 assets, uint256 shares, ...);\nfunction withdraw(uint256 assets, uint256 shares, ...);\n```\n- **Use `assets` > 0, `shares` = 0:** For partial repayments or withdrawals where a specific token amount is needed.\n- **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.\n\n## Collateral and Health\n\n-   **`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.\n-   **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`.\n\nTo learn more about how position health is calculated and managed, see the **[Collateral, LTV & Health concept page](/build/borrow/concepts/ltv/)**.\n\n## Practical Implementation Snippets\n\n### Supplying Collateral & Borrowing (Asset-First)\n```typescript\n// Conceptual TypeScript using a web3 library like Viem\n\n// 1. Approve collateral tokens\nawait client.writeContract({ functionName: 'approve', args: [morphoAddress, collateralAmount] });\n\n// 2. Supply collateral\nawait client.writeContract({ functionName: 'supplyCollateral', args: [marketParams, collateralAmount, userAddress] });\n\n// 3. Borrow assets\nconst { result } = await client.simulateContract({\n  functionName: 'borrow',\n  args: [marketParams, borrowAmount, 0, userAddress, userAddress] // assets > 0, shares = 0\n});\nawait client.writeContract(result.request);\n```\n\n### Full Repayment (Shares-First)\n```typescript\n// 1. Fetch the user's current borrow shares\nconst { borrowShares } = await client.readContract({\n  functionName: 'position',\n  args: [marketId, userAddress]\n});\n\n// 2. Approve the loan token for repayment\n// The amount to approve should be slightly more than the expected asset value of the shares\n// to account for interest accrued since the last block.\nconst repayAmountAssets = await client.readContract({\n    functionName: 'toAssetsUp', // using a helper or SDK function\n    args: [borrowShares, market.totalBorrowAssets, market.totalBorrowShares]\n});\nawait client.writeContract({ functionName: 'approve', args: [morphoAddress, repayAmountAssets] });\n\n// 3. Repay the full debt by specifying the exact shares\nawait client.writeContract({\n    functionName: 'repay',\n    args: [marketParams, 0, borrowShares, userAddress] // assets = 0, shares > 0\n});\n```\n\n## Best Practices\n\n-   **For User-Facing Actions**: Use the `assets` parameter for `supply`, `borrow`, and partial `repay`/`withdraw` as it's more intuitive for users.\n-   **For Closing Positions**: Use the `shares` parameter for full `repay` and `withdraw` operations to ensure the position is fully closed.\n-   **Slippage**: When converting between assets and shares, be aware of potential slippage due to interest accrual between transaction simulation and execution.\n-   **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.\n\nBy understanding these core mechanics, you can build safe, efficient, and user-friendly applications on top of Morpho Markets."
  },
  "/build/borrow/concepts/preliquidation/": {
    "title": "Pre-Liquidation (Auto-Deleveraging)",
    "url": "https://docs.morpho.org/build/borrow/concepts/preliquidation/",
    "section": "Build",
    "content": "**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.\n\nThink of it as a \"safety zone\" where a position can be gently corrected instead of falling off a cliff.\n\n## How Pre-Liquidation Works\n\nStandard liquidation is an all-or-nothing event triggered when a position's Health Factor hits 1.0. Pre-liquidation introduces a buffer zone.\n\n-   **Standard Liquidation**: Triggers when `LTV >= LLTV`.\n-   **Pre-Liquidation**: Triggers when `preLLTV <= LTV < LLTV`.\n\nA 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.\n\n### Key Benefits for the Borrower\n\n1.  **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.\n\n2.  **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.\n\n3.  **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.\n\n### The Pre-Liquidation Mechanism\n\nWhen a position enters the pre-liquidation zone, the mechanism works as follows:\n\n-   **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)**.\n-   **Smaller Incentive:** The pre-liquidator receives a smaller bonus, defined by the **preLIF (Pre-Liquidation Incentive Factor)**.\n-   **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.\n\n### Example: Standard vs. Pre-Liquidation\n\nConsider a user with a position in a market where `LLTV` is 86% and they've opted into pre-liquidation with a `preLLTV` of 83%.\n\n| Scenario                                | Standard Liquidation (No Pre-liquidation)                                 | With Pre-Liquidation                                                                |\n| --------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| **Trigger**                             | The collateral price drops until LTV hits 86%.                            | The collateral price drops until LTV hits 84%.                                      |\n| **Liquidation Event**                   | A liquidator repays **100%** of the debt.                                 | A pre-liquidator repays **~12%** of the debt.                                       |\n| **Penalty (Incentive)**                 | The liquidator receives a **~5%** bonus (LIF).                            | The pre-liquidator receives a **~4%** bonus (preLIF).                               |\n| **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. |\n\nIn this case, pre-liquidation acted as a circuit breaker, preventing a more damaging full liquidation.\n\n### Integration Considerations\n\nWhile pre-liquidation is a powerful safety feature, it is an advanced concept.\n\n-   **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.\n-   **Parameter Complexity:** Pre-liquidation introduces additional parameters (`preLLTV`, `preLCF`, etc.) that need to be managed and clearly explained.\n-   **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.\n\nFor 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."
  },
  "/build/borrow/concepts/public-allocator/": {
    "title": "Public Allocator: Just-in-Time Liquidity",
    "url": "https://docs.morpho.org/build/borrow/concepts/public-allocator/",
    "section": "Build",
    "content": "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.\n\nThe **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.\n\n## What is the Public Allocator?\n\nThe 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.\n\nFrom 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.\n\n## How It Works for a Borrower\n\nImagine a user wants to borrow 1,000 WETH from the `wstETH/WETH` market, but that specific market only has 200 WETH available.\n\n#### 1. Liquidity Request\nThe user (or your application on their behalf) initiates the borrow. The system detects the 800 WETH shortfall.\n\n#### 2. Public Allocator Triggered\nInstead 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).\n\n#### 3. Liquidity Reallocated\nThe Public Allocator executes a `reallocate` function, moving the 800 WETH into the target `wstETH/WETH` market.\n\n#### 4. Borrow Executed\nThe `wstETH/WETH` market now has 1,000 WETH available. The user's borrow transaction succeeds seamlessly.\n\nWhen 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.\n\n## Curator Controls: Flow Caps\n\nThis 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.\n\n-   `maxIn`: The maximum amount of assets that can be moved *into* a market by the Public Allocator.\n-   `maxOut`: The maximum amount that can be moved *out of* a market.\n\nThese guardrails ensure that while liquidity is flexible, it always operates within the risk parameters defined by the vault's curator.\n\n## Benefits for Your Integration\n\n-   **Offer Deeper Liquidity:** Allow your users to execute large borrows without worrying about the liquidity of a single market.\n-   **Improve User Experience:** Abstract away the complexity of fragmented liquidity. Users interact with one market and get the liquidity of many.\n-   **Maintain Security:** Benefit from a pool-like experience while retaining the underlying risk isolation of Morpho's core architecture.\n\nNow that you understand what the Public Allocator does, learn how to integrate it into your borrowing flow.\n\n➡️ **Next: [Triggering the Public Allocator Tutorial](/build/borrow/tutorials/public-allocator)**"
  },
  "/build/borrow/concepts/rewards/": {
    "title": "Rewards for Borrowers",
    "url": "https://docs.morpho.org/build/borrow/concepts/rewards/",
    "section": "Build",
    "content": "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.\n\n## Overview\n\nAs a borrower on Morpho, you can earn rewards for borrowing an asset from a market.\n\n**Net Cost Calculation:**\n```\nNet Borrow APY = Borrow APY - Borrow Rewards APR\n```\n\nIt is also possible to incentivize a simple collateral deposit (without the borrow action required).\n\nIn favorable conditions, rewards can exceed borrow costs, resulting in **negative net APY** (borrowers earn while borrowing).\n\nRewards 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.\n\n**Borrow Rewards:**\n- Incentives for borrowing an asset\n- Accrue based on outstanding borrow balance\n- Offset borrowing costs directly\n\n### Net Cost Display Priority\n\nFor borrow products, users care most about **net cost after all rewards**:\n\n- Display net APY prominently\n- Highlight when borrowing becomes profitable (negative net APY)\n- Show breakdown: borrow cost - borrow rewards\n\n## Distribution System\n\nRewards 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.\n\nThe claiming process is **identical** for all Morpho users, regardless of whether they're depositors, borrowers, or collateral suppliers.\n\n**For complete details on distribution systems, see:**\n- [Distribution System](/build/rewards/concepts/distribution-system)\n- [Reward Campaigns](/build/rewards/concepts/reward-campaigns)\n\n## Learn More\n\nFor comprehensive information about integrating rewards:\n\n- **[Rewards Integration Guide](/build/rewards/get-started)**: Complete overview and integration paths\n- **[Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)**: Complete API queries and calculations\n- **[Claim Rewards](/build/rewards/tutorials/claim-rewards)**: Implementation for both Merkl and URD\n- **[Integrate Display](/build/rewards/tutorials/integrate-display)**: UI/UX best practices\n\n## Implementation\n\nFor practical implementation guidance specific to borrow products, see:\n- [Integrate Rewards for Borrow Products](/build/borrow/tutorials/rewards)"
  },
  "/build/borrow/get-started/": {
    "title": "Morpho Markets for Borrow products",
    "url": "https://docs.morpho.org/build/borrow/get-started/",
    "section": "Build",
    "content": "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.\n\nUsers 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.\n\nNote: \nBorrowers will see interests accruing in their debt position, while the collateral remains idle, and do not yield.\n\n## Key Components of Borrow Integration\n\nWhen building borrow products with Morpho Markets, you need to integrate three main components:\n\n1.  **Market Operations**: Supplying collateral, borrowing, repaying, and withdrawing collateral.\n2.  **Position Health Management**: Real-time tracking of Loan-to-Value (LTV), Health Factor, and liquidation risk.\n3.  **Rewards Integration**: Discovery and claiming of incentives for supplying collateral or borrowing.\n\nIntegrating Borrow gives users access to:\n\n1.  **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.\n2.  **Capital Efficiency**: The underlying interest rate models are designed for high utilization, which translates to better rates for both borrowers and lenders.\n3.  **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.\n\n## Technical Components\n\nFrom a technical standpoint, integrating Borrow involves:\n\n1.  **Market Discovery and Display**: Implementing systems to discover available markets and display their key parameters (Collateral/Loan Asset, APYs, TVL, LLTV, Oracle, IRM).\n\n2.  **Transaction Handling**: Building the interface and backend support, including asset approvals, transaction monitoring, and position updates. Here are the four core market operations:\n    -   `supplyCollateral`\n    -   `borrow`\n    -   `repay`\n    -   `withdrawCollateral`\n\n3.  **Position Management**: Creating interfaces for users to:\n    -   View their current collateral and debt balances.\n    -   Clearly track their **Health Factor** and current LTV.\n    -   Perform any of the four core market operations.\n    -   Claim any available rewards.\n\n4.  **Liquidation Risk Transparency**: Building clear and prominent displays that communicate:\n    -   The user's current Health Factor.\n    -   The market's Liquidation Loan-to-Value (LLTV), which is the LTV at which liquidation can occur.\n    -   Visual warnings when a user's position health is declining.\n\n## Rewards Considerations\n\nA complete Borrow integration should include rewards functionality. Many markets offer incentives for both borrowers and collateral suppliers through reward campaigns.\n\nKey aspects to integrate:\n\n-   **Rewards Discovery**: Identify available reward programs for borrowers and collateral suppliers\n-   **Rewards Tracking**: Display accruing and claimable rewards in real-time\n-   **Claiming Process**: Implement claim functionality using Merkle-proof based distribution systems (URD and Merkl)\n-   **Multi-Token Support**: Handle various reward tokens from different incentive programs\n-   **Program Awareness**: Display active campaigns and their respective parameters\n\nFor detailed implementation guidance, see the [Rewards integration guide](/build/rewards/get-started).\n\n## Assets Flow - Borrow\n\nUnderstanding the complete flow of assets is crucial for a proper integration:\n\n### 1. Supply Collateral\n- A user selects a market (e.g., wstETH/WETH).\n- They supply a collateral asset (wstETH) to the market. This collateral secures their future debt.\n\n### 2. Borrow\n- The user borrows the loan asset (WETH) from the same market.\n- The amount they can borrow is limited by the value of their collateral and the market's Liquidation Loan-to-Value (LLTV).\n- The user's **Health Factor** is established, representing their position's safety from liquidation.\n\n### 3. Repay\n- The user repays the loan asset (WETH), either partially or in full.\n- Repaying debt reduces their LTV and increases their Health Factor, making their position safer.\n- Interest continuously accrues on the outstanding debt, which must also be repaid.\n\n### 4. Withdraw Collateral\n- After repaying debt, the user can withdraw their collateral.\n- 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.\n\n## Functional Integration Requirements\n\nFor a complete Borrow integration, your system needs to implement:\n\n1.  **Read Operations**:\n    -   Query market parameters (LLTV, oracle, irm, etc.).\n    -   Fetch real-time market state (APYs, total supply/borrow, utilization).\n    -   Display user-specific position data (collateral, debt, **Health Factor**).\n    -   Present available liquidity, including reallocatable liquidity from the Public Allocator.\n\n2.  **Write Operations**:\n    -   Handle token approvals for supplying collateral and repaying debt.\n    -   Execute `supplyCollateral`, `borrow`, `repay`, and `withdrawCollateral`.\n    -   Facilitate claiming any associated rewards.\n\n3.  **Monitoring Capabilities**:\n    -   Track position Health Factor changes in real-time.\n    -   Alert users when their position approaches the liquidation threshold.\n    -   Update market data and interest rates dynamically.\n\n## Risk Considerations\n\nA responsible Borrow integration must clearly communicate the following risks to the user:\n\n1.  **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.\n2.  **Oracle Risk**: Inaccurate or manipulated price feeds from the market's oracle can lead to premature liquidations or prevent timely ones, causing bad debt.\n3.  **Smart Contract Risk**: Exposure to vulnerabilities in the Morpho core contracts.\n4.  **Market Liquidity Risk**: Low liquidity in a market can prevent users from borrowing or impact interest rates significantly.\n5.  **Counterparty Risk**: The risk associated with the assets themselves (e.g., de-pegging of a stablecoin or centralization risk of a token).\n\nBy properly integrating these components and transparently communicating risks, your application can offer users direct access to Morpho's efficient and secure lending markets."
  },
  "/build/borrow/guides/gelato/": {
    "title": "Guide: Integrating Gasless Crypto-Backed Loans with Gelato",
    "url": "https://docs.morpho.org/build/borrow/guides/gelato/",
    "section": "Build",
    "content": "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.\n\nWe will walk through the entire process, from initial setup to implementing the core supply and borrow functionalities.\n\n**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/)**.\n\n## Architecture Overview\n\nThe integration relies on two key components working in concert:\n\n1.  **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.\n2.  **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.\n\nHere is a high-level view of the interaction flow:\n\n```\n┌─────────────────┐\n│    End User     │\n└─────────────────┘\n         │\n         │ Interacts with\n         ▼\n┌─────────────────┐\n│ Your Application│\n└─────────────────┘\n         │\n         │ Uses\n         ▼\n┌─────────────────┐\n│ Gelato Smart    │\n│ Wallet SDK      │\n└─────────────────┘\n         │\n         │ 1. Creates Smart Account & Session\n         │ 2. Bundles & Sponsors Transactions\n         ▼\n┌─────────────────┐\n│   Blockchain    │\n└─────────────────┘\n         │\n         │ Executes atomic calls\n         ▼\n┌─────────────────┐\n│ Morpho Protocol │\n│   Contracts     │\n│ (supply, borrow)│\n└─────────────────┘\n```\n\n### Part 1: Setup and Configuration\n\nThis guide assumes you are building a React application with TypeScript. A correct setup is critical for a stable and secure application.\n\n#### Step 1: Install Dependencies\nFirst, install all necessary packages from Gelato, Dynamic, and other required libraries.\n\n```bash\nnpm install @gelatonetwork/smartwallet @dynamic-labs/sdk-react-core @dynamic-labs/wagmi-connector @tanstack/react-query viem wagmi\n```\n\n#### Step 2: Obtain API Keys\nYou will need two API keys:\n\n1.  **Gelato API Key**: This key is used to sponsor transactions (i.e., pay for your users' gas fees).\n    *   Go to the **[Gelato Relay App](https://relay.gelato.network/)**.\n    *   Create a new app, select the required networks, and copy your Sponsor API Key.\n\n2.  **Dynamic Environment ID**: This key connects your application to Dynamic's wallet-as-a-service infrastructure.\n    *   Sign up at the **[Dynamic Dashboard](https://www.dynamic.xyz/)**.\n    *   Create a new project and copy your Environment ID.\n\nNever 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_`).\n\n#### Step 3: Define Constants and ABIs\nFor a clean implementation, define your contract addresses, ABIs, and market parameters in a separate constants file.\n\n```typescript\n// constants.ts\nimport { base, arbitrum, optimism, polygon, scroll } from \"viem/chains\";\n\n// 1. Supported Networks\nexport const SUPPORTED_NETWORKS = {\n  [base.id]: base,\n  [arbitrum.id]: arbitrum,\n  [optimism.id]: optimism,\n  [polygon.id]: polygon,\n  [scroll.id]: scroll,\n};\n\n// 2. Contract Addresses (Example for Base Mainnet)\nexport const MORPHO_BLUE_ADDRESS = \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\nexport const USDC_ADDRESS = \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\"; // Note: Use the correct USDC address for your network\nexport const CBBTC_ADDRESS = \"0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf\"; // Note: Use the correct cbBTC address for your network\n\n// 3. Morpho Market Parameters (Example for cbBTC/USDC market)\n// NOTE: For a production app, fetch these dynamically. See the \"Get Data\" tutorials.\nexport const CBBTC_USDC_MARKET_PARAMS = {\n  loanToken: USDC_ADDRESS,\n  collateralToken: CBBTC_ADDRESS,\n  oracle: \"0x...\", // The specific oracle for this market\n  irm: \"0x...\",     // The specific IRM for this market\n  lltv: BigInt(\"860000000000000000\"), // 86%\n};\n\n// 4. Minimal ABI fragments\nexport const ERC20_ABI = [\n  {\n    \"inputs\": [{\"name\":\"spender\",\"type\":\"address\"}, {\"name\":\"amount\",\"type\":\"uint256\"}],\n    \"name\": \"approve\",\n    \"outputs\": [{\"name\":\"\",\"type\":\"bool\"}],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\",\n  },\n];\n\nexport const MORPHO_BLUE_ABI = [\n  // supplyCollateral, borrow, repay etc.\n  // NOTE: A more complete ABI is needed. See official Morpho resources.\n];\n```\n\n#### Step 4: Configure the Context Provider\nWrap your application's root with the `GelatoSmartWalletContextProvider` and `QueryClientProvider`. This makes the smart wallet client and user session available throughout your component tree.\n\n```tsx\n// In your main App.tsx or a layout component\nimport { GelatoSmartWalletContextProvider } from \"@gelatonetwork/smartwallet\";\nimport { dynamic } from \"@gelatonetwork/smartwallet/adapters\";\nimport { wagmi } from \"@gelatonetwork/smartwallet/networks\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { http } from \"viem\";\nimport { SUPPORTED_NETWORKS } from \"./constants\";\n\nconst queryClient = new QueryClient();\nconst chains = Object.values(SUPPORTED_NETWORKS);\nconst transports = chains.reduce((acc, chain) => {\n  acc[chain.id] = http();\n  return acc;\n}, {} as Record<number, ReturnType<typeof http>>);\n\n\nconst App = ({ children }: { children: React.ReactNode }) => {\n  return (\n    <GelatoSmartWalletContextProvider\n      settings={{\n        // Specify the smart account implementation\n        scw: { type: \"gelato\" },\n        // Your Gelato Sponsor API Key\n        apiKey: process.env.NEXT_PUBLIC_GELATO_API_KEY as string,\n        // Connects to Dynamic for Wallet-as-a-Service\n        waas: dynamic(process.env.NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID as string),\n        // Standard wagmi configuration for chains and transports\n        wagmi: wagmi({ chains, transports }),\n      }}\n    >\n      <QueryClientProvider client={queryClient}>\n        {children}\n      </QueryClientProvider>\n    </GelatoSmartWalletContextProvider>\n  );\n};\n```\n\n### Part 3: Production Considerations\n\n#### Security Best Practices\n\n*   **Key Management**: Never expose private keys or API keys in client-side code. Use secure environment variables.\n*   **Input Validation**: Always validate and sanitize user inputs before constructing transactions to prevent injection attacks.\n*   **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.\n*   **Dependency Management**: Keep all SDKs and libraries updated to their latest stable versions to benefit from security patches.\n\n#### Common Issues & Troubleshooting\n\n| Issue                             | Solution                                                                                                   |\n| --------------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| **Transaction fails silently**      | Check the browser console for detailed error messages. Common causes include incorrect contract addresses or ABI definitions. |\n| **\"Insufficient Allowance\"**        | Ensure the `approve` call is included in your bundle and the amount is sufficient.                               |\n| **\"Provider Not Found\"**          | Verify that `GelatoSmartWalletContextProvider` correctly wraps your entire application or component tree.      |\n| **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. |\n\n## Key Resources & Next Steps\n\nYou now have the building blocks to integrate a powerful, abstracted lending experience. To learn more, explore these resources:\n\n    Live Demo\n    Try the complete user flow in the official Morpho x Gelato demo application.\n    \n      View Demo ↗\n  \n\n  Gelato Smart Wallet SDK Docs\n    Dive deeper into the Gelato SDK's features, including different account types and payment options.\n    \n      Read Docs ↗\n    \n\n  Morpho Borrow Concepts\n    Understand the core concepts of Morpho Markets, including LTV, health factor, and liquidations.\n    \n      Learn More →\n    \n\n  Community Support\n    Use the Morpho Help Page to ask questions and get help from Morpho.\n    \n      Reach out ↗"
  },
  "/build/borrow/resources/all/": {
    "title": "Borrow: Developer Resources",
    "url": "https://docs.morpho.org/build/borrow/resources/all/",
    "section": "Build",
    "content": "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).\n\n## Onchain Data & Contracts\n\nThese resources are for interacting directly with the blockchain.\n\n-   **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).\n-   **Contract Specifications**: For detailed function signatures, events, and errors, refer to the canonical contract specs:\n    -   [Morpho Core Contract](/get-started/resources/contracts/morpho/)\n    -   [Public Allocator](/get-started/resources/contracts/public-allocator/)\n    -   [Bundlers](/get-started/resources/contracts/bundlers/)\n-   **GitHub Repositories**:\n    -   [`morpho-blue`](https://github.com/morpho-org/morpho-blue): The core protocol contracts.\n    -   [`public-allocator`](https://github.com/morpho-org/public-allocator): The contract for just-in-time liquidity.\n\n## Offchain Data & Tools\n\nThese tools provide easier access to onchain data for frontends, backends, and analytics.\n\n-   **Morpho API (Recommended)**: The simplest way to fetch comprehensive data about markets, their states, APYs, and user positions.\n    -   **API Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql)\n    -   **Tutorial**: [Using the API for Markets](/build/borrow/tutorials/get-data#get-data)\n-   **Morpho Subgraphs**: For developers who prefer querying via The Graph protocol.\n    -   **Tutorial**: [Using Subgraphs for Markets](/tools/offchain/subgraphs/)\n-   **SDKs**: A suite of TypeScript libraries to accelerate your development.\n    -   **`@morpho-org/blue-sdk`**: Core, framework-agnostic classes for entities like Markets.\n    -   **`@morpho-org/blue-sdk-viem`**: Adds Viem-based fetchers to the core SDK classes for easy onchain data retrieval.\n    -   **`@morpho-org/liquidity-sdk-viem`**: A specialized SDK to calculate available liquidity, including from the Public Allocator.\n    -   **Learn more**: [Introduction to Morpho SDKs](/tools/offchain/sdks/get-started/)\n\n## Code & Examples\n\n-   **Solidity Snippets**: The [`morpho-blue-snippets`](https://github.com/morpho-org/morpho-blue-snippets) repository contains simple, educational Solidity contracts for common market interactions.\n-   **Liquidation Bots**: For advanced developers, the community has provided open-source liquidation bot examples.\n-   **Learn more**: [Community Liquidations Resources](/tools/community/liquidations/)"
  },
  "/build/borrow/tutorials/assets-flow/": {
    "title": "Supply Collateral, Borrow, Repay & Withdraw Collateral",
    "url": "https://docs.morpho.org/build/borrow/tutorials/assets-flow/",
    "section": "Build",
    "content": "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.\n\nUnlike 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.\n\nWe will cover two primary methods of interaction:\n1.  **Direct Smart Contract Integration** using Solidity.\n2.  **Offchain Integration** using the Morpho SDK with TypeScript and Viem.\n\n## Key Concepts: Assets vs. Shares\n\nThe 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.\n\n| Concept  | Functions Affected      | Description                                                                                                   |\n| -------- | ----------------------- | ------------------------------------------------------------------------------------------------------------- |\n| **Assets** | `borrow`, `repay` | The actual underlying token (e.g., USDC, WETH) that a user wants to lend or borrow.               |\n| **Shares** | `borrow`, `repay` | Internal accounting units representing a proportional claim on the market's total supply or debt. |\n\n**Best Practice:**\n- For `borrow`, using the `assets` parameter is the most common and intuitive approach for users.\n- 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.\n- Collateral (`supplyCollateral` and `withdrawCollateral`) is always handled in `assets`.\n\n## Prerequisites\n\nBefore you begin, you will need:\n-   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).\n-   An account with a balance of the collateral asset (e.g., wstETH) and the loan asset (e.g., WETH for repayments).\n\n## Method 1: Smart Contract Integration (Solidity)\n\nThis 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.\n\n### Step 1: Supply Collateral\n\nFirst, the user must supply a collateral asset to the market. This requires approving the Morpho contract to spend the collateral token.\n\n```solidity\nimport { IMorpho, MarketParams } from \"morpho-blue/src/interfaces/IMorpho.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Within your contract\nIMorpho morpho = IMorpho(0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb);\nMarketParams memory marketParams = ...; // The parameters for the chosen market\nuint256 collateralAmount = 1 ether;\n\n// 1. Approve Morpho to spend the collateral token\nIERC20(marketParams.collateralToken).approve(address(morpho), collateralAmount);\n\n// 2. Supply the collateral\nmorpho.supplyCollateral(marketParams, collateralAmount, msg.sender, \"\");\n```\n\n### Step 2: Borrow Assets\n\nOnce collateral is supplied, the user can borrow the loan asset against it.\n\n```solidity\n// Borrowing a specific amount of the loan token (asset-first approach)\nuint256 borrowAmount = 1000 * 10**18; // Example: 1000 WETH\n// The final two arguments are onBehalf and receiver\n(uint256 assetsBorrowed, ) = morpho.borrow(marketParams, borrowAmount, 0, msg.sender, msg.sender);\n```\n\nYour 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/).\n\n### Step 3: Repay Debt\n\nTo repay the loan, the user must approve the Morpho contract to spend the loan token.\n\n```solidity [Partial Repay]\n// Asset-first approach: Repay a specific amount of the loan token.\nuint256 repayAmount = 500 * 10**18;\nIERC20(marketParams.loanToken).approve(address(morpho), repayAmount);\nmorpho.repay(marketParams, repayAmount, 0, msg.sender, \"\");\n```\n```solidity [Full Repay]\n// Shares-first approach (Recommended for full repayment)\n( , uint128 borrowShares, ) = morpho.position(marketParams.id(), msg.sender);\n// Note: You need to approve a sufficient amount of the loan token first.\n// The exact asset amount can be calculated offchain or via a helper contract.\nIERC20(marketParams.loanToken).approve(address(morpho), type(uint256).max);\nmorpho.repay(marketParams, 0, borrowShares, msg.sender, \"\");\n```\n\n### Step 4: Withdraw Collateral\n\nAfter the debt is fully or partially repaid, the user can withdraw their collateral, provided their position remains healthy.\n\n```solidity\nuint256 amountToWithdraw = 0.5 ether;\n// The final two arguments are onBehalf and receiver\nmorpho.withdrawCollateral(marketParams, amountToWithdraw, msg.sender, msg.sender);\n```\n\n## Full Example: Solidity Snippet\nHere is a complete example contract demonstrating the full borrow-repay cycle.\n\nThe 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.\n\n```solidity\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport { IMorpho, MarketParams, Market, Position } from \"morpho-blue/src/interfaces/IMorpho.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { MorphoBalancesLib } from \"morpho-blue/src/libraries/periphery/MorphoBalancesLib.sol\";\nimport { MarketParamsLib } from \"morpho-blue/src/libraries/MarketParamsLib.sol\";\n\ncontract MorphoMarketInteraction {\n    using MarketParamsLib for MarketParams;\n    using MorphoBalancesLib for IMorpho;\n\n    IMorpho public immutable morpho;\n    MarketParams public immutable marketParams;\n\n    constructor(IMorpho _morpho, MarketParams memory _marketParams) {\n        morpho = _morpho;\n        marketParams = _marketParams;\n    }\n\n    function supplyCollateralAndBorrow(uint256 collateralAmount, uint256 borrowAmount) external {\n        IERC20(marketParams.collateralToken).approve(address(morpho), collateralAmount);\n        morpho.supplyCollateral(marketParams, collateralAmount, msg.sender, \"\");\n        morpho.borrow(marketParams, borrowAmount, 0, msg.sender, msg.sender);\n    }\n\n    function repayAllAndWithdraw(uint256 collateralAmount) external {\n        uint256 debt = morpho.expectedBorrowAssets(marketParams, msg.sender);\n        IERC20(marketParams.loanToken).approve(address(morpho), debt);\n\n        (, uint128 borrowShares, ) = morpho.position(marketParams.id(), msg.sender);\n        morpho.repay(marketParams, 0, borrowShares, msg.sender, \"\");\n        \n        morpho.withdrawCollateral(marketParams, collateralAmount, msg.sender, msg.sender);\n    }\n}\n\n```\n\n## Method 2: Offchain Integration (TypeScript SDK)\n\nThis method is ideal for dApp frontends or backend services. We'll use TypeScript with **Viem**.\n\n### Step 1: Setup\n\nInstall dependencies and set up your Viem client.\n```bash\nnpm install viem @morpho-org/blue-sdk @morpho-org/morpho-ts\n```\n\n```typescript\nimport { createWalletClient, http, publicActions, parseUnits } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { mainnet } from \"viem/chains\";\nimport { IMorpho_ABI } from \"@morpho-org/morpho-ts\";\n\nconst morphoAddress = \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\nconst marketParams = { ... }; // Your target market's parameters\nconst account = privateKeyToAccount(\"0x...\");\n\nconst client = createWalletClient({\n  account,\n  chain: mainnet,\n  transport: http(process.env.RPC_URL_MAINNET),\n}).extend(publicActions);\n```\n\n### Step 2: Supply Collateral & Borrow\n\nThis example combines supplying collateral and borrowing. In a real app, these would likely be separate user actions.\n\n```typescript\nconst collateralAmount = parseUnits(\"1.0\", 18); // 1 wstETH\nconst borrowAmount = parseUnits(\"2000\", 18); // 2000 WETH\n\n// 1. Approve collateral\nawait client.writeContract({\n  address: marketParams.collateralToken,\n  abi: IERC20_ABI, // A standard ERC20 ABI\n  functionName: \"approve\",\n  args: [morphoAddress, collateralAmount],\n});\n\n// 2. Supply collateral\nawait client.writeContract({\n  address: morphoAddress,\n  abi: IMorpho_ABI,\n  functionName: \"supplyCollateral\",\n  args: [marketParams, collateralAmount, account.address, \"0x\"],\n});\n\n// 3. Borrow\nawait client.writeContract({\n  address: morphoAddress,\n  abi: IMorpho_ABI,\n  functionName: \"borrow\",\n  args: [marketParams, borrowAmount, 0, account.address, account.address],\n});\n```\n### Step 3: Repay & Withdraw\n\nThis example shows a full repayment using the `shares` parameter.\n\n```typescript\n// 1. Get user's borrow shares\nconst { borrowShares } = await client.readContract({\n  address: morphoAddress,\n  abi: IMorpho_ABI,\n  functionName: \"position\",\n  args: [marketId, account.address],\n});\n\nif (borrowShares > 0) {\n    // 2. Approve repayment (for the full debt amount in assets)\n    // The Morpho SDK can help calculate the expected asset amount for the shares.\n    const expectedDebtAssets = ...; \n    await client.writeContract({\n        address: marketParams.loanToken,\n        abi: IERC20_ABI,\n        functionName: \"approve\",\n        args: [morphoAddress, expectedDebtAssets],\n    });\n\n    // 3. Repay full debt using shares\n    await client.writeContract({\n        address: morphoAddress,\n        abi: IMorpho_ABI,\n        functionName: \"repay\",\n        args: [marketParams, 0, borrowShares, account.address, \"0x\"],\n    });\n\n    // 4. Withdraw collateral\n    const collateralToWithdraw = parseUnits(\"1.0\", 18);\n    await client.writeContract({\n        address: morphoAddress,\n        abi: IMorpho_ABI,\n        functionName: \"withdrawCollateral\",\n        args: [marketParams, collateralToWithdraw, account.address, account.address],\n    });\n}\n```"
  },
  "/build/borrow/tutorials/get-data/": {
    "title": "Get Data",
    "url": "https://docs.morpho.org/build/borrow/tutorials/get-data/",
    "section": "Build",
    "content": "## Before Starting\n\nIn this tutorial, you'll see three main ways to fetch data for Morpho Markets:\n\n-   **API**: Using the Morpho public API. This is the easiest and most direct way to get comprehensive, indexed data for most applications.\n-   **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.\n-   **SDK**: Using the Morpho SDKs for pre-built abstractions that handle complex calculations (like interest accrual) and simplify development.\n\nAPI Endpoint: [api.morpho.org/graphql](https://api.morpho.org/graphql)\n\nFor 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.\n\n## Discovery and Listing\n\n### Markets List\n\nQuickly retrieve a list of all markets or filter for specific ones, like those listed for incentives.\n\n```graphql [Listed Markets]\nquery {\n  markets(where: { listed: true }) {\n    items {\n      uniqueKey\n      listed\n      lltv\n      oracleAddress\n      irmAddress\n      loanAsset {\n        address\n        symbol\n        decimals\n      }\n      collateralAsset {\n        address\n        symbol\n        decimals\n      }\n      state {\n        borrowAssets\n        supplyAssets\n        fee\n        utilization\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates how to discover new markets by listening to `CreateMarket` events from the Morpho V1 contract. The script shows how to:\n- Monitor market creation events within a specific block range\n- Parse market parameters including loan/collateral tokens, oracle, IRM, and LLTV\n- Extract and format market IDs and configuration details\n- Display results in both detailed and table formats for easy analysis\n- Handle LLTV conversion from WAD format to percentage\n\n```typescript\nimport \"dotenv/config\";\nimport { createPublicClient, http, PublicClient, parseAbiItem, Address } from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\nexport async function createMainnetClient(): Promise<PublicClient> {\n  const client = createPublicClient({\n    chain: mainnet,\n    transport: http(process.env.RPC_URL_MAINNET!, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n  \n  return client;\n}\n\n// Morpho V1 contract address\nconst MORPHO_BLUE_ADDRESS: Address = \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// Block range to search for market creations\nconst START_BLOCK = 22867292n;\nconst END_BLOCK = 22867298n;\n\n// CreateMarket event ABI\nconst CREATE_MARKET_EVENT = parseAbiItem(\n  \"event CreateMarket(bytes32 indexed id, (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams)\"\n);\n\ninterface MarketParams {\n  loanToken: Address;\n  collateralToken: Address;\n  oracle: Address;\n  irm: Address;\n  lltv: bigint;\n}\n\ninterface MarketCreationEvent {\n  id: `0x${string}`;\n  marketParams: MarketParams;\n  blockNumber: bigint;\n  transactionHash: string;\n  lltvPercentage: number;\n}\n\n/**\n * Converts LLTV from WAD format to percentage\n */\nfunction formatLLTV(lltv: bigint): number {\n  return Number(lltv) / 1e18 * 100;\n}\n\n/**\n * Formats an address to a shorter display format\n */\nfunction formatAddress(address: string): string {\n  return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nexport async function fetchNewMarketCreations(\n  client: PublicClient,\n  startBlock: bigint = START_BLOCK,\n  endBlock: bigint = END_BLOCK\n): Promise<MarketCreationEvent[]> {\n  console.log(`Fetching market creations from block ${startBlock} to ${endBlock}...`);\n  \n  // Get logs for CreateMarket events\n  const logs = await client.getLogs({\n    address: MORPHO_BLUE_ADDRESS,\n    event: CREATE_MARKET_EVENT,\n    fromBlock: startBlock,\n    toBlock: endBlock,\n  });\n\n  console.log(`Found ${logs.length} market creation(s)`);\n\n  // Parse and format the logs\n  const marketCreations: MarketCreationEvent[] = logs.map((log) => {\n    const marketParams = log.args.marketParams!;\n    return {\n      id: log.args.id!,\n      marketParams: {\n        loanToken: marketParams.loanToken,\n        collateralToken: marketParams.collateralToken,\n        oracle: marketParams.oracle,\n        irm: marketParams.irm,\n        lltv: marketParams.lltv,\n      },\n      blockNumber: log.blockNumber!,\n      transactionHash: log.transactionHash!,\n      lltvPercentage: formatLLTV(marketParams.lltv),\n    };\n  });\n\n  return marketCreations;\n}\n\nexport function displayMarketCreations(marketCreations: MarketCreationEvent[]): void {\n  if (marketCreations.length === 0) {\n    console.log(\"No new markets were created in the specified block range.\");\n    return;\n  }\n\n  console.log(\"\\n✅ --- New Morpho Markets Created --- ✅\");\n  \n  console.log(\"\\n--- Market Summary ---\");\n  console.log(`Total Markets Created: ${marketCreations.length}`);\n  \n  console.log(\"\\n--- Market Details ---\");\n  marketCreations.forEach((market, index) => {\n    console.log(`\\n${index + 1}. Market ID: ${market.id}`);\n    console.log(`   Loan Token: ${market.marketParams.loanToken}`);\n    console.log(`   Collateral Token: ${market.marketParams.collateralToken}`);\n    console.log(`   Oracle: ${formatAddress(market.marketParams.oracle)}`);\n    console.log(`   IRM: ${formatAddress(market.marketParams.irm)}`);\n    console.log(`   LLTV: ${market.lltvPercentage.toFixed(2)}%`);\n    console.log(`   Block: ${market.blockNumber}`);\n    console.log(`   Transaction: ${market.transactionHash}`);\n  });\n\n  // Display in table format for better overview\n  console.log(\"\\n--- Markets Table ---\");\n  console.log(\"ID                                                                 | Loan Token   | Collateral   | LLTV     | Block\");\n  console.log(\"-------------------------------------------------------------------+---------------+--------------+----------+----------\");\n  \n  marketCreations.forEach((market) => {\n    const shortId = `${market.id.slice(0, 8)}...${market.id.slice(-8)}`;\n    const loanToken = formatAddress(market.marketParams.loanToken);\n    const collateralToken = formatAddress(market.marketParams.collateralToken);\n    const lltv = `${market.lltvPercentage.toFixed(2)}%`.padStart(8);\n    \n    console.log(\n      `${shortId.padEnd(66)} | ${loanToken.padEnd(13)} | ${collateralToken.padEnd(12)} | ${lltv} | ${market.blockNumber}`\n    );\n  });\n\n  console.log(\"\\n----------------------------------------\");\n}\n\nexport async function main(): Promise<void> {\n  try {\n    const client = await createMainnetClient();\n    \n    // Fetch market creations in the specified block range\n    const marketCreations = await fetchNewMarketCreations(client, START_BLOCK, END_BLOCK);\n    \n    // Display the results\n    displayMarketCreations(marketCreations);\n    \n  } catch (error) {\n    console.error(\"Error fetching market creations:\", error);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFetching market creations from block 22867292 to 22867298...\nFound 1 market creation(s)\n\n✅ --- New Morpho Markets Created --- ✅\n\n--- Market Summary ---\nTotal Markets Created: 1\n\n--- Market Details ---\n\n1. Market ID: 0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540\n   Loan Token: 0xdAC17F958D2ee523a2206206994597C13D831ec7\n   Collateral Token: 0x8ddac7aa85Ce324AF75a3bFcB876375555d43BB8\n   Oracle: 0xF470...66e0\n   IRM: 0x870a...00BC\n   LLTV: 91.50%\n   Block: 22867295\n   Transaction: 0x4c9e1efb7e86f8bb15c01f3f109d88ec0a0e0d553140628dfc9d852dcc902d51\n\n--- Markets Table ---\nID                                                                 | Loan Token   | Collateral   | LLTV     | Block\n-------------------------------------------------------------------+---------------+--------------+----------+----------\n0x9a3320...03c3d540                                                | 0xdAC1...1ec7 | 0x8dda...3BB8 |   91.50% | 22867295\n\n----------------------------------------\n```\n\nThis 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.\n\n{\" \"}\n\nYou can discover markets by listening for the `CreateMarket` event emitted from the core `Morpho` contract:\n\n```solidity\n// Listen to CreateMarket events\nevent CreateMarket(\n    bytes32 indexed id,\n    MarketParams marketParams\n);\n\n// Market parameters structure\nstruct MarketParams {\n    address loanToken;\n    address collateralToken;\n    address oracle;\n    address irm;\n    uint256 lltv;\n}\n\n// Get market details by ID\nfunction idToMarketParams(bytes32 id)\n    external view returns (MarketParams memory);\n\n// Check if market exists\nfunction market(bytes32 id) external view returns (\n    uint128 totalSupplyAssets,\n    uint128 totalSupplyShares,\n    uint128 totalBorrowAssets,\n    uint128 totalBorrowShares,\n    uint128 lastUpdate,\n    uint128 fee\n);\n```\n\n**Key Functions:**\n- **Event Monitoring**: Listen to `CreateMarket` events for new markets\n- **Market Resolution**: `idToMarketParams(id)` returns full market configuration\n- **Market State**: `market(id)` returns current market liquidity and state\n- **Market ID**: Computed as `keccak256(abi.encode(marketParams))`\n\n**Event Logs**: See the [Etherscan events log](https://etherscan.io/address/0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb#events) for real examples.\n\n### Market Parameters\n\nFetch the core, immutable parameters for one or more markets.\n\n---\n\n```graphql [All Markets]\nquery {\n  markets(\n    first: 100\n    orderBy: SupplyAssetsUsd\n    orderDirection: Desc\n    where: { chainId_in: [1, 8453] }\n  ) {\n    items {\n      uniqueKey\n      loanAsset { address }\n      collateralAsset { address }\n      lltv\n      irmAddress\n      oracleAddress\n    }\n  }\n}\n```\n\n---\n\n```graphql [Unique Market]\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    uniqueKey\n    loanAsset { address }\n    collateralAsset { address }\n    lltv\n    irmAddress\n    oracleAddress\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates comprehensive market parameter operations including:\n- Decoding market IDs to parameters using `idToMarketParams`\n- Encoding market parameters to generate market IDs using keccak256\n- Validating market ID integrity by round-trip encoding/decoding\n- Checking market existence and fetching token information\n- Understanding the relationship between market parameters and their unique identifiers\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  PublicClient,\n  parseAbi,\n  Address,\n  keccak256,\n  encodeAbiParameters,\n  parseAbiParameters,\n  formatUnits,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// Morpho V1 contract address\nconst MORPHO_BLUE_ADDRESS: Address = \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// Example market ID to demonstrate\nconst EXAMPLE_MARKET_ID: `0x${string}` = \"0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540\";\n\n// Minimal Morpho V1 ABI for market parameters\nconst MORPHO_BLUE_ABI = parseAbi([\n  \"function idToMarketParams(bytes32 id) view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n  \"function market(bytes32 id) view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)\",\n]);\n\n// ERC20 ABI for token information\nconst ERC20_ABI = parseAbi([\n  \"function symbol() view returns (string)\",\n  \"function name() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n]);\n\ninterface MarketParams {\n  loanToken: Address;\n  collateralToken: Address;\n  oracle: Address;\n  irm: Address;\n  lltv: bigint;\n}\n\ninterface TokenInfo {\n  address: Address;\n  symbol: string;\n  name: string;\n  decimals: number;\n}\n\ninterface MarketInfo {\n  id: `0x${string}`;\n  params: MarketParams;\n  loanToken: TokenInfo;\n  collateralToken: TokenInfo;\n  lltvPercentage: number;\n  exists: boolean;\n}\n\ninterface MarketState {\n  totalSupplyAssets: bigint;\n  totalSupplyShares: bigint;\n  totalBorrowAssets: bigint;\n  totalBorrowShares: bigint;\n  lastUpdate: bigint;\n  fee: bigint;\n}\n\n/**\n * Converts LLTV from WAD format to percentage\n */\nfunction formatLLTV(lltv: bigint): number {\n  return Number(formatUnits(lltv, 18)) * 100;\n}\n\n/**\n * Fetches token information for a given address\n */\nasync function getTokenInfo(\n  client: PublicClient,\n  tokenAddress: Address\n): Promise<TokenInfo> {\n  try {\n    const [symbol, name, decimals] = await client.multicall({\n      contracts: [\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"name\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"decimals\" },\n      ],\n      allowFailure: false,\n    });\n\n    return {\n      address: tokenAddress,\n      symbol,\n      name,\n      decimals,\n    };\n  } catch (error) {\n    // If token info fails, return address as fallback\n    return {\n      address: tokenAddress,\n      symbol: `Token(${tokenAddress.slice(0, 6)}...)`,\n      name: `Unknown Token ${tokenAddress.slice(0, 6)}...`,\n      decimals: 18, // Default fallback\n    };\n  }\n}\n\n/**\n * Checks if a market exists by verifying if any of its state values are non-zero\n */\nasync function checkMarketExists(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<boolean> {\n  try {\n    const marketState = await client.readContract({\n      address: MORPHO_BLUE_ADDRESS,\n      abi: MORPHO_BLUE_ABI,\n      functionName: \"market\",\n      args: [marketId],\n    }) as [bigint, bigint, bigint, bigint, bigint, bigint];\n\n    // Market exists if it has been created (any non-zero state indicates creation)\n    return marketState.some(value => value > 0n);\n  } catch (error) {\n    return false;\n  }\n}\n\n/**\n * Encodes market parameters into a market ID using keccak256 hash\n */\nexport function encodeMarketId(marketParams: MarketParams): `0x${string}` {\n  const encoded = encodeAbiParameters(\n    parseAbiParameters(\"address, address, address, address, uint256\"),\n    [\n      marketParams.loanToken,\n      marketParams.collateralToken,\n      marketParams.oracle,\n      marketParams.irm,\n      marketParams.lltv,\n    ]\n  );\n  \n  return keccak256(encoded);\n}\n\n/**\n * Decodes a market ID back to market parameters by querying the Morpho V1 contract\n */\nexport async function decodeMarketId(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<MarketParams | null> {\n  try {\n    const [loanToken, collateralToken, oracle, irm, lltv] = await client.readContract({\n      address: MORPHO_BLUE_ADDRESS,\n      abi: MORPHO_BLUE_ABI,\n      functionName: \"idToMarketParams\",\n      args: [marketId],\n    }) as [Address, Address, Address, Address, bigint];\n\n    // Check if market actually exists (all zero values indicate non-existent market)\n    if (loanToken === \"0x0000000000000000000000000000000000000000\") {\n      return null;\n    }\n\n    return {\n      loanToken,\n      collateralToken,\n      oracle,\n      irm,\n      lltv,\n    };\n  } catch (error) {\n    console.error(`Error decoding market ID ${marketId}:`, error);\n    return null;\n  }\n}\n\n/**\n * Validates that encoding market parameters produces the expected market ID\n */\nexport async function validateMarketId(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<{ isValid: boolean; params: MarketParams | null; computedId: `0x${string}` | null }> {\n  const params = await decodeMarketId(client, marketId);\n  \n  if (!params) {\n    return { isValid: false, params: null, computedId: null };\n  }\n\n  const computedId = encodeMarketId(params);\n  const isValid = computedId.toLowerCase() === marketId.toLowerCase();\n\n  return { isValid, params, computedId };\n}\n\n/**\n * Retrieves comprehensive market information including parameters and token details\n */\nexport async function getMarketInfo(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<MarketInfo> {\n  console.log(`Fetching market information for ID: ${marketId}`);\n\n  const params = await decodeMarketId(client, marketId);\n  \n  if (!params) {\n    return {\n      id: marketId,\n      params: {\n        loanToken: \"0x0000000000000000000000000000000000000000\",\n        collateralToken: \"0x0000000000000000000000000000000000000000\",\n        oracle: \"0x0000000000000000000000000000000000000000\",\n        irm: \"0x0000000000000000000000000000000000000000\",\n        lltv: 0n,\n      },\n      loanToken: {\n        address: \"0x0000000000000000000000000000000000000000\",\n        symbol: \"UNKNOWN\",\n        name: \"Unknown Token\",\n        decimals: 0,\n      },\n      collateralToken: {\n        address: \"0x0000000000000000000000000000000000000000\",\n        symbol: \"UNKNOWN\", \n        name: \"Unknown Token\",\n        decimals: 0,\n      },\n      lltvPercentage: 0,\n      exists: false,\n    };\n  }\n\n  // Check if market exists\n  const exists = await checkMarketExists(client, marketId);\n\n  // Fetch token information\n  const [loanTokenInfo, collateralTokenInfo] = await Promise.all([\n    getTokenInfo(client, params.loanToken),\n    getTokenInfo(client, params.collateralToken),\n  ]);\n\n  return {\n    id: marketId,\n    params,\n    loanToken: loanTokenInfo,\n    collateralToken: collateralTokenInfo,\n    lltvPercentage: formatLLTV(params.lltv),\n    exists,\n  };\n}\n\n/**\n * Demonstrates market ID encoding and validation\n */\nexport async function demonstrateMarketIdOperations(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<void> {\n  console.log(\"=== Market ID Operations Demo ===\\n\");\n\n  // 1. Decode market ID to parameters\n  console.log(\"1. Decoding market ID to parameters...\");\n  const params = await decodeMarketId(client, marketId);\n  \n  if (!params) {\n    console.log(\"❌ Market does not exist or failed to decode\");\n    return;\n  }\n\n  console.log(\"✅ Market parameters decoded successfully:\");\n  console.log(`   Loan Token: ${params.loanToken}`);\n  console.log(`   Collateral Token: ${params.collateralToken}`);\n  console.log(`   Oracle: ${params.oracle}`);\n  console.log(`   IRM: ${params.irm}`);\n  console.log(`   LLTV: ${formatLLTV(params.lltv)}%`);\n\n  // 2. Re-encode parameters to market ID\n  console.log(\"\\n2. Re-encoding parameters to market ID...\");\n  const recomputedId = encodeMarketId(params);\n  console.log(`   Original ID:  ${marketId}`);\n  console.log(`   Computed ID:  ${recomputedId}`);\n\n  // 3. Validate the match\n  console.log(\"\\n3. Validation result:\");\n  const isMatch = recomputedId.toLowerCase() === marketId.toLowerCase();\n  console.log(`   ${isMatch ? \"✅\" : \"❌\"} Market ID validation: ${isMatch ? \"PASS\" : \"FAIL\"}`);\n\n  // 4. Check if market exists onchain\n  console.log(\"\\n4. Checking market existence...\");\n  const exists = await checkMarketExists(client, marketId);\n  console.log(`   ${exists ? \"✅\" : \"❌\"} Market exists onchain: ${exists ? \"YES\" : \"NO\"}`);\n}\n\n/**\n * Displays comprehensive market information\n */\nexport function displayMarketInfo(marketInfo: MarketInfo): void {\n  console.log(\"\\n✅ --- Morpho Market Parameters --- ✅\");\n\n  console.log(`\\n--- Market Overview ---`);\n  console.log(`Market ID: ${marketInfo.id}`);\n  console.log(`Exists: ${marketInfo.exists ? \"✅ Yes\" : \"❌ No\"}`);\n\n  if (!marketInfo.exists) {\n    console.log(\"This market does not exist on Morpho V1.\");\n    return;\n  }\n\n  console.log(`\\n--- Market Parameters ---`);\n  console.log(`Loan Token: ${marketInfo.loanToken.name} (${marketInfo.loanToken.symbol})`);\n  console.log(`  Address: ${marketInfo.params.loanToken}`);\n  console.log(`  Decimals: ${marketInfo.loanToken.decimals}`);\n  \n  console.log(`Collateral Token: ${marketInfo.collateralToken.name} (${marketInfo.collateralToken.symbol})`);\n  console.log(`  Address: ${marketInfo.params.collateralToken}`);\n  console.log(`  Decimals: ${marketInfo.collateralToken.decimals}`);\n\n  console.log(`Oracle: ${marketInfo.params.oracle}`);\n  console.log(`IRM (Interest Rate Model): ${marketInfo.params.irm}`);\n  console.log(`LLTV (Loan-to-Value): ${marketInfo.lltvPercentage.toFixed(2)}%`);\n\n  console.log(\"\\n--- Encoded Parameters ---\");\n  console.log(`LLTV (Raw): ${marketInfo.params.lltv.toString()}`);\n  console.log(`Market ID Validation: ${encodeMarketId(marketInfo.params) === marketInfo.id ? \"✅ Valid\" : \"❌ Invalid\"}`);\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Main function to demonstrate market parameter operations\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    \n    // Demonstrate market ID operations\n    await demonstrateMarketIdOperations(client, EXAMPLE_MARKET_ID);\n    \n    // Get comprehensive market information\n    const marketInfo = await getMarketInfo(client, EXAMPLE_MARKET_ID);\n    \n    // Display results\n    displayMarketInfo(marketInfo);\n    \n  } catch (error) {\n    console.error(\"Error in market parameters script:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\n=== Market ID Operations Demo ===\n\n1. Decoding market ID to parameters...\n✅ Market parameters decoded successfully:\n   Loan Token: 0xdAC17F958D2ee523a2206206994597C13D831ec7\n   Collateral Token: 0x8ddac7aa85Ce324AF75a3bFcB876375555d43BB8\n   Oracle: 0xF47020f01e77257Fe86B9ECb36552486E0Ae66e0\n   IRM: 0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC\n   LLTV: 91.5%\n\n2. Re-encoding parameters to market ID...\n   Original ID:  0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540\n   Computed ID:  0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540\n\n3. Validation result:\n   ✅ Market ID validation: PASS\n\n4. Checking market existence...\n   ✅ Market exists onchain: YES\nFetching market information for ID: 0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540\n\n✅ --- Morpho Market Parameters --- ✅\n\n--- Market Overview ---\nMarket ID: 0x9a33209eee9e93f5f7aed04085f9f5e0ce9a7a103c476f5c30a0e5ca03c3d540\nExists: ✅ Yes\n\n--- Market Parameters ---\nLoan Token: Tether USD (USDT)\n  Address: 0xdAC17F958D2ee523a2206206994597C13D831ec7\n  Decimals: 6\nCollateral Token: Pendle Market Wrapped (PENDLE-LPT-WRAPPED)\n  Address: 0x8ddac7aa85Ce324AF75a3bFcB876375555d43BB8\n  Decimals: 18\nOracle: 0xF47020f01e77257Fe86B9ECb36552486E0Ae66e0\nIRM (Interest Rate Model): 0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC\nLLTV (Loan-to-Value): 91.50%\n\n--- Encoded Parameters ---\nLLTV (Raw): 915000000000000000\nMarket ID Validation: ✅ Valid\n\n----------------------------------------\n```\n\nThis example demonstrates the bidirectional relationship between market parameters and market IDs, essential for understanding how Morpho Markets are uniquely identified and accessed.\n\n{\" \"}\n\nYou can retrieve market parameters by using the `idToMarketParams` view function on the `Morpho` contract, passing the `marketId`.\n\n```solidity\n// Get market parameters from market ID\n(\n    address loanToken,\n    address collateralToken,\n    address oracle,\n    address irm,\n    uint256 lltv\n) = IMorpho(morpho).idToMarketParams(marketId);\n\n// Generate market ID from parameters\nstruct MarketParams {\n    address loanToken;\n    address collateralToken;\n    address oracle;\n    address irm;\n    uint256 lltv;\n}\n\n// Market ID is the keccak256 hash of encoded parameters\nbytes32 marketId = keccak256(abi.encode(marketParams));\n\n// Check if market exists\n(\n    uint128 totalSupplyAssets,\n    uint128 totalSupplyShares,\n    uint128 totalBorrowAssets,\n    uint128 totalBorrowShares,\n    uint128 lastUpdate,\n    uint128 fee\n) = IMorpho(morpho).market(marketId);\n\n// Market exists if any state value > 0\nbool marketExists = totalSupplyAssets > 0 || totalSupplyShares > 0 ||\n                   totalBorrowAssets > 0 || totalBorrowShares > 0;\n```\n\n**Key Functions:**\n- **Parameter Lookup**: `idToMarketParams(marketId)` returns all market configuration\n- **Market ID Generation**: `keccak256(abi.encode(marketParams))` creates unique identifier\n- **Existence Check**: `market(marketId)` returns state (non-zero values indicate existence)\n- **Parameter Validation**: Re-encode parameters to verify market ID integrity\n\n**Important Notes:**\n- Market IDs are deterministic based on parameters\n- Non-existent markets return zero values from `idToMarketParams`\n- LLTV is stored in WAD format (18 decimals)\n\n## Market Metrics\n\n### Total Collateral, Borrow & Supply\n\nGet the real-time state of liquidity and debt in a market.\n\n---\n\n```graphql [All Markets]\nquery {\n    markets(\n      first: 100\n      orderBy: SupplyAssetsUsd\n      orderDirection: Desc\n      where: { chainId_in: [1, 8453] }\n    ) {\n      items {\n        uniqueKey\n        state {\n          collateralAssets\n          collateralAssetsUsd\n          borrowAssets\n          borrowAssetsUsd\n          supplyAssets\n          supplyAssetsUsd\n          liquidityAssets\n          liquidityAssetsUsd\n        }\n      }\n    }\n  }\n```\n\n---\n\n```graphql [Unique Market]\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    state {\n      collateralAssets\n      borrowAssets\n      supplyAssets\n      liquidityAssets\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates comprehensive market liquidity analysis including:\n- Real-time interest accrual for supply and borrow assets\n- Collateral tracking (which doesn't accrue interest)\n- Market utilization and available liquidity calculations\n- Comparison between stale (last update) and current (accrued) values\n- Efficient batch processing for multiple markets\n- Important distinction: only loan token amounts (supply/borrow) accrue interest, collateral remains static\n\nThe `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.\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// Morpho V1 contract address\nconst MORPHO_BLUE_ADDRESS: Address = \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// Example market ID for demonstration\nconst EXAMPLE_MARKET_ID: `0x${string}` = \"0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\";\n\n// Morpho V1 ABI for market operations\nconst MORPHO_BLUE_ABI = parseAbi([\n  \"function market(bytes32 id) view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)\",\n  \"function idToMarketParams(bytes32 id) view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n  \"function position(bytes32 id, address user) view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral)\",\n]);\n\n// Interest Rate Model ABI\nconst IRM_ABI = parseAbi([\n  \"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) view returns (uint256)\",\n]);\n\n// ERC20 ABI for token information\nconst ERC20_ABI = parseAbi([\n  \"function symbol() view returns (string)\",\n  \"function name() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n  \"function totalSupply() view returns (uint256)\",\n]);\n\ntype MarketParams = {\n  readonly loanToken: Address;\n  readonly collateralToken: Address;\n  readonly oracle: Address;\n  readonly irm: Address;\n  readonly lltv: bigint;\n};\n\ntype MarketState = {\n  readonly totalSupplyAssets: bigint;\n  readonly totalSupplyShares: bigint;\n  readonly totalBorrowAssets: bigint;\n  readonly totalBorrowShares: bigint;\n  readonly lastUpdate: bigint;\n  readonly fee: bigint;\n};\n\ninterface TokenInfo {\n  address: Address;\n  symbol: string;\n  name: string;\n  decimals: number;\n}\n\ninterface MarketLiquidityInfo {\n  marketId: `0x${string}`;\n  params: MarketParams;\n  staleState: MarketState;\n  currentState: MarketState;\n  loanToken: TokenInfo;\n  collateralToken: TokenInfo;\n  lltvPercentage: number;\n  // Current (accrued) values\n  totalSupplyAssets: bigint;\n  totalBorrowAssets: bigint;\n  totalCollateralAssets: bigint;\n  // Formatted values\n  formattedTotalSupply: string;\n  formattedTotalBorrow: string;\n  formattedTotalCollateral: string;\n  // Metrics\n  utilization: bigint;\n  utilizationPercentage: number;\n  availableLiquidity: bigint;\n  formattedAvailableLiquidity: string;\n  interestAccrued: bigint;\n  formattedInterestAccrued: string;\n  lastUpdateTime: Date;\n  blockTimestamp: bigint;\n}\n\nconst WAD = 10n ** 18n;\n\nconst wMulDown = (x: bigint, y: bigint): bigint => (x * y) / WAD;\nconst wDivUp = (x: bigint, y: bigint): bigint => (x * WAD + y - 1n) / y;\n\nconst wTaylorCompounded = (x: bigint, n: bigint): bigint => {\n  const firstTerm = x * n;\n  const secondTerm = (firstTerm * firstTerm) / (2n * WAD);\n  const thirdTerm = (secondTerm * firstTerm) / (3n * WAD);\n  return firstTerm + secondTerm + thirdTerm;\n};\n\n/**\n * Formats LLTV from WAD format to percentage\n */\nfunction formatLLTV(lltv: bigint): number {\n  return Number(formatUnits(lltv, 18)) * 100;\n}\n\n/**\n * Formats utilization from WAD format to percentage\n */\nfunction formatUtilization(utilization: bigint): number {\n  return Number(formatUnits(utilization, 16)); // 18 - 2 = 16 for percentage\n}\n\n/**\n * Fetches token information for a given address\n */\nasync function getTokenInfo(\n  client: PublicClient,\n  tokenAddress: Address\n): Promise<TokenInfo> {\n  try {\n    const [symbol, name, decimals] = await client.multicall({\n      contracts: [\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"name\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"decimals\" },\n      ],\n      allowFailure: false,\n    });\n\n    return {\n      address: tokenAddress,\n      symbol,\n      name,\n      decimals,\n    };\n  } catch (error) {\n    return {\n      address: tokenAddress,\n      symbol: `Token(${tokenAddress.slice(0, 6)}...)`,\n      name: `Unknown Token ${tokenAddress.slice(0, 6)}...`,\n      decimals: 18,\n    };\n  }\n}\n\n/**\n * Accrues interest on a market from its last update time to the current block's timestamp.\n * This updates the total supply and borrow assets but NOT the collateral (which doesn't accrue interest).\n */\nfunction accrueInterests(\n  marketState: MarketState,\n  borrowRate: bigint,\n  blockTimestamp: bigint\n): { accruedState: MarketState; interestAccrued: bigint } {\n  const elapsed = blockTimestamp - marketState.lastUpdate;\n  \n  if (elapsed === 0n || marketState.totalBorrowAssets === 0n) {\n    return { \n      accruedState: marketState, \n      interestAccrued: 0n \n    };\n  }\n\n  const interest = wMulDown(\n    marketState.totalBorrowAssets, \n    wTaylorCompounded(borrowRate, elapsed)\n  );\n\n  const accruedState = {\n    ...marketState,\n    totalSupplyAssets: marketState.totalSupplyAssets + interest,\n    totalBorrowAssets: marketState.totalBorrowAssets + interest,\n    lastUpdate: blockTimestamp,\n  };\n\n  return { accruedState, interestAccrued: interest };\n}\n\n/**\n * Calculates total collateral across all positions in a market.\n * Collateral doesn't accrue interest, so we can sum it directly.\n */\nasync function getTotalCollateralAssets(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<bigint> {\n  // Note: This is a simplified approach. In practice, you'd need to:\n  // 1. Track all position holders (via events or subgraph)\n  // 2. Sum their collateral amounts\n  // For demonstration, we'll use a placeholder approach\n  \n  // This would require tracking all users who have positions in this market\n  // For now, we'll return 0n as a placeholder\n  // In a real implementation, you'd:\n  // - Listen to SupplyCollateral events\n  // - Track all unique addresses\n  // - Sum their current collateral positions\n  \n  console.log(\"Note: Total collateral calculation requires tracking all position holders\");\n  return 0n;\n}\n\n/**\n * Retrieves comprehensive market liquidity information including real-time accrued values.\n */\nexport async function getMarketLiquidityInfo(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<MarketLiquidityInfo> {\n  console.log(`Fetching liquidity information for market: ${marketId}`);\n\n  // Get current block timestamp\n  const block = await client.getBlock({ blockTag: \"latest\" });\n  const blockTimestamp = block.timestamp;\n\n  // Get market state and parameters\n  const [marketStateResult, marketParamsResult] = await client.multicall({\n    contracts: [\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"market\", args: [marketId] },\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"idToMarketParams\", args: [marketId] },\n    ],\n    allowFailure: false,\n  });\n\n  const staleState: MarketState = {\n    totalSupplyAssets: marketStateResult[0],\n    totalSupplyShares: marketStateResult[1],\n    totalBorrowAssets: marketStateResult[2],\n    totalBorrowShares: marketStateResult[3],\n    lastUpdate: marketStateResult[4],\n    fee: marketStateResult[5],\n  };\n\n  const params: MarketParams = {\n    loanToken: marketParamsResult[0],\n    collateralToken: marketParamsResult[1],\n    oracle: marketParamsResult[2],\n    irm: marketParamsResult[3],\n    lltv: marketParamsResult[4],\n  };\n\n  // Get token information\n  const [loanToken, collateralToken] = await Promise.all([\n    getTokenInfo(client, params.loanToken),\n    getTokenInfo(client, params.collateralToken),\n  ]);\n\n  // Initialize values\n  let currentState = staleState;\n  let interestAccrued = 0n;\n\n  // Calculate current state with interest accrual if IRM is set\n  if (params.irm !== \"0x0000000000000000000000000000000000000000\") {\n    // Get borrow rate from IRM\n    const borrowRate = await client.readContract({\n      address: params.irm,\n      abi: IRM_ABI,\n      functionName: \"borrowRateView\",\n      args: [params, staleState],\n    }) as bigint;\n\n    // Accrue interest to get current state\n    const accrualResult = accrueInterests(staleState, borrowRate, blockTimestamp);\n    currentState = accrualResult.accruedState;\n    interestAccrued = accrualResult.interestAccrued;\n  }\n\n  // Get total collateral (doesn't accrue interest)\n  const totalCollateralAssets = await getTotalCollateralAssets(client, marketId);\n\n  // Calculate metrics\n  const utilization = currentState.totalSupplyAssets > 0n \n    ? wDivUp(currentState.totalBorrowAssets, currentState.totalSupplyAssets)\n    : 0n;\n\n  const availableLiquidity = currentState.totalSupplyAssets - currentState.totalBorrowAssets;\n\n  return {\n    marketId,\n    params,\n    staleState,\n    currentState,\n    loanToken,\n    collateralToken,\n    lltvPercentage: formatLLTV(params.lltv),\n    totalSupplyAssets: currentState.totalSupplyAssets,\n    totalBorrowAssets: currentState.totalBorrowAssets,\n    totalCollateralAssets,\n    formattedTotalSupply: formatUnits(currentState.totalSupplyAssets, loanToken.decimals),\n    formattedTotalBorrow: formatUnits(currentState.totalBorrowAssets, loanToken.decimals),\n    formattedTotalCollateral: formatUnits(totalCollateralAssets, collateralToken.decimals),\n    utilization,\n    utilizationPercentage: formatUtilization(utilization),\n    availableLiquidity,\n    formattedAvailableLiquidity: formatUnits(availableLiquidity, loanToken.decimals),\n    interestAccrued,\n    formattedInterestAccrued: formatUnits(interestAccrued, loanToken.decimals),\n    lastUpdateTime: new Date(Number(staleState.lastUpdate) * 1000),\n    blockTimestamp,\n  };\n}\n\n/**\n * Retrieves liquidity information for multiple markets efficiently\n */\nexport async function getMultipleMarketsLiquidity(\n  client: PublicClient,\n  marketIds: `0x${string}`[]\n): Promise<MarketLiquidityInfo[]> {\n  console.log(`Fetching liquidity information for ${marketIds.length} markets...`);\n\n  const liquidityPromises = marketIds.map(marketId => \n    getMarketLiquidityInfo(client, marketId)\n  );\n\n  return Promise.all(liquidityPromises);\n}\n\n/**\n * Displays comprehensive market liquidity information\n */\nexport function displayMarketLiquidity(liquidityInfo: MarketLiquidityInfo): void {\n  console.log(\"\\n✅ --- Morpho Market Liquidity Information --- ✅\");\n\n  console.log(`\\n--- Market Overview ---`);\n  console.log(`Market ID: ${liquidityInfo.marketId}`);\n  console.log(`Loan Token: ${liquidityInfo.loanToken.name} (${liquidityInfo.loanToken.symbol})`);\n  console.log(`Collateral Token: ${liquidityInfo.collateralToken.name} (${liquidityInfo.collateralToken.symbol})`);\n  console.log(`LLTV: ${liquidityInfo.lltvPercentage.toFixed(2)}%`);\n\n  console.log(`\\n--- Current Liquidity (Real-time) ---`);\n  console.log(`Total Supply: ${liquidityInfo.formattedTotalSupply} ${liquidityInfo.loanToken.symbol}`);\n  console.log(`Total Borrow: ${liquidityInfo.formattedTotalBorrow} ${liquidityInfo.loanToken.symbol}`);\n  console.log(`Total Collateral: ${liquidityInfo.formattedTotalCollateral} ${liquidityInfo.collateralToken.symbol}`);\n  console.log(`Available Liquidity: ${liquidityInfo.formattedAvailableLiquidity} ${liquidityInfo.loanToken.symbol}`);\n  console.log(`Utilization: ${liquidityInfo.utilizationPercentage.toFixed(2)}%`);\n\n  console.log(`\\n--- Interest Accrual ---`);\n  console.log(`Last Update: ${liquidityInfo.lastUpdateTime.toISOString()}`);\n  console.log(`Interest Accrued: ${liquidityInfo.formattedInterestAccrued} ${liquidityInfo.loanToken.symbol}`);\n\n  console.log(`\\n--- Stale vs Current Comparison ---`);\n  console.log(`Stale Total Supply: ${formatUnits(liquidityInfo.staleState.totalSupplyAssets, liquidityInfo.loanToken.decimals)} ${liquidityInfo.loanToken.symbol}`);\n  console.log(`Current Total Supply: ${liquidityInfo.formattedTotalSupply} ${liquidityInfo.loanToken.symbol}`);\n  console.log(`Stale Total Borrow: ${formatUnits(liquidityInfo.staleState.totalBorrowAssets, liquidityInfo.loanToken.decimals)} ${liquidityInfo.loanToken.symbol}`);\n  console.log(`Current Total Borrow: ${liquidityInfo.formattedTotalBorrow} ${liquidityInfo.loanToken.symbol}`);\n\n  console.log(`\\n--- Raw Values ---`);\n  console.log(`Total Supply Assets: ${liquidityInfo.totalSupplyAssets}`);\n  console.log(`Total Borrow Assets: ${liquidityInfo.totalBorrowAssets}`);\n  console.log(`Total Collateral Assets: ${liquidityInfo.totalCollateralAssets}`);\n  console.log(`Utilization (WAD): ${liquidityInfo.utilization}`);\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Displays a summary table of multiple markets liquidity\n */\nexport function displayMarketsLiquiditySummary(markets: MarketLiquidityInfo[]): void {\n  if (markets.length === 0) {\n    console.log(\"No markets to display.\");\n    return;\n  }\n\n  console.log(\"\\n✅ --- Markets Liquidity Summary --- ✅\");\n  console.log(\"\\nMarket ID                    | Loan/Collateral     | Total Supply | Total Borrow | Utilization | Available\");\n  console.log(\"-----------------------------+---------------------+--------------+--------------+-------------+----------\");\n\n  markets.forEach((market) => {\n    const shortId = `${market.marketId.slice(0, 8)}...${market.marketId.slice(-8)}`;\n    const tokenPair = `${market.loanToken.symbol}/${market.collateralToken.symbol}`;\n    const totalSupply = parseFloat(market.formattedTotalSupply).toLocaleString('en-US', { maximumFractionDigits: 0 });\n    const totalBorrow = parseFloat(market.formattedTotalBorrow).toLocaleString('en-US', { maximumFractionDigits: 0 });\n    const utilization = `${market.utilizationPercentage.toFixed(1)}%`.padStart(10);\n    const available = parseFloat(market.formattedAvailableLiquidity).toLocaleString('en-US', { maximumFractionDigits: 0 });\n\n    console.log(\n      `${shortId.padEnd(28)} | ${tokenPair.padEnd(19)} | ${totalSupply.padStart(12)} | ${totalBorrow.padStart(12)} | ${utilization} | ${available.padStart(8)}`\n    );\n  });\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Main function to demonstrate market liquidity calculations\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    \n    // Get liquidity information for the example market\n    const marketLiquidity = await getMarketLiquidityInfo(client, EXAMPLE_MARKET_ID);\n    \n    // Display detailed results\n    displayMarketLiquidity(marketLiquidity);\n    \n    // Example: Get liquidity for multiple markets\n    const multipleMarkets = [EXAMPLE_MARKET_ID];\n    const marketsLiquidity = await getMultipleMarketsLiquidity(client, multipleMarkets);\n    \n    // Display summary\n    displayMarketsLiquiditySummary(marketsLiquidity);\n    \n  } catch (error) {\n    console.error(\"Error in market liquidity calculation:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFetching liquidity information for market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\nNote: Total collateral calculation requires tracking all position holders\n\n✅ --- Morpho Market Liquidity Information --- ✅\n\n--- Market Overview ---\nMarket ID: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\nLoan Token: USD Coin (USDC)\nCollateral Token: Coinbase Wrapped BTC (cbBTC)\nLLTV: 86.00%\n\n--- Current Liquidity (Real-time) ---\nTotal Supply: 522083875.989369 USDC\nTotal Borrow: 481268818.125629 USDC\nTotal Collateral: 0 cbBTC\nAvailable Liquidity: 40815057.86374 USDC\nUtilization: 92.18%\n\n--- Interest Accrual ---\nLast Update: 2025-11-07T10:57:35.000Z\nInterest Accrued: 0 USDC\n\n--- Stale vs Current Comparison ---\nStale Total Supply: 522083875.989369 USDC\nCurrent Total Supply: 522083875.989369 USDC\nStale Total Borrow: 481268818.125629 USDC\nCurrent Total Borrow: 481268818.125629 USDC\n\n--- Raw Values ---\nTotal Supply Assets: 522083875989369\nTotal Borrow Assets: 481268818125629\nTotal Collateral Assets: 0\nUtilization (WAD): 921822795644868562\n\n----------------------------------------\nFetching liquidity information for 1 markets...\nFetching liquidity information for market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\nNote: Total collateral calculation requires tracking all position holders\n\n✅ --- Markets Liquidity Summary --- ✅\n\nMarket ID                    | Loan/Collateral     | Total Supply | Total Borrow | Utilization | Available\n-----------------------------+---------------------+--------------+--------------+-------------+----------\n0x64d65c...883fcc64          | USDC/cbBTC          |  522,083,876 |  481,268,818 |      92.2% | 40,815,058\n\n----------------------------------------\n```\n\nThis 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.\n\n{\" \"}\n\n- As it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain.\nFeel 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.\n\n```solidity\n/// @notice Calculates the total supply of assets in a specific market.\n    /// @param marketParams The parameters of the market.\n    /// @return totalSupplyAssets The calculated total supply of assets.\n    function marketTotalSupply(MarketParams memory marketParams) public view returns (uint256 totalSupplyAssets) {\n        totalSupplyAssets = morpho.expectedTotalSupplyAssets(marketParams);\n    }\n\n/// @notice Calculates the total borrow of assets in a specific market.\n    /// @param marketParams The parameters of the market.\n    /// @return totalBorrowAssets The calculated total borrow of assets.\n    function marketTotalBorrow(MarketParams memory marketParams) public view returns (uint256 totalBorrowAssets) {\n        totalBorrowAssets = morpho.expectedTotalBorrowAssets(marketParams);\n    }\n\n```\n\nThe 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.\n\n### Market APY (Native & Rewards)\n\nGet the real-time APY, interest rates, and accrual information for markets.\n\nThe API provides both the native APY from borrowing/lending and the additional APR from reward incentives.\n\n###### Important UI Reference one might find on apps:\n\n1. `avgApy` represents the Native APY (6h average vault APY excluding rewards, before deducting the performance fee)\n2. `avgNetApy` represents the complete APY (6h average vault APY including rewards, after deducting the performance fee)\n\n---\n\n```graphql [All Markets]\nquery {\n  markets(\n    first: 100\n    orderBy: SupplyAssetsUsd\n    orderDirection: Desc\n    where: { chainId_in: [1, 8453] }\n  ) {\n    items {\n      uniqueKey\n      state {\n        borrowApy\n        avgBorrowApy\n        avgNetBorrowApy\n        supplyApy\n        avgSupplyApy\n        avgNetSupplyApy\n        rewards {\n          asset {\n            address\n            chain {\n              id\n            }\n          }\n          supplyApr\n          borrowApr\n        }\n      }\n    }\n  }\n}\n```\n\n---\n\n```graphql [Unique Market]\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    state {\n      borrowApy\n      avgBorrowApy\n      avgNetBorrowApy\n      supplyApy\n      avgSupplyApy\n      avgNetSupplyApy\n      rewards {\n        supplyApr\n        borrowApr\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates comprehensive market APY calculations including:\n- Real-time interest accrual from last update to current block\n- Borrow and supply APY calculations using Interest Rate Models (IRM)\n- Market utilization and fee impact on supply rates\n- Interest compounding using Taylor expansion for precision\n- Comparison between stale and accrued market states\n- Efficient batch processing for multiple markets\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// Morpho V1 contract address\nconst MORPHO_BLUE_ADDRESS: Address = \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// Example market ID for demonstration \nconst EXAMPLE_MARKET_ID: `0x${string}` = \"0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\";\n\n// Morpho V1 ABI for market operations\nconst MORPHO_BLUE_ABI = parseAbi([\n  \"function market(bytes32 id) view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)\",\n  \"function idToMarketParams(bytes32 id) view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n]);\n\n// Interest Rate Model ABI\nconst IRM_ABI = parseAbi([\n  \"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) view returns (uint256)\",\n]);\n\n// ERC20 ABI for token information\nconst ERC20_ABI = parseAbi([\n  \"function symbol() view returns (string)\",\n  \"function name() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n]);\n\ntype MarketParams = {\n  loanToken: Address;\n  collateralToken: Address;\n  oracle: Address;\n  irm: Address;\n  lltv: bigint;\n}\n\ntype MarketState = {\n  totalSupplyAssets: bigint;\n  totalSupplyShares: bigint;\n  totalBorrowAssets: bigint;\n  totalBorrowShares: bigint;\n  lastUpdate: bigint;\n  fee: bigint;\n}\n\ninterface TokenInfo {\n  address: Address;\n  symbol: string;\n  name: string;\n  decimals: number;\n}\n\ninterface MarketAPYInfo {\n  marketId: `0x${string}`;\n  params: MarketParams;\n  state: MarketState;\n  accruedState: MarketState;\n  loanToken: TokenInfo;\n  collateralToken: TokenInfo;\n  lltvPercentage: number;\n  borrowRate: bigint;\n  borrowAPY: bigint;\n  supplyAPY: bigint;\n  utilization: bigint;\n  borrowAPYPercentage: number;\n  supplyAPYPercentage: number;\n  utilizationPercentage: number;\n  lastUpdateTime: Date;\n  interestAccrued: bigint;\n  blockTimestamp: bigint;\n}\n\nconst WAD = 10n ** 18n;\nconst SECONDS_PER_YEAR = 31536000n;\n\nconst wMulDown = (x: bigint, y: bigint): bigint => (x * y) / WAD;\nconst wDivUp = (x: bigint, y: bigint): bigint => (x * WAD + y - 1n) / y;\n\nconst wTaylorCompounded = (x: bigint, n: bigint): bigint => {\n  const firstTerm = x * n;\n  const secondTerm = (firstTerm * firstTerm) / (2n * WAD);\n  const thirdTerm = (secondTerm * firstTerm) / (3n * WAD);\n  return firstTerm + secondTerm + thirdTerm;\n};\n\n/**\n * Formats a WAD-scaled value (18 decimals) to percentage\n */\nfunction formatWADToPercentage(value: bigint): number {\n  return Number(formatUnits(value, 16)); // 18 - 2 = 16 for percentage\n}\n\n/**\n * Formats LLTV from WAD format to percentage\n */\nfunction formatLLTV(lltv: bigint): number {\n  return Number(formatUnits(lltv, 18)) * 100;\n}\n\n/**\n * Fetches token information for a given address\n */\nasync function getTokenInfo(\n  client: PublicClient,\n  tokenAddress: Address\n): Promise<TokenInfo> {\n  try {\n    const [symbol, name, decimals] = await client.multicall({\n      contracts: [\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"name\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"decimals\" },\n      ],\n      allowFailure: false,\n    });\n\n    return {\n      address: tokenAddress,\n      symbol,\n      name,\n      decimals,\n    };\n  } catch (error) {\n    return {\n      address: tokenAddress,\n      symbol: `Token(${tokenAddress.slice(0, 6)}...)`,\n      name: `Unknown Token ${tokenAddress.slice(0, 6)}...`,\n      decimals: 18,\n    };\n  }\n}\n\n/**\n * Accrues interest on a market from its last update time to the current block's timestamp.\n * This is crucial for getting the real-time state of the market.\n */\nfunction accrueInterests(\n  marketState: MarketState,\n  borrowRate: bigint,\n  blockTimestamp: bigint\n): { accruedState: MarketState; interestAccrued: bigint } {\n  const elapsed = blockTimestamp - marketState.lastUpdate;\n  \n  if (elapsed === 0n || marketState.totalBorrowAssets === 0n) {\n    return { \n      accruedState: marketState, \n      interestAccrued: 0n \n    };\n  }\n\n  const interest = wMulDown(\n    marketState.totalBorrowAssets, \n    wTaylorCompounded(borrowRate, elapsed)\n  );\n\n  const accruedState = {\n    ...marketState,\n    totalSupplyAssets: marketState.totalSupplyAssets + interest,\n    totalBorrowAssets: marketState.totalBorrowAssets + interest,\n    lastUpdate: blockTimestamp,\n  };\n\n  return { accruedState, interestAccrued: interest };\n}\n\n/**\n * Calculates comprehensive market APY information including supply and borrow rates.\n */\nexport async function getMarketAPYInfo(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<MarketAPYInfo> {\n  console.log(`Fetching APY information for market: ${marketId}`);\n\n  // Get current block timestamp\n  const block = await client.getBlock({ blockTag: \"latest\" });\n  const blockTimestamp = block.timestamp;\n\n  // Get market state and parameters\n  const [marketStateResult, marketParamsResult] = await client.multicall({\n    contracts: [\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"market\", args: [marketId] },\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"idToMarketParams\", args: [marketId] },\n    ],\n    allowFailure: false,\n  });\n\n  const state: MarketState = {\n    totalSupplyAssets: marketStateResult[0],\n    totalSupplyShares: marketStateResult[1],\n    totalBorrowAssets: marketStateResult[2],\n    totalBorrowShares: marketStateResult[3],\n    lastUpdate: marketStateResult[4],\n    fee: marketStateResult[5],\n  };\n\n  const params: MarketParams = {\n    loanToken: marketParamsResult[0],\n    collateralToken: marketParamsResult[1],\n    oracle: marketParamsResult[2],\n    irm: marketParamsResult[3],\n    lltv: marketParamsResult[4],\n  };\n\n  // Get token information\n  const [loanToken, collateralToken] = await Promise.all([\n    getTokenInfo(client, params.loanToken),\n    getTokenInfo(client, params.collateralToken),\n  ]);\n\n  // Initialize default values\n  let borrowRate = 0n;\n  let borrowAPY = 0n;\n  let supplyAPY = 0n;\n  let utilization = 0n;\n  let accruedState = state;\n  let interestAccrued = 0n;\n\n  // Calculate rates if IRM is set\n  if (params.irm !== \"0x0000000000000000000000000000000000000000\") {\n    // Get borrow rate from IRM\n    borrowRate = await client.readContract({\n      address: params.irm,\n      abi: IRM_ABI,\n      functionName: \"borrowRateView\",\n      args: [params, state],\n    }) as bigint;\n\n    // Accrue interest to get current state\n    const accrualResult = accrueInterests(state, borrowRate, blockTimestamp);\n    accruedState = accrualResult.accruedState;\n    interestAccrued = accrualResult.interestAccrued;\n\n    // Calculate APYs\n    borrowAPY = wTaylorCompounded(borrowRate, SECONDS_PER_YEAR);\n    \n    // Calculate utilization using accrued state\n    if (accruedState.totalSupplyAssets > 0n) {\n      utilization = wDivUp(accruedState.totalBorrowAssets, accruedState.totalSupplyAssets);\n    }\n\n    // Supply APY = Borrow APY * Utilization * (1 - Fee)\n    supplyAPY = wMulDown(\n      wMulDown(borrowAPY, utilization),\n      WAD - accruedState.fee\n    );\n  }\n\n  return {\n    marketId,\n    params,\n    state,\n    accruedState,\n    loanToken,\n    collateralToken,\n    lltvPercentage: formatLLTV(params.lltv),\n    borrowRate,\n    borrowAPY,\n    supplyAPY,\n    utilization,\n    borrowAPYPercentage: formatWADToPercentage(borrowAPY),\n    supplyAPYPercentage: formatWADToPercentage(supplyAPY),\n    utilizationPercentage: formatWADToPercentage(utilization),\n    lastUpdateTime: new Date(Number(state.lastUpdate) * 1000),\n    interestAccrued,\n    blockTimestamp,\n  };\n}\n\n/**\n * Calculates APY information for multiple markets efficiently\n */\nexport async function getMultipleMarketsAPY(\n  client: PublicClient,\n  marketIds: `0x${string}`[]\n): Promise<MarketAPYInfo[]> {\n  console.log(`Fetching APY information for ${marketIds.length} markets...`);\n\n  const apyPromises = marketIds.map(marketId => \n    getMarketAPYInfo(client, marketId)\n  );\n\n  return Promise.all(apyPromises);\n}\n\n/**\n * Displays comprehensive market APY information\n */\nexport function displayMarketAPY(marketInfo: MarketAPYInfo): void {\n  console.log(\"\\n✅ --- Morpho Market APY Information --- ✅\");\n\n  console.log(`\\n--- Market Overview ---`);\n  console.log(`Market ID: ${marketInfo.marketId}`);\n  console.log(`Loan Token: ${marketInfo.loanToken.name} (${marketInfo.loanToken.symbol})`);\n  console.log(`Collateral Token: ${marketInfo.collateralToken.name} (${marketInfo.collateralToken.symbol})`);\n  console.log(`LLTV: ${marketInfo.lltvPercentage.toFixed(2)}%`);\n\n  console.log(`\\n--- Market Liquidity (Real-time) ---`);\n  console.log(`Total Supply: ${formatUnits(marketInfo.accruedState.totalSupplyAssets, marketInfo.loanToken.decimals)} ${marketInfo.loanToken.symbol}`);\n  console.log(`Total Borrow: ${formatUnits(marketInfo.accruedState.totalBorrowAssets, marketInfo.loanToken.decimals)} ${marketInfo.loanToken.symbol}`);\n  console.log(`Utilization: ${marketInfo.utilizationPercentage.toFixed(2)}%`);\n\n  console.log(`\\n--- Interest Rates ---`);\n  console.log(`Borrow APY: ${marketInfo.borrowAPYPercentage.toFixed(4)}%`);\n  console.log(`Supply APY: ${marketInfo.supplyAPYPercentage.toFixed(4)}%`);\n  console.log(`Borrow Rate (per second): ${formatUnits(marketInfo.borrowRate, 18)}`);\n\n  console.log(`\\n--- Interest Accrual ---`);\n  console.log(`Last Update: ${marketInfo.lastUpdateTime.toISOString()}`);\n  console.log(`Interest Accrued: ${formatUnits(marketInfo.interestAccrued, marketInfo.loanToken.decimals)} ${marketInfo.loanToken.symbol}`);\n  console.log(`Market Fee: ${formatWADToPercentage(marketInfo.state.fee).toFixed(4)}%`);\n\n  console.log(`\\n--- Raw Values (WAD) ---`);\n  console.log(`Borrow APY: ${marketInfo.borrowAPY}`);\n  console.log(`Supply APY: ${marketInfo.supplyAPY}`);\n  console.log(`Utilization: ${marketInfo.utilization}`);\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Displays a summary table of multiple markets\n */\nexport function displayMarketsAPYSummary(markets: MarketAPYInfo[]): void {\n  if (markets.length === 0) {\n    console.log(\"No markets to display.\");\n    return;\n  }\n\n  console.log(\"\\n✅ --- Markets APY Summary --- ✅\");\n  console.log(\"\\nMarket ID                    | Loan/Collateral     | Borrow APY | Supply APY | Utilization\");\n  console.log(\"-----------------------------+---------------------+------------+------------+------------\");\n\n  markets.forEach((market) => {\n    const shortId = `${market.marketId.slice(0, 8)}...${market.marketId.slice(-8)}`;\n    const tokenPair = `${market.loanToken.symbol}/${market.collateralToken.symbol}`;\n    const borrowAPY = `${market.borrowAPYPercentage.toFixed(2)}%`.padStart(10);\n    const supplyAPY = `${market.supplyAPYPercentage.toFixed(2)}%`.padStart(10);\n    const utilization = `${market.utilizationPercentage.toFixed(2)}%`.padStart(10);\n\n    console.log(\n      `${shortId.padEnd(28)} | ${tokenPair.padEnd(19)} | ${borrowAPY} | ${supplyAPY} | ${utilization}`\n    );\n  });\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Main function to demonstrate market APY calculations\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    \n    // Get APY information for the example market\n    const marketAPY = await getMarketAPYInfo(client, EXAMPLE_MARKET_ID);\n    \n    // Display detailed results\n    displayMarketAPY(marketAPY);\n    \n    // Example: Get APY for multiple markets (add more market IDs here)\n    const multipleMarkets = [EXAMPLE_MARKET_ID];\n    const marketsAPY = await getMultipleMarketsAPY(client, multipleMarkets);\n    \n    // Display summary\n    displayMarketsAPYSummary(marketsAPY);\n    \n  } catch (error) {\n    console.error(\"Error in market APY calculation:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFetching APY information for market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\n\n✅ --- Morpho Market APY Information --- ✅\n\n--- Market Overview ---\nMarket ID: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\nLoan Token: USD Coin (USDC)\nCollateral Token: Coinbase Wrapped BTC (cbBTC)\nLLTV: 86.00%\n\n--- Market Liquidity (Real-time) ---\nTotal Supply: 522363906.351897 USDC\nTotal Borrow: 481268778.178246 USDC\nUtilization: 92.13%\n\n--- Interest Rates ---\nBorrow APY: 7.5419%\nSupply APY: 6.9486%\nBorrow Rate (per second): 0.000000002305661164\n\n--- Interest Accrual ---\nLast Update: 2025-11-07T10:56:59.000Z\nInterest Accrued: 0 USDC\nMarket Fee: 0.0000%\n\n--- Raw Values (WAD) ---\nBorrow APY: 75418869301348230\nSupply APY: 69485557173609405\nUtilization: 921328545724660480\n\n----------------------------------------\nFetching APY information for 1 markets...\nFetching APY information for market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\n\n✅ --- Markets APY Summary --- ✅\n\nMarket ID                    | Loan/Collateral     | Borrow APY | Supply APY | Utilization\n-----------------------------+---------------------+------------+------------+------------\n0x64d65c...883fcc64          | USDC/cbBTC          |      7.54% |      6.95% |     92.13%\n\n----------------------------------------\n```\n\nThis 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.\n\n{\" \"}\n\nAs it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain.\nFeel 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.\n\n```solidity\n/// @notice Calculates the supply APY (Annual Percentage Yield) for a given market.\n    /// @param marketParams The parameters of the market.\n    /// @param market The market for which the supply APY is being calculated.\n    /// @return supplyApy The calculated supply APY (scaled by WAD).\n    function supplyAPY(MarketParams memory marketParams, Market memory market)\n        public\n        view\n        returns (uint256 supplyApy)\n    {\n        (uint256 totalSupplyAssets,, uint256 totalBorrowAssets,) = morpho.expectedMarketBalances(marketParams);\n\n        // Get the borrow rate\n        if (marketParams.irm != address(0)) {\n            uint256 utilization = totalBorrowAssets == 0 ? 0 : totalBorrowAssets.wDivUp(totalSupplyAssets);\n            supplyApy = borrowAPY(marketParams, market).wMulDown(1 ether - market.fee).wMulDown(utilization);\n        }\n    }\n\n/// @notice Calculates the borrow APY (Annual Percentage Yield) for a given market.\n    /// @param marketParams The parameters of the market.\n    /// @param market The state of the market.\n    /// @return borrowApy The calculated borrow APY (scaled by WAD).\n    function borrowAPY(MarketParams memory marketParams, Market memory market)\n        public\n        view\n        returns (uint256 borrowApy)\n    {\n        if (marketParams.irm != address(0)) {\n            borrowApy = IIrm(marketParams.irm).borrowRateView(marketParams, market).wTaylorCompounded(365 days);\n        }\n    }\n```\n\n### Interactive Interest Rate Visualization\n\nUnderstanding 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.\n\nThe Morpho protocol uses a kinked interest rate model (IRM) with a target utilization of 90%.\n\n  \n\nBelow you'll find three approaches to working with this model: using the API, implementing it yourself, or understanding the mathematical foundation.\n\n**Fetch Pre-Calculated Curve Data**\n\nThe 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).\n\n---\n\n**Step 1: Query the GraphQL Endpoint**\n\n```graphql\nquery GetMarketIrmCurve($uniqueKey: String!, $chainId: Int!) {\n  marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {\n    id\n    irmAddress\n    state {\n      id\n      utilization\n    }\n    currentIrmCurve {\n      utilization\n      supplyApy\n      borrowApy\n    }\n  }\n}\n```\n\nAPI Endpoint: [api.morpho.org/graphql](https://api.morpho.org/graphql?explorerURLState=N4IgJg9gxgrgtgUwHYBcQC4QEcYIE4CeABAOIIoCyAhngNbkCSecAwjHgG4IAUAJDEgCWOBAGkEBdEQDKKPIKQBzAIQAaIrygALKgoZgpDVGo1J4AI3wB5AGYAFCApQBnQ6gCURYAB083pEREcDT0KABCBACqQiLiBNwCwrhxUvwxyRLq2rpI%2BqnZemCePn4BgUSCYL7%2B5RXMAIJgYHgIzs7VZYHOKFQoCF4dtYGVg0MwKIIANoIAXr2CEEijgQC%2By0SweC2oTKzsXAOlQ0TmEFsQAO71AA4E610w19eTBDd3R2MT03MTi%2BtrHwB-iBSBAqhAHBogio5kmrQwIBKNSI3hABVyVQwRAAjKpRgB6fEbcxhAAqLHxkWkABEWEEQuRRqjErEJKipKiAAwADwAbAAWMC8gCsUAAnFQAExgMXYqAAZl5YGFvJs5ig-OlvLFCDFAHYxfL5cL5ZLOdjteZ5WAbLz5eYbGLJXqABw6yVQF1e%2BU2KBQAWovEfVFmOCWPC2BxOdpYsyTSYdFYgFZAA)\n\nThis endpoint returns:\n- Market identification data\n- Current utilization state\n- Pre-calculated interest rate curve with 101 data points\n\n---\n\n**Step 2: Integrate with Frontend Component**\n\n```typescript\nconst ChartInterestRateModelClient = ({ queryResult }) => {\n  const marketData = queryResult?.data?.marketByUniqueKey;\n  const shouldShowNoDataError = useMemo(\n    () =>\n      marketData?.currentIrmCurve?.length === 0 ||\n      marketData?.irmAddress === undefined,\n    [marketData?.currentIrmCurve?.length, marketData?.irmAddress]\n  );\n\n  return (\n    <Card padding=\"s\" grow={1}>\n      <InterestRateModelChart\n        statuses={{\n          loading: false,\n          error: shouldShowNoDataError,\n        }}\n        height=\"288px\"\n        data={marketData?.currentIrmCurve}\n        irmAddress={marketData?.irmAddress}\n        utilization={marketData?.state?.utilization ?? 0}\n      />\n    </Card>\n  );\n};\n```\n\n**Benefits of API Approach:**\n- No need to implement rate calculations\n- Pre-calculated data optimized for visualization\n- Always up-to-date with latest protocol parameters\n- Minimal code required for integration\n\n{\" \"}\n\n**Build Your Own Rate Calculator**\n\nFor developers who need to calculate rates independently or integrate calculations into backend systems, you can implement the algorithm directly.\n\n---\n\n**Step 1: Core Algorithm**\n\nThe interest rate calculation formula:\n\n```typescript\nfunction rateAtUtilization(apyAtTarget, utilization, fee) {\n  let borrowApy;\n  const minApy = Math.expm1(Math.log1p(apyAtTarget) / 4);\n  const maxApy = Math.expm1(Math.log1p(apyAtTarget) * 4);\n\n  if (utilization <= 0.9) {\n    borrowApy = minApy + (apyAtTarget - minApy) * (utilization / 0.9);\n  } else {\n    borrowApy =\n      ((maxApy - apyAtTarget) / 0.1) * (utilization - 0.9) + apyAtTarget;\n  }\n\n  const supplyApy = borrowApy * (1 - fee) * utilization;\n\n  return {\n    borrowApy,\n    supplyApy,\n  };\n}\n```\n\n---\n\n**Step 2: Required Parameters**\nTo use this function, you need:\n\n1. **`apyAtTarget`**: The target borrow APY at 90% utilization\n   - This is derived from the `rateAtTarget` value stored in the [AdaptiveCurveIRM contract](https://docs.morpho.org/get-started/resources/contracts/irm/#mappings)\n   - Retrieve `rateAtTarget` for your market's IRM from the contract\n   - Convert to APY using: `apyAtTarget = (e^(rateAtTarget × secondsPerYear) - 1)`\n   - Example: If `rateAtTarget = 1512768697` (per second rate), this converts to approximately 4.9% APY\n\n2. **`utilization`**: Current utilization ratio (0 to 1)\n   - Calculate as: `totalBorrow / totalSupply`\n   - Use for calculating rates at specific points\n\n3. **`fee`**: Protocol fee percentage (e.g., 0.1 for 10%)\n   - Check [market state](/get-started/resources/contracts/morpho/#market-struct) for the exact fee\n   - This affects the supply APY calculation\n\n---\n\n**Step 3: Generate Curve Data**\n\n```typescript\n// Generate 101 data points for visualization\nconst generateCurveData = (apyAtTarget, fee) => {\n  const dataPoints = [];\n  for (let i = 0; i <= 100; i++) {\n    const utilization = i / 100;\n    const { borrowApy, supplyApy } = rateAtUtilization(\n      apyAtTarget,\n      utilization,\n      fee\n    );\n    dataPoints.push({\n      utilization,\n      borrowApy,\n      supplyApy\n    });\n  }\n  return dataPoints;\n};\n```\n\n**Use Cases for Direct Implementation:**\n- Real-time rate calculations in smart contracts\n- Custom analytics and modeling\n- Integration with proprietary systems\n- Independent verification of API data\n\n{\" \"}\n\n**Understanding the Kinked Interest Rate Model**\n\nThe AdaptiveCurveIRM uses a two-slope (kinked) model with distinct behavior before and after the target utilization.\n\n---\n\n**Key Parameters**\n\n1. **Target Utilization**: 90% (the kink point)\n2. **APY Range**: From minApy (~1/4 target) to maxApy (~4x target)\n3. **Formula Elements**:\n   - `minApy = Math.expm1(Math.log1p(apyAtTarget) / 4)`\n   - `maxApy = Math.expm1(Math.log1p(apyAtTarget) * 4)`\n\n---\n\n**Two-Slope Behavior**\n\n**Below Target (0% - 90% utilization):**\n```\nborrowApy = minApy + (apyAtTarget - minApy) * (utilization / 0.9)\n```\n- Linear increase from minApy to apyAtTarget\n- Gentle slope to encourage borrowing\n- Supply rates gradually increase with utilization\n\n**Above Target (90% - 100% utilization):**\n```\nborrowApy = ((maxApy - apyAtTarget) / 0.1) * (utilization - 0.9) + apyAtTarget\n```\n- Steeper linear increase to maxApy\n- Discourages over-utilization\n- Incentivizes suppliers at high utilization\n\n---\n\n**Mathematical Properties at Key Points**\n\n**At 0% utilization:**\n- Borrow APY = minApy (~1/4 of target APY)\n- Supply APY = 0 (as utilization is 0)\n- Lowest rates to attract initial borrowers\n\n**At 90% utilization (target):**\n- Borrow APY = apyAtTarget\n- Supply APY = apyAtTarget × (1 - fee) × 0.9\n- Optimal balance point for the market\n\n**At 100% utilization:**\n- Borrow APY = maxApy (~4x target APY)\n- Supply APY = maxApy × (1 - fee)\n- Maximum rates to incentivize supply\n\n**Supply APY Formula:**\n\n```\nsupplyApy = borrowApy × (1 - fee) × utilization\n```\n\n- Protocol fee is deducted from borrow interest\n- Supply APY scales with utilization\n\nFor more on the AdaptiveCurveIRM, explore the [technical reference](/get-started/resources/contracts/irm/).\n\n## Asset Information\n\n### Assets\n\nGet metadata and pricing for specific tokens.\n\n---\n\n```graphql [API]\nquery GetAssetsWithPrice {\n  assets(where: { symbol_in: [\"wstETH\", \"WETH\"], chainId_in: [1] }) {\n    items {\n      symbol\n      address\n      priceUsd\n      chain {\n        id\n        network\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates comprehensive asset information retrieval including:\n- Basic ERC20 metadata (name, symbol, decimals, total supply)\n- Asset validation and error handling for invalid tokens\n- EIP-2612 permit support detection for gasless approvals\n- User balance and allowance tracking\n- Portfolio analysis across multiple assets\n- Efficient batch processing using multicall\n- Formatted display with large number abbreviations (K, M, B, T)\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// Example token addresses for demonstration\nconst EXAMPLE_ASSETS: Address[] = [\n  \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\", // USDC\n  \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", // WETH\n  \"0xdAC17F958D2ee523a2206206994597C13D831ec7\", // USDT\n  \"0x6B175474E89094C44Da98b954EedeAC495271d0F\", // DAI\n  \"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599\", // WBTC\n];\n\n// Comprehensive ERC20 ABI for asset information\nconst ERC20_ABI = parseAbi([\n  \"function name() view returns (string)\",\n  \"function symbol() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n  \"function totalSupply() view returns (uint256)\",\n  \"function balanceOf(address account) view returns (uint256)\",\n  \"function allowance(address owner, address spender) view returns (uint256)\",\n]);\n\n// Optional: Extended ERC20 ABI for additional metadata (some tokens support these)\nconst EXTENDED_ERC20_ABI = parseAbi([\n  \"function version() view returns (string)\",\n  \"function DOMAIN_SEPARATOR() view returns (bytes32)\",\n  \"function nonces(address owner) view returns (uint256)\",\n]);\n\ninterface AssetInfo {\n  address: Address;\n  name: string;\n  symbol: string;\n  decimals: number;\n  totalSupply: bigint;\n  formattedTotalSupply: string;\n  // Optional extended info\n  version?: string;\n  domainSeparator?: `0x${string}`;\n  supportsPermit: boolean;\n  isValid: boolean;\n  error?: string;\n}\n\ninterface AssetBalance {\n  asset: AssetInfo;\n  balance: bigint;\n  formattedBalance: string;\n  allowance?: bigint;\n  formattedAllowance?: string;\n}\n\ninterface AssetPortfolio {\n  userAddress: Address;\n  assets: AssetBalance[];\n  totalAssetsCount: number;\n  validAssetsCount: number;\n  invalidAssetsCount: number;\n}\n\n/**\n * Checks if an address is a valid ERC20 token by attempting to call basic functions\n */\nasync function isValidERC20(\n  client: PublicClient,\n  tokenAddress: Address\n): Promise<boolean> {\n  try {\n    await client.multicall({\n      contracts: [\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"name\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"decimals\" },\n      ],\n      allowFailure: false,\n    });\n    return true;\n  } catch (error) {\n    return false;\n  }\n}\n\n/**\n * Checks if a token supports EIP-2612 permit functionality\n */\nasync function supportsPermit(\n  client: PublicClient,\n  tokenAddress: Address\n): Promise<boolean> {\n  try {\n    await client.readContract({\n      address: tokenAddress,\n      abi: EXTENDED_ERC20_ABI,\n      functionName: \"DOMAIN_SEPARATOR\",\n    });\n    return true;\n  } catch (error) {\n    return false;\n  }\n}\n\n/**\n * Formats large numbers with appropriate suffixes (K, M, B, T)\n */\nfunction formatLargeNumber(value: string): string {\n  const num = parseFloat(value);\n  if (num >= 1e12) return `${(num / 1e12).toFixed(2)}T`;\n  if (num >= 1e9) return `${(num / 1e9).toFixed(2)}B`;\n  if (num >= 1e6) return `${(num / 1e6).toFixed(2)}M`;\n  if (num >= 1e3) return `${(num / 1e3).toFixed(2)}K`;\n  return num.toFixed(6);\n}\n\n/**\n * Retrieves comprehensive information about a single asset\n */\nexport async function getAssetInfo(\n  client: PublicClient,\n  tokenAddress: Address\n): Promise<AssetInfo> {\n  try {\n    // First check if it's a valid ERC20\n    const isValid = await isValidERC20(client, tokenAddress);\n    \n    if (!isValid) {\n      return {\n        address: tokenAddress,\n        name: \"Invalid Token\",\n        symbol: \"INVALID\",\n        decimals: 0,\n        totalSupply: 0n,\n        formattedTotalSupply: \"0\",\n        supportsPermit: false,\n        isValid: false,\n        error: \"Not a valid ERC20 token\",\n      };\n    }\n\n    // Get basic ERC20 information\n    const [name, symbol, decimals, totalSupply] = await client.multicall({\n      contracts: [\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"name\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"decimals\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"totalSupply\" },\n      ],\n      allowFailure: false,\n    });\n\n    // Check for permit support and get extended info\n    const [hasPermit, version, domainSeparator] = await Promise.all([\n      supportsPermit(client, tokenAddress),\n      client.readContract({\n        address: tokenAddress,\n        abi: EXTENDED_ERC20_ABI,\n        functionName: \"version\",\n      }).catch(() => undefined),\n      client.readContract({\n        address: tokenAddress,\n        abi: EXTENDED_ERC20_ABI,\n        functionName: \"DOMAIN_SEPARATOR\",\n      }).catch(() => undefined),\n    ]);\n\n    const formattedTotalSupply = formatUnits(totalSupply, decimals);\n\n    return {\n      address: tokenAddress,\n      name,\n      symbol,\n      decimals,\n      totalSupply,\n      formattedTotalSupply,\n      version: version as string | undefined,\n      domainSeparator: domainSeparator as `0x${string}` | undefined,\n      supportsPermit: hasPermit,\n      isValid: true,\n    };\n\n  } catch (error) {\n    return {\n      address: tokenAddress,\n      name: \"Error\",\n      symbol: \"ERROR\",\n      decimals: 0,\n      totalSupply: 0n,\n      formattedTotalSupply: \"0\",\n      supportsPermit: false,\n      isValid: false,\n      error: error instanceof Error ? error.message : \"Unknown error\",\n    };\n  }\n}\n\n/**\n * Retrieves asset information for multiple tokens efficiently\n */\nexport async function getMultipleAssetsInfo(\n  client: PublicClient,\n  tokenAddresses: Address[]\n): Promise<AssetInfo[]> {\n  console.log(`Fetching information for ${tokenAddresses.length} assets...`);\n\n  const assetPromises = tokenAddresses.map(address => \n    getAssetInfo(client, address)\n  );\n\n  return Promise.all(assetPromises);\n}\n\n/**\n * Gets asset balances and allowances for a specific user\n */\nexport async function getAssetBalance(\n  client: PublicClient,\n  tokenAddress: Address,\n  userAddress: Address,\n  spenderAddress?: Address\n): Promise<AssetBalance> {\n  const assetInfo = await getAssetInfo(client, tokenAddress);\n  \n  if (!assetInfo.isValid) {\n    return {\n      asset: assetInfo,\n      balance: 0n,\n      formattedBalance: \"0\",\n    };\n  }\n\n  try {\n    const balance = await client.readContract({\n      address: tokenAddress,\n      abi: ERC20_ABI,\n      functionName: \"balanceOf\",\n      args: [userAddress],\n    }) as bigint;\n\n    let allowance: bigint | undefined;\n    let formattedAllowance: string | undefined;\n\n    if (spenderAddress) {\n      allowance = await client.readContract({\n        address: tokenAddress,\n        abi: ERC20_ABI,\n        functionName: \"allowance\",\n        args: [userAddress, spenderAddress],\n      }) as bigint;\n      formattedAllowance = formatUnits(allowance, assetInfo.decimals);\n    }\n\n    return {\n      asset: assetInfo,\n      balance,\n      formattedBalance: formatUnits(balance, assetInfo.decimals),\n      allowance,\n      formattedAllowance,\n    };\n\n  } catch (error) {\n    return {\n      asset: {\n        ...assetInfo,\n        isValid: false,\n        error: `Balance fetch failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n      },\n      balance: 0n,\n      formattedBalance: \"0\",\n    };\n  }\n}\n\n/**\n * Creates a complete asset portfolio for a user\n */\nexport async function getUserAssetPortfolio(\n  client: PublicClient,\n  userAddress: Address,\n  tokenAddresses: Address[],\n  spenderAddress?: Address\n): Promise<AssetPortfolio> {\n  console.log(`Fetching asset portfolio for user: ${userAddress}`);\n\n  const balancePromises = tokenAddresses.map(tokenAddress =>\n    getAssetBalance(client, tokenAddress, userAddress, spenderAddress)\n  );\n\n  const assets = await Promise.all(balancePromises);\n\n  const validAssets = assets.filter(asset => asset.asset.isValid);\n  const invalidAssets = assets.filter(asset => !asset.asset.isValid);\n\n  return {\n    userAddress,\n    assets,\n    totalAssetsCount: assets.length,\n    validAssetsCount: validAssets.length,\n    invalidAssetsCount: invalidAssets.length,\n  };\n}\n\n/**\n * Displays comprehensive asset information\n */\nexport function displayAssetInfo(assetInfo: AssetInfo): void {\n  console.log(\"\\n✅ --- Asset Information --- ✅\");\n  \n  console.log(`\\n--- Basic Info ---`);\n  console.log(`Address: ${assetInfo.address}`);\n  console.log(`Name: ${assetInfo.name}`);\n  console.log(`Symbol: ${assetInfo.symbol}`);\n  console.log(`Decimals: ${assetInfo.decimals}`);\n  console.log(`Valid ERC20: ${assetInfo.isValid ? \"✅ Yes\" : \"❌ No\"}`);\n  \n  if (assetInfo.error) {\n    console.log(`Error: ${assetInfo.error}`);\n  }\n\n  if (assetInfo.isValid) {\n    console.log(`\\n--- Supply Info ---`);\n    console.log(`Total Supply: ${assetInfo.formattedTotalSupply} ${assetInfo.symbol}`);\n    console.log(`Total Supply (formatted): ${formatLargeNumber(assetInfo.formattedTotalSupply)} ${assetInfo.symbol}`);\n    console.log(`Total Supply (raw): ${assetInfo.totalSupply}`);\n\n    console.log(`\\n--- Extended Features ---`);\n    console.log(`Supports Permit (EIP-2612): ${assetInfo.supportsPermit ? \"✅ Yes\" : \"❌ No\"}`);\n    if (assetInfo.version) {\n      console.log(`Version: ${assetInfo.version}`);\n    }\n    if (assetInfo.domainSeparator) {\n      console.log(`Domain Separator: ${assetInfo.domainSeparator}`);\n    }\n  }\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Displays a summary table of multiple assets\n */\nexport function displayAssetsTable(assets: AssetInfo[]): void {\n  console.log(\"\\n✅ --- Assets Summary Table --- ✅\");\n  \n  const validAssets = assets.filter(asset => asset.isValid);\n  const invalidAssets = assets.filter(asset => !asset.isValid);\n\n  console.log(`\\nValid Assets: ${validAssets.length} | Invalid Assets: ${invalidAssets.length}`);\n  \n  if (validAssets.length > 0) {\n    console.log(\"\\n--- Valid Assets ---\");\n    console.log(\"Symbol       | Name                    | Decimals | Total Supply       | Permit\");\n    console.log(\"-------------+-------------------------+----------+--------------------+-------\");\n    \n    validAssets.forEach(asset => {\n      const symbol = asset.symbol.padEnd(12);\n      const name = asset.name.length > 23 ? asset.name.slice(0, 20) + \"...\" : asset.name.padEnd(23);\n      const decimals = asset.decimals.toString().padStart(8);\n      const supply = formatLargeNumber(asset.formattedTotalSupply).padStart(18);\n      const permit = asset.supportsPermit ? \"  ✅\" : \"  ❌\";\n      \n      console.log(`${symbol} | ${name} | ${decimals} | ${supply} | ${permit}`);\n    });\n  }\n\n  if (invalidAssets.length > 0) {\n    console.log(\"\\n--- Invalid Assets ---\");\n    invalidAssets.forEach(asset => {\n      console.log(`❌ ${asset.address}: ${asset.error || \"Invalid ERC20\"}`);\n    });\n  }\n  \n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Displays user asset portfolio\n */\nexport function displayAssetPortfolio(portfolio: AssetPortfolio): void {\n  console.log(\"\\n✅ --- User Asset Portfolio --- ✅\");\n  \n  console.log(`\\n--- Portfolio Overview ---`);\n  console.log(`User Address: ${portfolio.userAddress}`);\n  console.log(`Total Assets: ${portfolio.totalAssetsCount}`);\n  console.log(`Valid Assets: ${portfolio.validAssetsCount}`);\n  console.log(`Invalid Assets: ${portfolio.invalidAssetsCount}`);\n\n  const assetsWithBalance = portfolio.assets.filter(asset => \n    asset.asset.isValid && asset.balance > 0n\n  );\n\n  if (assetsWithBalance.length > 0) {\n    console.log(`\\n--- Assets with Balance ---`);\n    console.log(\"Symbol       | Balance              | Allowance (if set)\");\n    console.log(\"-------------+----------------------+-------------------\");\n    \n    assetsWithBalance.forEach(assetBalance => {\n      const symbol = assetBalance.asset.symbol.padEnd(12);\n      const balance = parseFloat(assetBalance.formattedBalance).toLocaleString('en-US', {\n        maximumFractionDigits: 6,\n      }).padStart(20);\n      const allowance = assetBalance.formattedAllowance \n        ? parseFloat(assetBalance.formattedAllowance).toLocaleString('en-US', {\n            maximumFractionDigits: 6,\n          })\n        : \"Not checked\";\n      \n      console.log(`${symbol} | ${balance} | ${allowance}`);\n    });\n  } else {\n    console.log(`\\n--- No assets with balance found ---`);\n  }\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Main function to demonstrate asset information retrieval\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    \n    console.log(\"=== Asset Information Demo ===\\n\");\n    \n    // Demo 1: Get information for a single asset\n    console.log(\"1. Single Asset Info (USDC):\");\n    const usdcInfo = await getAssetInfo(client, EXAMPLE_ASSETS[0]);\n    displayAssetInfo(usdcInfo);\n    \n    // Demo 2: Get information for multiple assets\n    console.log(\"\\n2. Multiple Assets Info:\");\n    const assetsInfo = await getMultipleAssetsInfo(client, EXAMPLE_ASSETS);\n    displayAssetsTable(assetsInfo);\n    \n    // Demo 3: Get user portfolio (example with zero address - will show zero balances)\n    console.log(\"\\n3. User Portfolio (Zero Address - for demo):\");\n    const zeroAddress = \"0x0000000000000000000000000000000000000000\";\n    const portfolio = await getUserAssetPortfolio(client, zeroAddress, EXAMPLE_ASSETS.slice(0, 3));\n    displayAssetPortfolio(portfolio);\n    \n    console.log(\"\\n=== Demo Complete ===\");\n    \n  } catch (error) {\n    console.error(\"Error in asset information script:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\n=== Asset Information Demo ===\n\n1. Single Asset Info (USDC):\n\n✅ --- Asset Information --- ✅\n\n--- Basic Info ---\nAddress: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\nName: USD Coin\nSymbol: USDC\nDecimals: 6\nValid ERC20: ✅ Yes\n\n--- Supply Info ---\nTotal Supply: 41233587998.984993 USDC\nTotal Supply (formatted): 41.23B USDC\nTotal Supply (raw): 41233587998984993\n\n--- Extended Features ---\nSupports Permit (EIP-2612): ✅ Yes\nVersion: 2\nDomain Separator: 0x06c37168a7db5138defc7866392bb87a741f9b3d104deb5094588ce041cae335\n\n----------------------------------------\n\n2. Multiple Assets Info:\nFetching information for 5 assets...\n\n✅ --- Assets Summary Table --- ✅\n\nValid Assets: 5 | Invalid Assets: 0\n\n--- Valid Assets ---\nSymbol       | Name                    | Decimals | Total Supply       | Permit\n-------------+-------------------------+----------+--------------------+-------\nUSDC         | USD Coin                |        6 |             41.23B |   ✅\nWETH         | Wrapped Ether           |       18 |              2.54M |   ❌\nUSDT         | Tether USD              |        6 |             74.81B |   ❌\nDAI          | Dai Stablecoin          |       18 |              3.64B |   ✅\nWBTC         | Wrapped BTC             |        8 |            128.85K |   ❌\n\n----------------------------------------\n\n3. User Portfolio (Zero Address - for demo):\nFetching asset portfolio for user: 0x0000000000000000000000000000000000000000\n\n✅ --- User Asset Portfolio --- ✅\n\n--- Portfolio Overview ---\nUser Address: 0x0000000000000000000000000000000000000000\nTotal Assets: 3\nValid Assets: 3\nInvalid Assets: 0\n\n--- Assets with Balance ---\nSymbol       | Balance              | Allowance (if set)\n-------------+----------------------+-------------------\nWETH         |         1,086.556748 | Not checked\nUSDT         |       201,290.112228 | Not checked\n\n----------------------------------------\n\n=== Demo Complete ===\n```\n\nThis example provides complete asset analysis capabilities essential for DeFi applications, including validation, metadata extraction, and portfolio management.\n\n## Position Tracking\n\n### User Position on Market\n\n```graphql [API]\nquery {\n  marketPositions(\n    first: 10,\n    orderBy: BorrowShares,\n    orderDirection: Desc\n    where: {\n      marketUniqueKey_in: [\"0x698fe98247a40c5771537b5786b2f3f9d78eb487b4ce4d75533cd0e94d88a115\"]\n    }\n  ) {\n    items {\n      user { address }\n      state {\n        collateral\n        borrowAssets\n        borrowAssetsUsd\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates comprehensive user position analysis including:\n- Real-time interest accrual for accurate borrow/supply amounts\n- Health factor calculation with liquidation risk assessment\n- Collateral valuation using oracle prices\n- Position safety metrics (LTV, liquidation buffer, liquidation price)\n- Multiple market position tracking and portfolio analysis\n- Conversion between shares and assets with proper rounding\n- Risk assessment and liquidation threshold calculations\n\nUser 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.\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// Morpho V1 contract address\nconst MORPHO_BLUE_ADDRESS: Address = \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// Example user and market for demonstration\nconst EXAMPLE_USER: Address = \"0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f\";\nconst EXAMPLE_MARKET_ID: `0x${string}` = \"0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\";\n\n// Morpho V1 ABI for user position operations\nconst MORPHO_BLUE_ABI = parseAbi([\n  \"function market(bytes32 id) view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)\",\n  \"function idToMarketParams(bytes32 id) view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n  \"function position(bytes32 id, address user) view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral)\",\n]);\n\n// Interest Rate Model ABI\nconst IRM_ABI = parseAbi([\n  \"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) view returns (uint256)\",\n]);\n\n// Oracle ABI\nconst ORACLE_ABI = parseAbi([\n  \"function price() view returns (uint256)\",\n]);\n\n// ERC20 ABI for token information\nconst ERC20_ABI = parseAbi([\n  \"function symbol() view returns (string)\",\n  \"function name() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n]);\n\ntype MarketParams = {\n  loanToken: Address;\n  collateralToken: Address;\n  oracle: Address;\n  irm: Address;\n  lltv: bigint;\n}\n\ntype MarketState = {\n  totalSupplyAssets: bigint;\n  totalSupplyShares: bigint;\n  totalBorrowAssets: bigint;\n  totalBorrowShares: bigint;\n  lastUpdate: bigint;\n  fee: bigint;\n}\n\ntype UserPosition = {\n  supplyShares: bigint;\n  borrowShares: bigint;\n  collateral: bigint;\n}\n\ntype TokenInfo = {\n  address: Address;\n  symbol: string;\n  name: string;\n  decimals: number;\n}\n\ninterface UserPositionInfo {\n  user: Address;\n  marketId: `0x${string}`;\n  marketParams: MarketParams;\n  staleMarketState: MarketState;\n  currentMarketState: MarketState;\n  rawPosition: UserPosition;\n  loanToken: TokenInfo;\n  collateralToken: TokenInfo;\n  lltvPercentage: number;\n  \n  // User-specific calculated values (real-time with accrued interest)\n  supplyAssets: bigint;\n  borrowAssets: bigint;\n  collateralAssets: bigint;\n  \n  // Formatted values\n  formattedSupplyAssets: string;\n  formattedBorrowAssets: string;\n  formattedCollateralAssets: string;\n  \n  // Health metrics\n  collateralPrice: bigint;\n  maxBorrow: bigint;\n  healthFactor: bigint;\n  isHealthy: boolean;\n  liquidationBuffer: bigint;\n  currentLTV: number;\n  maxLTV: number;\n  \n  // Risk metrics\n  utilizationOfCollateral: number;\n  liquidationPrice: bigint;\n  \n  // Interest accrual info\n  interestAccrued: bigint;\n  formattedInterestAccrued: string;\n  lastUpdateTime: Date;\n  blockTimestamp: bigint;\n}\n\nconst WAD = 10n ** 18n;\nconst VIRTUAL_ASSETS = 1n;\nconst VIRTUAL_SHARES = 10n ** 6n;\nconst ORACLE_PRICE_SCALE = 10n ** 36n;\nconst MAX_UINT256 = 2n ** 256n - 1n;\n\nconst wMulDown = (x: bigint, y: bigint): bigint => (x * y) / WAD;\nconst wDivUp = (x: bigint, y: bigint): bigint => (x * WAD + y - 1n) / y;\nconst wDivDown = (x: bigint, y: bigint): bigint => (x * WAD) / y;\nconst mulDivDown = (x: bigint, y: bigint, z: bigint): bigint => (x * y) / z;\nconst mulDivUp = (x: bigint, y: bigint, z: bigint): bigint => (x * y + z - 1n) / z;\n\nconst wTaylorCompounded = (x: bigint, n: bigint): bigint => {\n  const firstTerm = x * n;\n  const secondTerm = (firstTerm * firstTerm) / (2n * WAD);\n  const thirdTerm = (secondTerm * firstTerm) / (3n * WAD);\n  return firstTerm + secondTerm + thirdTerm;\n};\n\n/** Converts shares to assets (rounding down for supply, up for borrow) */\nconst toAssetsDown = (shares: bigint, totalAssets: bigint, totalShares: bigint): bigint => {\n  if (totalShares === 0n) return shares;\n  return mulDivDown(shares, totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES);\n};\n\nconst toAssetsUp = (shares: bigint, totalAssets: bigint, totalShares: bigint): bigint => {\n  if (totalShares === 0n) return shares;\n  return mulDivUp(shares, totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES);\n};\n\n/**\n * Formats LLTV from WAD format to percentage\n */\nfunction formatLLTV(lltv: bigint): number {\n  return Number(formatUnits(lltv, 18)) * 100;\n}\n\n/**\n * Fetches token information for a given address\n */\nasync function getTokenInfo(\n  client: PublicClient,\n  tokenAddress: Address\n): Promise<TokenInfo> {\n  try {\n    const [symbol, name, decimals] = await client.multicall({\n      contracts: [\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"name\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"decimals\" },\n      ],\n      allowFailure: false,\n    });\n\n    return {\n      address: tokenAddress,\n      symbol,\n      name,\n      decimals,\n    };\n  } catch (error) {\n    return {\n      address: tokenAddress,\n      symbol: `Token(${tokenAddress.slice(0, 6)}...)`,\n      name: `Unknown Token ${tokenAddress.slice(0, 6)}...`,\n      decimals: 18,\n    };\n  }\n}\n\n/**\n * Accrues interest on a market from its last update time to current block timestamp\n */\nfunction accrueInterests(\n  marketState: MarketState,\n  borrowRate: bigint,\n  blockTimestamp: bigint\n): { accruedState: MarketState; interestAccrued: bigint } {\n  const elapsed = blockTimestamp - marketState.lastUpdate;\n  \n  if (elapsed === 0n || marketState.totalBorrowAssets === 0n) {\n    return { \n      accruedState: marketState, \n      interestAccrued: 0n \n    };\n  }\n\n  const interest = wMulDown(\n    marketState.totalBorrowAssets, \n    wTaylorCompounded(borrowRate, elapsed)\n  );\n\n  const accruedState = {\n    ...marketState,\n    totalSupplyAssets: marketState.totalSupplyAssets + interest,\n    totalBorrowAssets: marketState.totalBorrowAssets + interest,\n    lastUpdate: blockTimestamp,\n  };\n\n  return { accruedState, interestAccrued: interest };\n}\n\n/**\n * Retrieves comprehensive user position information with real-time interest accrual\n */\nexport async function getUserPositionInfo(\n  client: PublicClient,\n  userAddress: Address,\n  marketId: `0x${string}`\n): Promise<UserPositionInfo> {\n  console.log(`Fetching position for user: ${userAddress} in market: ${marketId}`);\n\n  // Get current block timestamp\n  const block = await client.getBlock({ blockTag: \"latest\" });\n  const blockTimestamp = block.timestamp;\n\n  // Get market data, parameters, and user position\n  const [marketStateResult, marketParamsResult, positionResult] = await client.multicall({\n    contracts: [\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"market\", args: [marketId] },\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"idToMarketParams\", args: [marketId] },\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"position\", args: [marketId, userAddress] },\n    ],\n    allowFailure: false,\n  });\n\n  const staleMarketState: MarketState = {\n    totalSupplyAssets: marketStateResult[0],\n    totalSupplyShares: marketStateResult[1],\n    totalBorrowAssets: marketStateResult[2],\n    totalBorrowShares: marketStateResult[3],\n    lastUpdate: marketStateResult[4],\n    fee: marketStateResult[5],\n  };\n\n  const marketParams: MarketParams = {\n    loanToken: marketParamsResult[0],\n    collateralToken: marketParamsResult[1],\n    oracle: marketParamsResult[2],\n    irm: marketParamsResult[3],\n    lltv: marketParamsResult[4],\n  };\n\n  const rawPosition: UserPosition = {\n    supplyShares: positionResult[0],\n    borrowShares: positionResult[1],\n    collateral: positionResult[2],\n  };\n\n  // Get token information\n  const [loanToken, collateralToken] = await Promise.all([\n    getTokenInfo(client, marketParams.loanToken),\n    getTokenInfo(client, marketParams.collateralToken),\n  ]);\n\n  // Initialize values\n  let currentMarketState = staleMarketState;\n  let interestAccrued = 0n;\n\n  // Calculate current state with interest accrual if IRM is set\n  if (marketParams.irm !== \"0x0000000000000000000000000000000000000000\") {\n    // Get borrow rate from IRM\n    const borrowRate = await client.readContract({\n      address: marketParams.irm,\n      abi: IRM_ABI,\n      functionName: \"borrowRateView\",\n      args: [marketParams, staleMarketState],\n    }) as bigint;\n\n    // Accrue interest to get current state\n    const accrualResult = accrueInterests(staleMarketState, borrowRate, blockTimestamp);\n    currentMarketState = accrualResult.accruedState;\n    interestAccrued = accrualResult.interestAccrued;\n  }\n\n  // Calculate user's real-time asset amounts\n  const supplyAssets = toAssetsDown(\n    rawPosition.supplyShares,\n    currentMarketState.totalSupplyAssets,\n    currentMarketState.totalSupplyShares\n  );\n\n  const borrowAssets = toAssetsUp(\n    rawPosition.borrowShares,\n    currentMarketState.totalBorrowAssets,\n    currentMarketState.totalBorrowShares\n  );\n\n  const collateralAssets = rawPosition.collateral;\n\n  // Get collateral price and calculate health metrics\n  let collateralPrice = 0n;\n  let maxBorrow = 0n;\n  let healthFactor = MAX_UINT256;\n  let isHealthy = true;\n  let liquidationPrice = 0n;\n\n  if (marketParams.oracle !== \"0x0000000000000000000000000000000000000000\") {\n    collateralPrice = await client.readContract({\n      address: marketParams.oracle,\n      abi: ORACLE_ABI,\n      functionName: \"price\",\n    }) as bigint;\n\n    // Calculate maximum borrowing capacity\n    maxBorrow = wMulDown(\n      mulDivDown(collateralAssets, collateralPrice, ORACLE_PRICE_SCALE),\n      marketParams.lltv\n    );\n\n    // Calculate health factor\n    if (borrowAssets > 0n) {\n      healthFactor = wDivDown(maxBorrow, borrowAssets);\n      isHealthy = healthFactor >= WAD;\n      \n      // Calculate liquidation price (price at which position becomes unhealthy)\n      if (collateralAssets > 0n) {\n        liquidationPrice = mulDivUp(\n          borrowAssets * ORACLE_PRICE_SCALE,\n          WAD,\n          mulDivDown(collateralAssets, marketParams.lltv, WAD)\n        );\n      }\n    }\n  }\n\n  // Calculate additional metrics\n  const liquidationBuffer = maxBorrow > borrowAssets ? maxBorrow - borrowAssets : 0n;\n  const currentLTV = maxBorrow > 0n ? Number(wDivDown(borrowAssets, mulDivDown(collateralAssets, collateralPrice, ORACLE_PRICE_SCALE))) / 1e18 * 100 : 0;\n  const maxLTV = formatLLTV(marketParams.lltv);\n  const utilizationOfCollateral = maxBorrow > 0n ? Number(wDivDown(borrowAssets, maxBorrow)) / 1e18 * 100 : 0;\n\n  return {\n    user: userAddress,\n    marketId,\n    marketParams,\n    staleMarketState,\n    currentMarketState,\n    rawPosition,\n    loanToken,\n    collateralToken,\n    lltvPercentage: maxLTV,\n    supplyAssets,\n    borrowAssets,\n    collateralAssets,\n    formattedSupplyAssets: formatUnits(supplyAssets, loanToken.decimals),\n    formattedBorrowAssets: formatUnits(borrowAssets, loanToken.decimals),\n    formattedCollateralAssets: formatUnits(collateralAssets, collateralToken.decimals),\n    collateralPrice,\n    maxBorrow,\n    healthFactor,\n    isHealthy,\n    liquidationBuffer,\n    currentLTV,\n    maxLTV,\n    utilizationOfCollateral,\n    liquidationPrice,\n    interestAccrued,\n    formattedInterestAccrued: formatUnits(interestAccrued, loanToken.decimals),\n    lastUpdateTime: new Date(Number(staleMarketState.lastUpdate) * 1000),\n    blockTimestamp,\n  };\n}\n\n/**\n * Checks if user has any position in the market\n */\nexport async function hasPosition(\n  client: PublicClient,\n  userAddress: Address,\n  marketId: `0x${string}`\n): Promise<boolean> {\n  const position = await client.readContract({\n    address: MORPHO_BLUE_ADDRESS,\n    abi: MORPHO_BLUE_ABI,\n    functionName: \"position\",\n    args: [marketId, userAddress],\n  }) as [bigint, bigint, bigint];\n\n  return position[0] > 0n || position[1] > 0n || position[2] > 0n;\n}\n\n/**\n * Gets user positions across multiple markets efficiently\n */\nexport async function getUserPositionsInMarkets(\n  client: PublicClient,\n  userAddress: Address,\n  marketIds: `0x${string}`[]\n): Promise<UserPositionInfo[]> {\n  console.log(`Fetching positions for user ${userAddress} across ${marketIds.length} markets...`);\n\n  const positionPromises = marketIds.map(marketId =>\n    getUserPositionInfo(client, userAddress, marketId)\n  );\n\n  const allPositions = await Promise.all(positionPromises);\n  \n  // Filter out positions with no assets\n  return allPositions.filter(position =>\n    position.supplyAssets > 0n || position.borrowAssets > 0n || position.collateralAssets > 0n\n  );\n}\n\n/**\n * Displays comprehensive user position information\n */\nexport function displayUserPosition(positionInfo: UserPositionInfo): void {\n  console.log(\"\\n✅ --- User Position Analysis --- ✅\");\n\n  console.log(`\\n--- User & Market Info ---`);\n  console.log(`User: ${positionInfo.user}`);\n  console.log(`Market ID: ${positionInfo.marketId}`);\n  console.log(`Loan Token: ${positionInfo.loanToken.name} (${positionInfo.loanToken.symbol})`);\n  console.log(`Collateral Token: ${positionInfo.collateralToken.name} (${positionInfo.collateralToken.symbol})`);\n  console.log(`Max LTV: ${positionInfo.maxLTV.toFixed(2)}%`);\n\n  console.log(`\\n--- Position Assets (Real-time) ---`);\n  console.log(`Supply: ${positionInfo.formattedSupplyAssets} ${positionInfo.loanToken.symbol}`);\n  console.log(`Borrow: ${positionInfo.formattedBorrowAssets} ${positionInfo.loanToken.symbol}`);\n  console.log(`Collateral: ${positionInfo.formattedCollateralAssets} ${positionInfo.collateralToken.symbol}`);\n\n  console.log(`\\n--- Health Metrics ---`);\n  console.log(`Health Factor: ${formatUnits(positionInfo.healthFactor, 18)}`);\n  console.log(`Is Healthy: ${positionInfo.isHealthy ? \"✅ Yes\" : \"❌ No (Liquidatable!)\"}`);\n  console.log(`Current LTV: ${positionInfo.currentLTV.toFixed(2)}%`);\n  console.log(`LTV Utilization: ${positionInfo.utilizationOfCollateral.toFixed(2)}%`);\n  console.log(`Liquidation Buffer: ${formatUnits(positionInfo.liquidationBuffer, positionInfo.loanToken.decimals)} ${positionInfo.loanToken.symbol}`);\n\n  console.log(`\\n--- Price & Risk Info ---`);\n  console.log(`Collateral Price: ${formatUnits(positionInfo.collateralPrice, 36)} ${positionInfo.loanToken.symbol} per ${positionInfo.collateralToken.symbol}`);\n  if (positionInfo.liquidationPrice > 0n) {\n    console.log(`Liquidation Price: ${formatUnits(positionInfo.liquidationPrice, 36)} ${positionInfo.loanToken.symbol} per ${positionInfo.collateralToken.symbol}`);\n    // Price drop to liquidation is mathematically equivalent to: 100% - utilization of collateral\n    // This avoids precision issues from bigint-to-number conversion\n    const priceDropToLiquidation = 100 - positionInfo.utilizationOfCollateral;\n    console.log(`Price Drop to Liquidation: ${priceDropToLiquidation.toFixed(2)}%`);\n  }\n\n  console.log(`\\n--- Interest Accrual ---`);\n  console.log(`Last Update: ${positionInfo.lastUpdateTime.toISOString()}`);\n  console.log(`Interest Accrued: ${positionInfo.formattedInterestAccrued} ${positionInfo.loanToken.symbol}`);\n\n  console.log(`\\n--- Raw Position Data ---`);\n  console.log(`Supply Shares: ${positionInfo.rawPosition.supplyShares}`);\n  console.log(`Borrow Shares: ${positionInfo.rawPosition.borrowShares}`);\n  console.log(`Collateral (raw): ${positionInfo.rawPosition.collateral}`);\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Displays a summary table of multiple user positions\n */\nexport function displayUserPositionsTable(positions: UserPositionInfo[]): void {\n  if (positions.length === 0) {\n    console.log(\"No positions found for user.\");\n    return;\n  }\n\n  console.log(\"\\n✅ --- User Positions Summary --- ✅\");\n  console.log(`\\nUser: ${positions[0].user}`);\n  console.log(`Total Positions: ${positions.length}`);\n  \n  console.log(\"\\nMarket                       | Loan/Collateral     | Borrowed    | Collateral  | Health Factor | Status\");\n  console.log(\"-----------------------------+---------------------+-------------+-------------+---------------+--------\");\n\n  positions.forEach(position => {\n    const shortMarketId = `${position.marketId.slice(0, 8)}...${position.marketId.slice(-8)}`;\n    const tokenPair = `${position.loanToken.symbol}/${position.collateralToken.symbol}`;\n    const borrowed = parseFloat(position.formattedBorrowAssets).toLocaleString('en-US', { maximumFractionDigits: 2 });\n    const collateral = parseFloat(position.formattedCollateralAssets).toLocaleString('en-US', { maximumFractionDigits: 2 });\n    const healthFactor = Number(formatUnits(position.healthFactor, 18)).toFixed(3);\n    const status = position.isHealthy ? \"✅ Healthy\" : \"❌ Risk\";\n\n    console.log(\n      `${shortMarketId.padEnd(28)} | ${tokenPair.padEnd(19)} | ${borrowed.padStart(11)} | ${collateral.padStart(11)} | ${healthFactor.padStart(13)} | ${status}`\n    );\n  });\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Main function to demonstrate user position analysis\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    \n    console.log(\"=== User Position Analysis Demo ===\\n\");\n    \n    // Check if user has a position in the market\n    const hasPos = await hasPosition(client, EXAMPLE_USER, EXAMPLE_MARKET_ID);\n    console.log(`User has position in market: ${hasPos ? \"✅ Yes\" : \"❌ No\"}`);\n    \n    if (!hasPos) {\n      console.log(\"No position found. Exiting demo.\");\n      return;\n    }\n    \n    // Get detailed position information\n    const positionInfo = await getUserPositionInfo(client, EXAMPLE_USER, EXAMPLE_MARKET_ID);\n    \n    // Display detailed results\n    displayUserPosition(positionInfo);\n    \n    // Example: Get positions across multiple markets (if you have more market IDs)\n    const multipleMarkets = [EXAMPLE_MARKET_ID];\n    const userPositions = await getUserPositionsInMarkets(client, EXAMPLE_USER, multipleMarkets);\n    \n    // Display summary table\n    displayUserPositionsTable(userPositions);\n    \n    console.log(\"\\n=== Demo Complete ===\");\n    \n  } catch (error) {\n    console.error(\"Error in user position analysis:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\n=== User Position Analysis Demo ===\n\nUser has position in market: ✅ Yes\nFetching position for user: 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f in market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\n\n✅ --- User Position Analysis --- ✅\n\n--- User & Market Info ---\nUser: 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f\nMarket ID: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\nLoan Token: USD Coin (USDC)\nCollateral Token: Coinbase Wrapped BTC (cbBTC)\nMax LTV: 86.00%\n\n--- Position Assets (Real-time) ---\nSupply: 0 USDC\nBorrow: 75883503.679379 USDC\nCollateral: 1291.00894824 cbBTC\n\n--- Health Metrics ---\nHealth Factor: 1.472724337032200696\nIs Healthy: ✅ Yes\nCurrent LTV: 58.40%\nLTV Utilization: 67.90%\nLiquidation Buffer: 35871978.968515 USDC\n\n--- Price & Risk Info ---\nCollateral Price: 1006.5634 USDC per cbBTC\nLiquidation Price: 683470337724024509145.488769364009452427844856671826760481 USDC per cbBTC\nPrice Drop to Liquidation: 32.10%\n\n--- Interest Accrual ---\nLast Update: 2025-11-07T10:55:11.000Z\nInterest Accrued: 66.30546 USDC\n\n--- Raw Position Data ---\nSupply Shares: 0\nBorrow Shares: 71029026727778728163\nCollateral (raw): 129100894824\n\n----------------------------------------\nFetching positions for user 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f across 1 markets...\nFetching position for user: 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f in market: 0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64\n\n✅ --- User Positions Summary --- ✅\n\nUser: 0x4352Cc849b33a936Ad93bB109aFDec1c89653b4f\nTotal Positions: 1\n\nMarket                       | Loan/Collateral     | Borrowed    | Collateral  | Health Factor | Status\n-----------------------------+---------------------+-------------+-------------+---------------+--------\n0x64d65c...883fcc64          | USDC/cbBTC          | 75,883,503.68 |    1,291.01 |         1.473 | ✅ Healthy\n\n----------------------------------------\n\n=== Demo Complete ===\n```\n\nThis 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.\n\n### All Market Positions\n\n```graphql [API]\nquery {\n  marketPositions(\n    first: 10\n    orderBy: SupplyShares\n    orderDirection: Desc\n    where: {\n      marketUniqueKey_in: [\n        \"0x698fe98247a40c5771537b5786b2f3f9d78eb487b4ce4d75533cd0e94d88a115\"\n      ]\n    }\n  ) {\n    items {\n      market {\n        uniqueKey\n        loanAsset {\n          address\n          symbol\n        }\n        collateralAsset {\n          address\n          symbol\n        }\n      }\n      user {\n        address\n      }\n      state {\n        supplyShares\n        supplyAssets\n        supplyAssetsUsd\n        borrowShares\n        borrowAssets\n        borrowAssetsUsd\n        collateral\n        collateralUsd\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n## Risk & Oracle Data\n\n### Oracle Data\n\n```graphql [All Markets]\nquery Markets($first: Int, $skip: Int, $orderBy: MarketOrderBy, $orderDirection: OrderDirection, $where: MarketFilters) {\n  markets(first: $first, skip: $skip, orderBy: $orderBy, orderDirection: $orderDirection, where: $where) {\n    items {\n      uniqueKey\n      oracle {\n        address\n        type\n        data {\n          ... on MorphoChainlinkOracleData {\n            baseFeedOne {\n              address\n            }\n            baseFeedTwo {\n              address\n            }\n            baseOracleVault {\n              address\n            }\n            quoteFeedOne {\n              address\n            }\n            quoteFeedTwo {\n              address\n            }\n            scaleFactor\n            vaultConversionSample\n          }\n          ... on MorphoChainlinkOracleV2Data {\n            baseFeedOne {\n              address\n            }\n            baseFeedTwo {\n              address\n            }\n            baseOracleVault {\n              address\n            }\n            baseVaultConversionSample\n            quoteFeedOne {\n              address\n            }\n            quoteFeedTwo {\n              address\n            }\n            quoteOracleVault {\n              address\n            }\n            quoteVaultConversionSample\n            scaleFactor\n          }\n        }\n        creationEvent {\n          txHash\n          timestamp\n          blockNumber\n        }\n      }\n    }\n  }\n}\n```\n\n---\n\n```graphql [Unique Market]\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    uniqueKey\n    oracle {\n      address\n      type\n      creationEvent {\n        txHash\n        timestamp\n        blockNumber\n      }\n      data {\n        ... on MorphoChainlinkOracleV2Data {\n          baseFeedOne {\n            address\n          }\n          baseFeedTwo {\n            address\n          }\n          baseOracleVault {\n            address\n          }\n          baseVaultConversionSample\n          quoteFeedOne {\n            address\n          }\n          quoteFeedTwo {\n            address\n          }\n          quoteOracleVault {\n            address\n          }\n          quoteVaultConversionSample\n          scaleFactor\n        }\n        ... on MorphoChainlinkOracleData {\n          baseFeedOne {\n            address\n          }\n          baseFeedTwo {\n            address\n          }\n          baseOracleVault {\n            address\n          }\n          quoteFeedOne {\n            address\n          }\n          quoteFeedTwo {\n            address\n          }\n          scaleFactor\n          vaultConversionSample\n        }\n      }\n    } \n  }\n}\n```\n\n{\" \"}\n\n### Liquidations\n\n```graphql [API]\nquery {\n  transactions(\n    where: {\n      marketUniqueKey_in: [\n        \"0x49bb2d114be9041a787432952927f6f144f05ad3e83196a7d062f374ee11d0ee\"\n        \"0x093d5b432aace8bf6c4d67494f4ac2542a499571ff7a1bcc9f8778f3200d457d\"\n      ]\n      type_in: [MarketLiquidation]\n    }\n  ) {\n    items {\n      blockNumber\n      hash\n      type\n      user {\n        address\n      }\n      data {\n        ... on MarketLiquidationTransactionData {\n          seizedAssets\n          repaidAssets\n          seizedAssetsUsd\n          repaidAssetsUsd\n          badDebtAssetsUsd\n          liquidator\n          market {\n            uniqueKey\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n### Market Warnings\n\nWarning `type` can be:\n\n- `unrecognized_collateral_asset`: The collateral asset used in the market is not a part of the recognized token list\n- `unrecognized_oracle` : The oracle used in the market is not recognized\n- `unrecognized_loan_asset`: The loan asset used in the market is not a part of our recognized token list\n- `bad_debt_unrealized` & RED level: This market has significant unrealized bad debt (>25 BPS total supply)\n- `bad_debt_unrealized` & YELLOW level: This market has some unrealized bad debt (>$10k)\n- `bad_debt_realized`: This market has some realized bad debt (>10 BPS of total supply)\n\nWarning `level` is either:\n\n- YELLOW\n- RED\n\n---\n\n```graphql [API]\nquery {\n  markets {\n    items {\n      uniqueKey\n      warnings {\n        type\n        level\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n## Integration\n\n### Vault Listing\n\nThe following query corresponds to which vault has this market in its supply queue\n\n---\n\n```graphql [API]\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    uniqueKey\n    supplyingVaults {\n      address\n      symbol\n      metadata {\n        description\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n## Historical Data\n\nThe `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).\n\nAvailable options when using an `historicalState` query:\n\n- `startTimestamp`: beginning of the historical data in UNIX timestamp format,\n- `endTimestamp`: end of the historical data in UNIX timestamp format,\n- `interval`: interval of the historical data points (`YEAR`, `QUARTER`, `MONTH`, `WEEK`, `DAY`, `HOUR`).\n\nInputting these options is not mandatory but it is advised to specify them to control the specific data returned.\n\nIf no options are specified, the default values will be:\n\n- `startTimestamp`: 0,\n- `endTimestamp`: infinity,\n- `interval`: will adjust according to `startTimestamp` and `endTimestamp` to return around 50 data points.\n\n`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: \"\")`.\n\n### Historical APYs\n\nThe example below mirrors the structure shown in the Morpho API sandbox, so you can copy/paste it directly when testing queries.\n\n```graphql [API]\nquery MarketByUniqueKey($uniqueKey: String!, $chainId: Int, $options: TimeseriesOptions) {\n  marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {\n    historicalState {\n      borrowApy(options: $options) {\n        x\n        y\n      }\n      supplyApy(options: $options) {\n        x\n        y\n      }\n    }\n  }\n}\n```\n\n---\n\nwith the following variables\n\n```json\n{\n  \"uniqueKey\": \"0x608929d6de2a10bacf1046ff157ae38df5b9f466fb89413211efb8f63c63833a\",\n  \"options\": {\n    \"startTimestamp\": 1707749700,\n    \"endTimestamp\": 1708354500,\n    \"interval\": \"HOUR\"\n  }\n}\n```\n\n{\" \"}\n\n### Historical Market States\n\n```graphql [API]\nquery MarketApys($options: TimeseriesOptions) {\n  marketByUniqueKey(\n    uniqueKey: \"0x608929d6de2a10bacf1046ff157ae38df5b9f466fb89413211efb8f63c63833a\"\n  ) {\n    uniqueKey\n    historicalState {\n      supplyAssetsUsd(options: $options) {\n        x\n        y\n      }\n      borrowAssetsUsd(options: $options) {\n        x\n        y\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n### Historical Asset Price\n\n```graphql [API]\nquery {\n  wstETHWeeklyPriceUsd: assetByAddress(\n    address: \"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0\"\n    chainId: 1\n  ) {\n    historicalPriceUsd(\n      options: {\n        startTimestamp: 1707749700\n        endTimestamp: 1708354500\n        interval: HOUR\n      }\n    ) {\n      x\n      y\n    }\n  }\n}\n```\n\n{\" \"}"
  },
  "/build/borrow/tutorials/public-allocator/": {
    "title": "Triggering the Public Allocator",
    "url": "https://docs.morpho.org/build/borrow/tutorials/public-allocator/",
    "section": "Build",
    "content": "This tutorial explains how to trigger a reallocation using the Public Allocator to provide just-in-time liquidity for a borrow transaction.\n\nBefore you begin, make sure you understand the core concepts behind the Public Allocator and why it's a powerful tool for enhancing liquidity.\n\n**Review the [Public Allocator Concept Page](/build/borrow/concepts/public-allocator) first.**\n\n## The Core Action: `reallocateTo`\n\nThe 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.\n\n```solidity\nfunction reallocateTo(\n    address vault,\n    Withdrawal[] calldata withdrawals,\n    MarketParams calldata supplyMarketParams\n) external payable;\n```\n- **`vault`**: The vault whose funds are being reallocated.\n- **`withdrawals`**: An array of structs, each specifying a source market and the amount to withdraw.\n- **`supplyMarketParams`**: The destination market where all withdrawn funds will be deposited.\n\n## Method 1: Manual Trigger via Etherscan (For Learning)\n\nManually triggering the `reallocateTo` function on a block explorer is a great way to understand its inputs.\n\n#### 1. Check Prerequisites\n\nBefore sending a transaction, verify:\n-   The Public Allocator has the **allocator role** for the target vault.\n-   The source markets have sufficient **`maxOut`** capacity and the destination market has sufficient **`maxIn`** capacity.\n-   You have the correct `marketId` for all source markets and the `marketParams` for the destination market.\n-   You know the `fee` required for the transaction, which can be read from the `fee(vaultAddress)` view function on the Public Allocator contract.\n\n#### 2. Structure the `withdrawals` Array\n\nThe `withdrawals` array must be **sorted in ascending order by market ID**.\n\n#### 3. Execute the Transaction\n\nOn 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.\n\n**Example Input:**\nThis 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.\n\n```json\n// Payable Amount (Value): [Fee in ETH, e.g., 0.001]\n{\n  \"vault\": \"0x38989bba00bdf8181f4082995b3deae96163ac5d\",\n  \"withdrawals\": [\n    // Withdrawal from Idle Market (assuming it has the lower marketId)\n    {\n      \"marketParams\": { \"loanToken\": \"0xc02...\", \"collateralToken\": \"0x000...\", ... },\n      \"amount\": \"70000000000000000000\"\n    },\n    // Withdrawal from wstETH/WETH market\n    {\n      \"marketParams\": { \"loanToken\": \"0xc02...\", \"collateralToken\": \"0x7f3...\", ... },\n      \"amount\": \"800000000000000000000\"\n    }\n  ],\n  \"supplyMarketParams\": {\n    \"loanToken\": \"0xc02...\",\n    \"collateralToken\": \"0xae7...\",\n    ...\n  }\n}\n```\nAfter this transaction, the rETH market will have an additional 870 WETH of liquidity available to borrow.\n\n## Method 2: Programmatic Trigger (SDK & API)\n\nFor 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.\n\nThe general logic is:\n1.  **Check Target Market Liquidity**: See if the user's borrow can be fulfilled without reallocation.\n2.  **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.\n3.  **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.\n\n**Example Implementation: Bundle Reallocation and Borrow**\n\nThis 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.\nFor working examples, check out the [earn-basic-app](https://github.com/morpho-org/earn-basic-app) repositories.\n\n### Prerequisites Using SDKs\n\nThe [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.\n\nThe bundler works by:\n\n- Simulating the full sequence of operations.\n- Populating a bundle with required ERC20 operations.\n- Optimizing the operations (merging duplicates, redirecting tokens when possible).\n- Encoding the bundle for submission using Viem.\n\n#### Installation\n\nInstall the bundler package along with its required peer dependencies:\n\n```bash\nyarn add @morpho-org/bundler-sdk-viem @morpho-org/blue-sdk @morpho-org/morpho-ts viem\n```\n\n#### Setup\n\nFirst, 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:\n\n```typescript\nimport {\n  populateBundle,\n  finalizeBundle,\n  encodeBundle,\n  type BundlingOptions,\n  type InputBundlerOperation,\n} from \"@morpho-org/bundler-sdk-viem\";\n\nimport { MarketId, DEFAULT_SLIPPAGE_TOLERANCE } from \"@morpho-org/blue-sdk\";\nimport { SimulationState } from \"@morpho-org/simulation-sdk\";\nimport { WalletClient } from \"viem\";\n```\n\nAlso, 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).\n\n### Core Concepts\n\n#### Bundled Operations\n\nThe [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:\n\n- Blue_Borrow\n\nThe bundler automatically adds:\n\n- The required ERC20 approvals (via Erc20_Approve, Erc20_Permit, or Erc20_Permit2)\n- ERC20 transfers from the user to the bundler\n- Additional steps such as token wrapping or unwrapping\n\n#### Using Slippage Tolerance\n\nWhen 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:\n\n- Accrued interest might change the expected output amount\n- Market states may be updated by other transactions\n- Vault conditions might shift slightly\n\nThe `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.\n**Important**: Always include the slippage parameter in operations that involve asset conversions.\n\n### Key Functions\n\n#### populateBundle\n\nThis function is the entry point to convert an array of InputBundlerOperation into a bundle of low-level operations. It:\n\n- Simulates each input operation using the current SimulationState.\n- Returns an object containing the bundled operations along with the simulation steps.\n\n```typescript\nconst { operations, steps } = populateBundle(\n  inputOperations,\n  simulationState,\n  bundlingOptions\n);\n```\n\n#### finalizeBundle\n\nAfter populating the bundle, finalizeBundle is used to:\n\n- Merge duplicate operations (e.g., multiple ERC20 approvals or transfers).\n- Optimize the operation sequence by redirecting tokens (e.g., from the bundler to the receiver).\n- Append any additional transfer operations to “skim” any remaining tokens.\n\n```typescript\nconst optimizedOperations = finalizeBundle(\n  operations,\n  simulationState,\n  receiverAddress,\n  unwrapTokensSet,\n  unwrapSlippage\n);\n```\n\n#### encodeBundle\n\nOnce 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.\n\n### Simulation & Error Handling\n\nThe [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:\n\n- Simulate the effect of each bundled operation on your current state.\n- Determine how much of each token is required (especially for ERC20 transfers).\n- Handle errors by providing detailed simulation steps, which can be very useful during development and testing.\n\nAlways wrap your bundling logic in a try-catch block to capture and log errors.\n\n### Advanced Bundling Options\n\nYou can enable public reallocation via the BundlingOptions parameter:\n\n```typescript\nconst bundlingOptions: BundlingOptions = {\n  withSimplePermit: new Set([\"0xTokenAddress1\", \"0xTokenAddress2\"]),\n  publicAllocatorOptions: {\n    enabled: true,\n    supplyTargetUtilization: {\n      [marketId]: 905000000000000000n, // For a specific market\n    },\n    defaultSupplyTargetUtilization: 905000000000000000n,\n  },\n};\n```\n\nThese options allow you to:\n\n- Force simple permit flows on certain tokens\n- Trigger liquidity reallocation when the market’s utilization exceeds a target threshold\n\n### Sending the Transaction\n\nOnce 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.\n\n### Example Implementation\n\nLet's walk through a practical example that demonstrates how to bundle a borrow action with public reallocation enabled, if needed.\n\nYou can find a complete working implementation in our [bundler-basic-app](https://github.com/morpho-org/bundler-basic-app) repository.\n\n```typescript\nimport { type Account, WalletClient, zeroAddress } from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\n\nimport {\n  type Address,\n  addresses,\n  ChainId,\n  DEFAULT_SLIPPAGE_TOLERANCE,\n  MarketId,\n  MarketParams,\n  UnknownMarketParamsError,\n  getUnwrappedToken,\n} from \"@morpho-org/blue-sdk\";\nimport {\n  type BundlingOptions,\n  type InputBundlerOperation,\n  encodeBundle,\n  finalizeBundle,\n  populateBundle,\n} from \"@morpho-org/bundler-sdk-viem\";\nimport \"@morpho-org/blue-sdk-viem/lib/augment\";\nimport { withSimplePermit } from \"@morpho-org/morpho-test\";\nimport {\n  type SimulationState,\n  SimulationState,\n  isBlueOperation,\n  isErc20Operation,\n  isMetaMorphoOperation,\n} from \"@morpho-org/simulation-sdk\";\n\nexport const setupBundle = async (\n  client: WalletClient,\n  startData: SimulationState,\n  inputOperations: InputBundlerOperation[],\n  {\n    account: account_ = client.account,\n    supportsSignature,\n    unwrapTokens,\n    unwrapSlippage,\n    onBundleTx,\n    ...options\n  }: BundlingOptions & {\n    account?: Address | Account;\n    supportsSignature?: boolean;\n    unwrapTokens?: Set<Address>;\n    unwrapSlippage?: bigint;\n    onBundleTx?: (data: SimulationState) => Promise<void> | void;\n  } = {}\n) => {\n  if (!account_) throw new Error(\"Account is required\");\n  const account = parseAccount(account_);\n\n  let { operations } = populateBundle(inputOperations, startData, {\n    ...options,\n    withSimplePermit: new Set([\n      ...withSimplePermit[startData.chainId],\n      ...(options?.withSimplePermit ?? []),\n    ]),\n    publicAllocatorOptions: {\n      enabled: true,\n      ...options.publicAllocatorOptions,\n    },\n  });\n  operations = finalizeBundle(\n    operations,\n    startData,\n    account.address,\n    unwrapTokens,\n    unwrapSlippage\n  );\n\n  const bundle = encodeBundle(operations, startData, supportsSignature);\n\n  const tokens = new Set<Address>();\n\n  operations.forEach((operation) => {\n    const { address } = operation;\n\n    if (\n      isBlueOperation(operation) &&\n      operation.type !== \"Blue_SetAuthorization\"\n    ) {\n      try {\n        const marketParams = MarketParams.get(operation.args.id);\n\n        if (marketParams.loanToken !== zeroAddress)\n          tokens.add(marketParams.loanToken);\n\n        if (marketParams.collateralToken !== zeroAddress)\n          tokens.add(marketParams.collateralToken);\n      } catch (error) {\n        if (!(error instanceof UnknownMarketParamsError)) throw error;\n      }\n    }\n\n    if (isMetaMorphoOperation(operation)) {\n      tokens.add(address);\n\n      const vault = startData.tryGetVault(address);\n      if (vault) tokens.add(vault.asset);\n    }\n\n    if (isErc20Operation(operation)) {\n      tokens.add(address);\n\n      const unwrapped = getUnwrappedToken(address, startData.chainId);\n      if (unwrapped != null) tokens.add(unwrapped);\n    }\n  });\n\n  await onBundleTx?.(startData);\n\n  // here EOA should sign tx, if it is a contract, this can be ignored/removed\n  await Promise.all(\n    bundle.requirements.signatures.map((requirement) =>\n      requirement.sign(client, account)\n    )\n  );\n\n  const txs = bundle.requirements.txs.map(({ tx }) => tx).concat([bundle.tx()]);\n\n  for (const tx of txs) {\n    await client.sendTransaction({ ...tx, account });\n  }\n\n  return { operations, bundle };\n};\n\nconst { morpho } = addresses[ChainId.EthMainnet];\n\n/**\n * Executes a borrow Morpho operation, via the Bundler\n * @param marketId - The ID of the market to interact with\n * @param client - The wallet client instance\n * @param simulationState - The current simulation state\n * @param amountSupply - Amount to supply as lending position\n * @param amountSupplyCollateral - Amount to supply as collateral\n * @param amountBorrow - Amount to borrow\n * @returns Array of transaction responses\n */\nexport const Borrow = async (\n  marketId: MarketId,\n  client: WalletClient,\n  simulationState: SimulationState,\n  amountSupply: bigint,\n  amountSupplyCollateral: bigint,\n  amountBorrow: bigint\n) => {\n  const user = client.account?.address;\n  if (!user) throw new Error(\"User address is required\");\n  return setupBundle(client, simulationState, [\n    {\n      type: \"Blue_Borrow\",\n      sender: user,\n      address: morpho,\n      args: {\n        id: marketId,\n        assets: amountBorrow,\n        onBehalf: user,\n        receiver: user,\n        slippage: DEFAULT_SLIPPAGE_TOLERANCE,\n      },\n    },\n  ]);\n};\n```\n\n#### Main SDK Repository:\n\nFor 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.\n\nFor a detailed, working example of how to implement this logic using TypeScript, Viem, and the Morpho API, refer to the **public-allocator-scripts** repository.\n\n**[View the Public Allocator Simulation Script on GitHub](https://github.com/morpho-org/public-allocator-scripts/blob/main/scripts/api/apiPublicAllocatorSimulated.ts)**"
  },
  "/build/borrow/tutorials/rewards/": {
    "title": "Integrate Rewards for Borrow Products",
    "url": "https://docs.morpho.org/build/borrow/tutorials/rewards/",
    "section": "Build",
    "content": "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.\n\n## What's Unique for Borrow Products\n\nWhen building borrow products, understand that borrowers earn rewards for borrowing an asset from a market\n\n**Critical integration requirement:**\n```\nNet Borrow APY = Borrow APY - Borrow Rewards APR\n```\n\nIt is also possible to incentivize a simple collateral deposit (without the borrow action required).\n\nWhen rewards exceed costs, net APY becomes negative (profitable borrowing).\n\nRewards 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.\n\n## Integration Steps\n\nFollow the centralized rewards tutorials with borrow-specific considerations:\n\n### Step 1: Fetch Market Rewards Data\n\n**Follow:** [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)\n\n**Borrow-specific notes:**\n- Query `state.rewards` on market object\n- Look for `borrowApr` (rewards for borrowing)\n- No weighted averaging needed (unlike vaults)\n\n### Step 2: Display Rewards in Your UI\n\n**Follow:** [Integrate Rewards Display](/build/rewards/tutorials/integrate-display)\n\n**Borrow-specific notes:**\n- Show **net cost** prominently (borrow cost - all rewards)\n- Highlight when borrowing becomes profitable (negative net APY)\n- Break down: borrow cost, borrow rewards\n- List reward tokens with their respective APRs\n- Calculate per-position rewards based on user amounts\n\n### Step 3: Enable Reward Claiming\n\n**Follow:** [Claim Rewards](/build/rewards/tutorials/claim-rewards)\n\n**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.\n\n## Complete Integration Example\n\nFor a full working reference implementation:\n\n**See:** [Complete Rewards Integration Guide](/build/rewards/guides/complete-integration)\n\nThis guide includes production-ready code using the [morpho-merkl-recipe](https://github.com/morpho-org/merkl-morpho-recipe).\n\n## Quick Reference\n\n| Task                      | Main Tutorial                                                      | Borrow-Specific Consideration         |\n|---------------------------|--------------------------------------------------------------------|---------------------------------------|\n| **Understanding rewards** | [Reward Campaigns](/build/rewards/concepts/reward-campaigns)       | Understand dual eligibility           |\n| **Distribution system**   | [Distribution System](/build/rewards/concepts/distribution-system) | Same Merkl/URD for all users          |\n| **Fetch rewards**         | [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)  | Query single location, no aggregation |\n| **Display rewards**       | [Integrate Display](/build/rewards/tutorials/integrate-display)    | Show net cost after rewards           |\n| **Claim rewards**         | [Claim Rewards](/build/rewards/tutorials/claim-rewards)            | Same process for all users            |\n\n## Need Help?\n\n- **Conceptual questions**: [Rewards for Borrowers Concept](/build/borrow/concepts/rewards)\n- **Main rewards guide**: [Rewards Integration Guide](/build/rewards/get-started)\n- **Technical support**: [help.morpho.org](https://help.morpho.org)\n- **Example code**: [morpho-merkl-recipe](https://github.com/morpho-org/merkl-morpho-recipe)"
  },
  "/build/earn/concepts/generate-revenue/": {
    "title": "How can distributors generate revenue on Morpho?",
    "url": "https://docs.morpho.org/build/earn/concepts/generate-revenue/",
    "section": "Build",
    "content": "**There are different ways to generate revenue on Morpho.**\n\nCurators and distributor channels have different ways to charge fees.\n\nA 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.\n\nTo generate revenue, a distributor has several possibilities developed below:\n- Own its own revenue layer (a Fee Wrapper or a Vault V2 Wrapper)\n- Have an agreement with a curator (onchain or offchain)\n\n## Fees\n\nMorpho Vault V2 can charge 2 types of fees, while Morpho Vault V1 has only one:\n\n| Fees                                                  | Vault V2       | Vault V1      |\n| ----------------------------------------------------- | -------------- | ------------- |\n| Performance fee (taken on the native yield)           | ✅    0% → 50% | ✅    0% → 50% |\n| Management fee (taken on the Assets Under Curation)   | ✅    0% →  5% |       ❌       |\n\n## Architecture\n\nHere is the setup of the current Earn architecture with USDC as an example\n\n  \n\nHere is the vault model illustrating asset flow in terms of allocation\n\n  \n\n## Examples of possible configurations\n\n| Model | Control | Trust Required | Complexity | Best For |\n| --- | --- | --- | --- | --- |\n| **Fee Wrapper** | High | None | Low | B2B distribution, per-customer vaults |\n| **V2 Wrapper** | High | None | Low | Independent distributors |\n| **Offchain Agreement** | Shared | High | Medium | Strategic partnerships |\n| **Onchain Splitter** | Shared | None | High | Formal trustless partnerships |\n\n------------------------- | ------------------------------------------------------------------------------- |\n| **ERC-4626 Compliant**       | All standard vault functions work as expected                                   |\n| **Immutably Bound**          | Bound to a single Morpho Vault V2 at deployment. Can **not** be changed         |\n| **Fee Flexibility**          | Owner can configure performance fees (up to 50%) and management fees (up to 5%) |\n| **Simplified Configuration** | Risk management functions are abdicated, making operation simpler               |\n| **Shared Liquidity**         | Users share the liquidity of the underlying Morpho Vault V2                     |\n\n#### Use Cases\n\n- **B2B Distribution**: Distributors can deploy one Fee Wrapper per customer, each with custom fee configurations\n- **Revenue Sharing**: Split native yield between the distribution channel and end users (e.g., 50/50 split via fee configuration)\n- **White-Label Products**: Distributor can offer Morpho yield under their own brand with their own fee structure\n\n#### Yield and Rewards\n\n**Native Yield (Inside ERC-4626 Flow)**\n\nNative 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.\n\n**External Rewards (Outside ERC-4626 Flow)**\n\nExternal 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.\nIt 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.\n\n#### Integration Guide\n\nExact query and formulas used in this page so partners can integrate the same post-fee APY logic directly. No on-chain reads needed — all data comes from the API.\n\n#### 1. Query the Morpho API\n\nEndpoint: POST https://api.morpho.org/graphql\n\nUse the fee wrapper address directly (not the underlying Morpho Vault V2 address) along with the chainID as variables.\n\n```graphql\nquery FeeWrapperAPY($feeWrapper: String!, $chainId: Int!) {\n  feeWrapper: vaultV2ByAddress(address: $feeWrapper, chainId: $chainId) {\n    avgNetApy\n    avgNetApyExcludingRewards\n    performanceFee\n    managementFee\n    name\n    symbol\n    rewards {\n      supplyApr\n      asset { address, symbol }\n    }\n    adapters {\n      items {\n        type\n        address\n        ... on MorphoVaultV2Adapter {\n          innerVault {\n            address\n            name\n            avgApy\n            performanceFee\n            managementFee\n            rewards {\n              supplyApr\n              asset { address, symbol }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n#### 2. Compute Net APY (6h rolling avg)\n```\n// From API response:\n// grossApy = feeWrapper.adapters[0].innerVault.avgApy   (6h rolling avg)\n// Rewards  = innerVault.rewards[].supplyApr              (pass through to depositors)\n\nadapterYield = grossApy * (1 - innerVault.performanceFee) - innerVault.managementFee\nwrapperPerfFeeDeduction = max(adapterYield, 0) * feeWrapper.performanceFee\nnativeYield = adapterYield - wrapperPerfFeeDeduction - feeWrapper.managementFee\nrewardsApr = sum(innerVault.rewards[].supplyApr)\nnetApy = nativeYield + rewardsApr\n```\n\n> **Note:** `avgApy` is the 6h rolling average — provides a stable, smoothed rate. Rewards are sourced from the inner vault (`innerVault.rewards[]`), rewards are distributed via Merkl based on the inner vault's market positions.\n\nThe API also exposes avgNetApy and avgNetApyExcludingRewards on the fee wrapper. These are 6h rolling net values computed by the API.\n\nFor newly deployed fee wrappers, these fields may be noisy or zero until sufficient history accumulates. The manual computation using innerVault.avgApy is recommended for consistent results across all wrappers.\n\n> If rewards are redirected via Merkl address remapping, omit `rewardsApr` from the final sum (end users do not receive them).\n\nMore FeeWrapper API data can be found [here](/build/earn/tutorials/get-data#fee-wrapper).\n\n#### Deployment\n\nThe simplest deployment method uses the FeeWrapperDeployer periphery contract:\n\n- [FeeWrapperDeployer source code](https://github.com/morpho-org/vault-v2/blob/main/src/periphery/FeeWrapperDeployer.sol)\n- [Fee Wrapper Demo App](https://fee-wrapper-demo.vercel.app/), allows you to:\n  - Deploy a Fee Wrapper\n  - Check if a Fee Wrapper is properly configured\n  - Update fees on an existing Fee Wrapper\n  - Enter a fee wrapper address to see the full yield breakdown\n\nFind the factory addresses in [addresses section](/get-started/resources/addresses/).\n\n#### Security Considerations\n\n**What the Owner CAN Do:**\n- Change performance fees (up to 50%, timelocked)\n- Change management fees (up to 5%, timelocked)\n- Change fee recipients (timelocked)\n- Add/remove allocators (timelocked)\n\n**What the Owner CANNOT Do:**\n- Change the underlying vault (abdicated)\n- Add new adapters (abdicated)\n- Remove the existing adapter (abdicated)\n- Access user funds directly\n- Prevent users from exiting (via forceDeallocate)\n\n---\n\n### 2. Offchain Agreement Model\n\n**Setup:** Distributor and curator establish a legal revenue-sharing agreement for liquidity provided.\n\n**Two Options:**\n\n**Option A - New Dedicated Vault:**\n\n  \n\n- Curator launches new vault (V1 or V2) exclusively for distributor's users\n- Fee split negotiated up-front (e.g., 50/50 on performance fees)\n- Clean attribution of liquidity and fees\n\n---\n\n**Option B - Existing Vault:**\n\n  \n\n- Distributor directs users to existing vault\n- Revenue share calculated based on tracked liquidity contribution\n- Requires tracking mechanism (transaction mapping, user addresses, time-weighted deposits)\n\n**Considerations:**\n\n- Legal contract enforces agreement\n- Option B requires reliable attribution system\n- Settlement handled offchain (periodic payouts)\n\n**Use Case:** Best for strategic partnerships where trust exists or when onchain complexity isn't warranted.\n\n---\n\n### 3. Onchain Splitter Contract Model\n\n  \n\n**Setup:** Smart contract automatically splits fees between curator and distributor based on pre-defined terms.\n\n**Requirements:**\n\n- Dedicated new vault (V1 or V2) for the partnership\n- Splitter contract receives fee recipient role\n- Automated distribution of fees to both parties\n\n**Fee Flow:**\n\n1. Vault accrues performance/management fees\n2. Fees sent to splitter contract\n3. Contract automatically distributes per agreement (e.g., 60% curator / 40% distributor, or 50/50)\n\n**Advantages:**\n\n- Trustless execution\n- Transparent onchain tracking\n- No manual settlement required\n\n**Trade-offs:**\n\n- Requires dedicated vault (curator unlikely to share existing vault)\n- Additional smart contract complexity\n- Gas costs for splitting operations\n\n**Use Case:** Best for formal partnerships requiring trustless, transparent revenue sharing with onchain guarantees."
  },
  "/build/earn/concepts/rewards/": {
    "title": "Rewards for Lenders",
    "url": "https://docs.morpho.org/build/earn/concepts/rewards/",
    "section": "Build",
    "content": "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.\n\n## Overview\n\nWhen you deposit into a Morpho Vault, you can earn rewards from **two distinct sources**:\n\n1. **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.\n2. **Forwarded Market Campaigns**: Rewards earned from underlying markets where the vault allocates liquidity\n\nThe total yield a depositor earns combines the native lending APY with reward APR from both sources:\n\n```\nNet APY = Native Vault APY + Vault Campaign APR + Forwarded Market Campaign APR\n```\n\n## What Makes Vault Rewards Unique\n\n### Reward Forwarding\n\nThis 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.\n\n**How it works:**\n\n1. A Morpho Market has an active supply campaign\n2. Your vault allocates liquidity to that market as a supplier\n3. The vault contract earns those market rewards\n4. Rewards are automatically reallocated to individual vault depositors\n5. You claim these forwarded rewards directly\n\n**Why this matters:**\n- You benefit from ALL active campaigns across the markets your vault uses\n- Vault curators optimize allocations, and you receive rewards automatically\n- More capital-efficient than directly supplying to individual markets\n\n### Complete APY Components\n\nThe net APY shown to users combines multiple components:\n\n```\nNet APY = Native APY + Underlying Token Yield + Rewards APR - Performance Fee\n```\n\nWhere:\n- **Native APY**: Native vault yield before fees and rewards\n- **Underlying Token Yield**: Yield from the asset itself (for yield-bearing tokens)\n- **Rewards APR**: Vault rewards + weighted market rewards\n- **Performance Fee**: Applied only to base APY\n\n## Distribution System\n\nRewards 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.\n\nThe claiming process is **identical** for all Morpho users, regardless of whether they're depositors, borrowers, or collateral suppliers.\n\n**For complete details on distribution systems, see:**\n- [Distribution System](/build/rewards/concepts/distribution-system)\n- [Reward Campaigns](/build/rewards/concepts/reward-campaigns)\n\n## Learn More\n\nFor comprehensive information about integrating rewards:\n\n- **[Rewards Integration Guide](/build/rewards/get-started)**: Complete overview and integration paths\n- **[Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)**: Complete API queries and calculations\n- **[Claim Rewards](/build/rewards/tutorials/claim-rewards)**: Implementation for both Merkl and URD\n- **[Integrate Display](/build/rewards/tutorials/integrate-display)**: UI/UX best practices\n\n## Implementation\n\nFor practical implementation guidance specific to earn products, see:\n- [Integrate Rewards for Earn Products](/build/earn/tutorials/rewards)"
  },
  "/build/earn/concepts/vault-mechanics/": {
    "title": "Vaults & ERC4626 Mechanics",
    "url": "https://docs.morpho.org/build/earn/concepts/vault-mechanics/",
    "section": "Build",
    "content": "**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.\n\n## ERC4626 Standard\n\nThe ERC‑4626 standard defines four core functions for deposits and withdrawals.\n\n### Core Functions\n\n#### Deposit\n```solidity\n// Deposit a specific amount of underlying assets.\n// Example: deposit 10 USDC and receive N vault shares.\nfunction deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n// Mint a specific amount of shares.\n// Example: mint N shares; the corresponding assets are pulled from the user.\nfunction mint(uint256 shares, address receiver) external returns (uint256 assets);\n```\n\n#### Withdraw\n```solidity\n// Withdraw a specific amount of assets.\n// Example: withdraw 10 USDC; N shares are burned.\nfunction withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n// Redeem a specific amount of shares for assets.\nfunction redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n```\n\n## Assets vs. Shares\n\n**Assets** are the underlying token (e.g., USDC, WETH).  \n**Shares** represent proportional ownership of the vault and typically appreciate as yield accrues.\n\n### Conversions\n```ts\n// Convert assets to shares (pre‑deposit expectation).\nconst shares = await vault.previewDeposit(assetAmount);\n\n// Convert shares to assets at the current rate.\nconst assets = await vault.convertToAssets(shareAmount);\n\n// Estimate shares needed to withdraw a target asset amount.\nconst sharesNeeded = await vault.previewWithdraw(assetAmount);\n\n// Estimate assets received when redeeming shares.\nconst assetsReceived = await vault.previewRedeem(shareAmount);\n```\n\n## Share Price Appreciation\n\nVault performance is reflected in the share price:\n```ts\n// 1 vault share = 1e18\nconst sharePrice = await vault.convertToAssets(10n ** 18n);\n// Example: totalAssets grows from 1.0M to 1.1M with 1.0M shares\n// -> price from $1.00/share to $1.10/share (≈10%)\n```\n\n## Inflation Attack Protection\n\nERC4626 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.\n\n### The Protection Mechanism\n\nBefore 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.\n\n**The Check:**\n```ts\n// Verify the vault has adequate dead deposit protection\nconst deadAddress = \"0x000000000000000000000000000000000000dEaD\";\nconst deadShares = await vault.balanceOf(deadAddress);\n\n// Minimum threshold: 1e9 shares (~$10 equivalent for most assets)\nif (deadShares < 1_000_000_000n) {\n  throw new Error(\"Vault lacks adequate inflation protection\");\n}\n```\n\n**Why 1e9 shares?**\nThis 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.\n\nFor assets with less than 9 decimals, the recommended minimum is 1e12 shares to prevent rounding issues (non-critical).\n\n**Implementation Notes:**\n- The dead deposit does not need to be made atomically with your interaction\n- Once established, it cannot be withdrawn (by design)\n- Both Morpho Vault V1 and V2 should have this protection in place\n- Curators and vault deployers are responsible for ensuring this protection exists\n\nThis 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).\n\n## Additional Considerations: Slippage\n\nERC4626 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.\n\n**When to consider slippage protection:**\n- Share price may shift due to interest accrual or other vault activity between simulation and inclusion\n- User-facing applications benefit from showing expected vs. actual amounts received\n- Implement min-received checks around ERC4626 operations for direct integrations\n\nSee the [Assets Flow tutorial](/build/earn/tutorials/assets-flow) for integration examples."
  },
  "/build/earn/concepts/yield-fees/": {
    "title": "Yield & Fees",
    "url": "https://docs.morpho.org/build/earn/concepts/yield-fees/",
    "section": "Build",
    "content": "Understanding how yield is generated and fees are applied in Morpho Vaults is crucial for building accurate earn products and setting proper user expectations.\n\n## Yield Generation\n\nWhile **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**. \n\n  \n\n### Where does the yield comes from? \n\n#### Borrower Interest\nBorrowers in underlying Morpho Markets pay interest\n\n#### Market Distribution\nInterest flows to lenders in each market\n\n#### Vault Collection\nVault collects interest as a lender across multiple markets\n\n#### Share Price Increase\nVault's total assets increase, raising share price\n\n#### Depositor Interest\nDepositors earn the interest paid by borrowers as the share of their position increased in token's value amount.\n\n## Fee Mechanism\n\n**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.\n\n### Performance Fee\n\nThe fee is taken as a cut on the native yield earned by allocating capital, and is capped at 50%.\n\n### Management Fee\n\nFor Morpho Vaults V2 only, this management fee is taken on the total asset deposited on the vault, and is capped at 5%.\n\n## Integration Best Practices\n\n### Real-Time Updates\n- Update share prices regularly\n- Show pending yield that hasn't been reflected in share price yet by accruing interests on the underlying markets\n- Display historical performance charts\n\n### User Education\n- Clearly explain that performance fees only apply to yield, not principal, while management fee apply on the principal.\n\n### Performance Monitoring\n- Track vault performance against benchmarks\n- Alert users to significant strategy changes\n- Provide detailed yield attribution"
  },
  "/build/earn/get-started/": {
    "title": "Morpho Vaults for Earn products",
    "url": "https://docs.morpho.org/build/earn/get-started/",
    "section": "Build",
    "content": "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.\n\nAs of today, one can integrate both [Morpho Vaults V2](/learn/concepts/vault-v2/) and [Morpho Vaults V1](/learn/concepts/vault/). \n\nThe users will benefit from earning native yield on their deposited assets, alongside with incentives (rewards) from different rewards provider.\n\n## Key Components of Earn Integration\n\nWhen building earn products with Morpho Vaults, you need to integrate three main components:\n\n1. **Vault Operations**: Deposit, withdraw, and position management\n2. **Yield Tracking**: Vault APY calculation and performance monitoring  \n3. **Rewards Integration**: Discovery, tracking, and claiming of additional incentives\n\nHere is a quick visual for better understanding:\n\n{\" \"}\n\n  \n\nIntegrating Earn gives users access to:\n\n1. **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.\n\n2. **Permissionless Infrastructure**: Any entity (individual, DAO, protocol) can create and manage vaults with different risk parameters and allocation strategies.\n\n3. **Non-Custodial Architecture**: All positions remain fully controlled by the user with transparent onchain verification of allocations and immutable vault logic.\n\n## Technical Components\n\nFrom a technical standpoint, integrating Earn involves:\n\n1. **Vault Discovery and Display**: Implementing systems to discover available vaults, display their key metrics (APY, TVL, allocation breakdown), and present risk profiles to users.\n\n2. **Transaction Handling**: Building the interface and backend support for deposit and withdrawal operations, including:\n\n   - Asset approval workflows\n   - Transaction status monitoring\n   - Receipt confirmation and position updates\n   - Rewards tracking updates\n\n3. **Position Management**: Creating interfaces for users to:\n\n   - View their current vault positions\n   - Track historical performance\n   - Monitor yield accrual\n   - Perform deposits & withdrawals\n   - Claim rewards\n\n4. **Risk Transparency**: Building displays that clearly communicate:\n   - Which Morpho markets the vault allocates to\n   - Collateral types users are exposed to\n   - Current utilization ratios\n   - Current allocation strategy and any pending changes\n\n## Rewards Considerations\n\nA 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.\n\nKey aspects to integrate:\n\n- **Rewards Discovery**: Identify available reward programs for vault depositors\n- **Rewards Tracking**: Display accruing and claimable rewards in real-time\n- **Claiming Process**: Implement claim functionality using Merkle-proof based distribution systems (URD and Merkl)\n- **Multi-Token Support**: Handle various reward tokens from different reward providers\n- **Program Awareness**: Display active campaigns and their respective parameters\n\nFor detailed implementation guidance, see the [Rewards integration guide](/build/rewards/get-started).\n\n## Assets Flow - Earn\n\nUnderstanding the complete flow of assets is crucial for proper integration:\n\n### 1. Deposit\n\n   - User deposits an asset (e.g., USDC, ETH) into a Morpho Vault\n   - User receives vault shares (ERC4626 tokens) representing their proportional ownership\n   - The vault allocates the deposited assets across:\n      - Morpho Markets V1 (for Vaults V1)\n      - Morpho Vaults V1 (for Vaults V2) based on the curator's strategy\n   - These markets are permissionless pools containing a loan token (what was deposited) and a collateral token\n\n### 2. Yield Generation\n\n   - Borrowers deposit collateral into Morpho Markets and borrow the loan token\n   - Borrowers pay interest on borrowed amounts\n   - This interest accrues to suppliers (the vault, in this case)\n   - The vault's share price increases as interest accumulates, representing yield for depositors\n\n### 3. Withdrawal Process\n   - Users can redeem their vault shares for the underlying asset at any time\n   - Vault V1 pulls liquidity directly from Morpho Markets V1 via its withdrawal queue\n   - Vault V2 pulls liquidity from underlying Morpho Vaults V1, which in turn pull from Morpho Markets V1\n   - Users receive their original deposit plus accrued yield (minus any performance or management fee)\n\n## Functional Integration Requirements\n\nFor a complete Earn integration, your system needs to implement:\n\n1. **Read Operations**:\n\n   - Query vault metadata (name, symbol, asset, curator, fees)\n   - Fetch current APY and historical performance\n   - Display current allocation across markets\n   - Show user-specific position data\n   - Present risk parameters of underlying markets\n\n2. **Write Operations**:\n\n   - Handle asset approvals\n   - Execute deposits & withdrawals\n   - Facilitate claiming any associated rewards\n\n3. **Monitoring Capabilities**:\n   - Track position changes\n   - Alert users to significant vault parameter changes\n   - Update yield information in real-time\n\n## Risk Considerations\n\nA complete Earn integration should help users understand:\n\n1. **Smart Contract Risk**: Exposure to both Morpho and Vault contracts\n2. **Market Risk**: Exposure to specific collateral types and their volatility\n3. **Curator Risk**: Dependence on curator's expertise and continued management\n4. **Liquidity Risk**: Potential for withdrawal delays during high utilization\n5. **Oracle Risk**: Vulnerability to incorrect price feeds affecting underlying markets\n\nBy 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."
  },
  "/build/earn/guides/base-onchainkit/": {
    "title": "Guide: Integrating One-Click Yield with OnchainKit",
    "url": "https://docs.morpho.org/build/earn/guides/base-onchainkit/",
    "section": "Build",
    "content": "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.\n\nWe will walk through the entire process, from initial setup to implementing both a plug-and-play component and a fully custom UI.\n\n**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.\n\n## Architecture Overview\n\nThe integration relies on two key components working in concert:\n\n1.  **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.\n2.  **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 `<Earn />` that abstract away the complexity of interacting with DeFi protocols.\n\nHere is a high-level view of the interaction flow:\n\n```\n┌───────────┐\n│ End User  │\n└───────────┘\n      │\n      │ Interacts with\n      ▼\n┌──────────────────┐\n│ Your Application │\n└──────────────────┘\n      │\n      │ Uses\n      ▼\n┌────────────────────┐\n│ OnchainKit         │\n│ <Earn /> Component │\n└────────────────────┘\n      │\n      │ 1. Connects Wallet\n      │ 2. Builds & Sponsors Transaction (via Paymaster)\n      ▼\n┌──────────────────┐\n│   Base Chain     │\n└──────────────────┘\n      │\n      │ Executes atomic deposit call\n      ▼\n┌──────────────────┐\n│ Morpho Vault     │\n│   (deposit)      │\n└──────────────────┘\n```\n\n## Part 1: Setup and Configuration\n\nThis guide assumes you are building a React application with TypeScript on the Base network.\n\n#### Step 1: Install Dependencies\nWe recommend starting with the official OnchainKit template, which sets up the entire environment for you.\n\n```bash\nnpm create onchain@latest\n```\n\nIf you are adding OnchainKit to an existing project, install the necessary packages:\n\n```bash\nnpm install @coinbase/onchainkit viem wagmi @tanstack/react-query\n```\n\n#### Step 2: Configure Paymaster for Gas Sponsorship\nTo sponsor your users' gas fees, you'll need a Paymaster service. OnchainKit is deeply integrated with the Coinbase Developer Platform (CDP).\n\n1.  **Create a CDP Account**: Sign up on the **[Coinbase Developer Platform](https://cdp.coinbase.com/)**.\n2.  **Create a Project**: Create a new project and get your `projectId`.\n3.  **Set up a Paymaster**: Navigate to the \"Paymaster\" section, create a new paymaster for the Base network, and copy the **Paymaster URL**.\n4.  **Fund Your Paymaster**: Add funds to your CDP account to cover the gas fees for your users.\n5.  **Allowlist Contracts (Important!)**: In your Paymaster policy settings, you **must** allowlist the contract functions the `<Earn />` component will call:\n    *   The **Morpho Vault** address: allow the `deposit` and `redeem` functions.\n    *   The **underlying token** (e.g., USDC, WETH) address: allow the `approve` function.\n\nNever hardcode API keys or Paymaster URLs. Use environment variables with a framework-specific prefix (e.g., `NEXT_PUBLIC_` or `VITE_`).\n\n#### Step 3: Define Constants\nFor 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)**.\n\n```typescript\n// constants.ts\nimport { base } from \"viem/chains\";\n\n// 1. Supported Network\nexport const SUPPORTED_NETWORK = base;\n\n// 2. Morpho Vault Address on Base (Example: USDC Vault)\nexport const MORPHO_USDC_VAULT_ADDRESS = \"0x425314C7836371752a7b8eF41B32997f888A011f\";\n```\n\n#### Step 4: Configure the OnchainKit Provider\nWrap your application's root with the `OnchainKitProvider`. This makes all of OnchainKit's hooks and components available throughout your app.\n\n```tsx\n// In your main App.tsx or a layout component\nimport { OnchainKitProvider } from '@coinbase/onchainkit';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { base } from 'viem/chains';\nimport { WagmiProvider, createConfig, http } from 'wagmi';\n\nconst queryClient = new QueryClient();\n\n// Configure wagmi with the standard Base RPC\nconst wagmiConfig = createConfig({\n  chains: [base],\n  transports: {\n    [base.id]: http(),\n  },\n});\n\nconst App = ({ children }: { children: React.ReactNode }) => {\n  return (\n    <WagmiProvider config={wagmiConfig}>\n      <QueryClientProvider client={queryClient}>\n        <OnchainKitProvider\n          chain={base}\n          // The paymaster URL is configured here to apply globally\n          paymaster={process.env.NEXT_PUBLIC_PAYMASTER_URL}\n          // The projectId is used by OnchainKit for various services\n          projectId={process.env.NEXT_PUBLIC_CDP_PROJECT_ID} \n        >\n          {children}\n        </OnchainKitProvider>\n      </QueryClientProvider>\n    </WagmiProvider>\n  );\n};\n```\n\n## Part 3: Production Considerations\n\n### Security Best Practices\n\n*   **Key Management**: Never expose private keys or Paymaster URLs in client-side code. Use secure environment variables.\n*   **Input Validation**: Always validate and sanitize user inputs, especially amounts, to prevent errors and unexpected behavior.\n*   **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.\n\n### Common Issues & Troubleshooting\n\n| Issue                             | Solution                                                                                                                              |\n| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| **Transaction fails silently**      | Check the browser console for detailed error messages. Common causes include an incorrect `vaultAddress` or network mismatch.          |\n| **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. |\n| **Component not rendering data**  | Ensure that `OnchainKitProvider` correctly wraps your entire application or the component tree where `<Earn />` is used.               |\n| **\"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. |\n\n## Key Resources & Next Steps\n\nYou now have the building blocks to integrate a powerful, user-friendly yield product. To learn more, explore these resources:\n\n    OnchainKit Earn Docs\n    Dive deeper into the `<Earn />` component, its subcomponents, and the `useEarnContext` hook.\n    \n      Read Docs →\n  \n\n  OnchainKit Quickstart\n    Review the setup process and explore other powerful components for identity, transactions, and more.\n    \n      Start Building →\n    \n\n  Morpho Earn Concepts\n    Understand the mechanics behind Morpho Vaults, including how yield is generated and risks are managed.\n    \n      Learn More →\n    \n\n  Community Support\n    Join the Base Discord to ask questions and get help from the community and the OnchainKit team.\n    \n      Join Discord →"
  },
  "/build/earn/resources/all/": {
    "title": "Earn: Developer Resources",
    "url": "https://docs.morpho.org/build/earn/resources/all/",
    "section": "Build",
    "content": "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).\n\n## Onchain Data & Contracts\n\nThese resources are for interacting directly with the blockchain.\n\n-   **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).\n-   **Contract Specifications**: For detailed function signatures, events, and errors, refer to the canonical [Morpho Vaults Contract Specs](/get-started/resources/contracts/morpho-vaults/).\n-   **GitHub Repositories**:\n    -   [`vault-v2`](https://github.com/morpho-org/vault-v2): The V2 version of Morpho Vaults.\n    -   [`metamorpho-V1.1`](https://github.com/morpho-org/metamorpho-v1.1): The latest Vault V1 implementation.\n    -   [`metamorpho`](https://github.com/morpho-org/metamorpho): The original Vault V1 implementation.\n    \n\n## Offchain Data & Tools\n\nThese tools provide easier access to onchain data for frontends, backends, and analytics.\n\n-   **Morpho API (Recommended)**: The simplest way to fetch comprehensive data about vaults, their states, APYs, and user positions.\n    -   **API Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql)\n    -   **Tutorial**: [Using the API for Vaults](/build/earn/tutorials/get-data)\n-   **Morpho Subgraphs**: For developers who prefer querying via The Graph protocol.\n    -   **Tutorial**: [Using Subgraphs for Vaults](/tools/offchain/subgraphs/#morpho-vault-examples)\n-   **SDKs**: A suite of TypeScript libraries to accelerate your development.\n    -   **`@morpho-org/blue-sdk`**: Core, framework-agnostic classes for entities like Vaults and Markets.\n    -   **`@morpho-org/blue-sdk-viem`**: Adds Viem-based fetchers to the core SDK classes.\n    -   **`@morpho-org/simulation-sdk`**: Simulates user interactions to predict outcomes before sending a transaction.\n    -   **Learn more**: [Introduction to Morpho SDKs](/tools/offchain/sdks/get-started/)\n\n## Code & Examples\n\n-   **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.\n-   **Solidity Snippets**: The [`morpho-blue-snippets`](https://github.com/morpho-org/morpho-blue-snippets) repository contains simple, educational Solidity contracts for common vault interactions."
  },
  "/build/earn/tutorials/assets-flow/": {
    "title": "Depositing & Withdrawing from Vaults",
    "url": "https://docs.morpho.org/build/earn/tutorials/assets-flow/",
    "section": "Build",
    "content": "**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, with one exception noted below.\n\n**Morpho Vault V2** has a non-conventional behavior on max functions (`maxDeposit`, `maxMint`, `maxWithdraw`, `maxRedeem`): they always return zero. See the [Morpho Vaults V2 reference](/get-started/resources/contracts/morpho-vaults-v2#maxdeposit) for details.\n\nFor background on ERC4626 mechanics and vault architecture, see [Vaults & ERC4626 Mechanics](/build/earn/concepts/vault-mechanics).\n\nThis 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.\n\n**Integration methods:**\n1. **Direct Smart Contract Integration** using Solidity\n2. **Offchain Integration** using TypeScript and Viem  \n\n## Key Concepts: Assets vs. Shares\n\nWhen 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.\n\n| Approach        | Deposit Function | Withdrawal Function | Description                                                                                             |\n| --------------- | ---------------- | ------------------- | ------------------------------------------------------------------------------------------------------- |\n| **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. |\n| **Shares-First**| `mint(shares, ...)`     | `redeem(shares, ...)`   | You specify the exact number of vault shares you want to mint or redeem.                                |\n\n**Best Practice:**\n- For **deposits**, `deposit()` is the most common and intuitive function.\n- 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.\"\n- For **partial withdrawals** where a user needs a specific amount of the underlying asset, `withdraw()` is appropriate.\n\n## Prerequisites\n\nBefore you begin, you will need:\n- 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).\n- An account with a balance of the vault's underlying asset (e.g., WETH for a WETH vault).\n\n## Vault Safety: Inflation Attack Protection\n\nBefore integrating with any ERC4626 vault, verify that adequate inflation attack protection is in place.\n\nAll 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.\n\n**Verification Check:**\n```ts\n// Check that the vault has adequate protection\nconst deadAddress = \"0x000000000000000000000000000000000000dEaD\";\nconst deadShares = await vault.balanceOf(deadAddress);\n\nif (deadShares < 1_000_000_000n) {\n  throw new Error(\"Vault lacks required inflation protection\");\n}\n```\n\n**Key Points:**\n- The dead deposit must be at least **1e9 shares** for assets with more than 9 decimals, or **1e12 shares** otherwise (approximately $1 equivalent).\n- This check should be performed during vault integration/whitelisting, not on every transaction\n- Properly protected vaults make inflation attacks economically unfeasible\n- Both Morpho Vault V1 and V2 should have this protection established by curators\n\nFor a detailed explanation of how this protection works, see [Vault Mechanics: Inflation Attack Protection](/build/earn/concepts/vault-mechanics#inflation-attack-protection).\n\n## EIP-2612 Permit Support\n\nBoth 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.\n\n### Vault Shares Permit (V1 & V2)\n\nAll 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.\n\n| Version | Implementation |\n|---------|----------------|\n| V1 / V1.1 | Inherits OpenZeppelin's `ERC20Permit` |\n| V2 | Native EIP-2612 implementation |\n\n**Use case:** Approve a third party (e.g., a router contract) to transfer your vault shares using an off-chain signature.\n\nThis permit is for **vault shares**, not for depositing assets. It does not enable gasless deposits on its own.\n\n### Gasless Deposits via the Underlying Asset's Permit (V1 & V2)\n\nIf 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.\n\nNeither 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:\n- A traditional `approve()` transaction\n- An EIP-2612 `permit` (if the asset supports it) — USDC, DAI, etc.\n- Permit2 (for assets without native permit) — WETH, WBTC, etc.\n\n### Example: Gasless Deposit with EIP-2612 Permit (TypeScript)\n\nThe following example demonstrates a deposit into a Morpho Vault using the underlying asset's EIP-2612 permit. The flow is:\n1. Sign an EIP-712 permit message off-chain (gasless)\n2. Call `asset.permit()` on-chain to set the approval\n3. Call `vault.deposit()` to deposit the approved tokens\n\nSteps 2 and 3 can be combined into a single atomic transaction using a multicall contract.\n\n```typescript\nimport {\n  createPublicClient,\n  createWalletClient,\n  http,\n  type Address,\n  type Hex,\n  parseUnits,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\n// Example vault using USDC as underlying (USDC supports EIP-2612 permit)\nconst VAULT_ADDRESS = \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\" as Address;\nconst USDC_ADDRESS = \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\" as Address;\n\nconst erc2612Abi = [\n  {\n    name: \"permit\",\n    type: \"function\",\n    inputs: [\n      { name: \"owner\", type: \"address\" },\n      { name: \"spender\", type: \"address\" },\n      { name: \"value\", type: \"uint256\" },\n      { name: \"deadline\", type: \"uint256\" },\n      { name: \"v\", type: \"uint8\" },\n      { name: \"r\", type: \"bytes32\" },\n      { name: \"s\", type: \"bytes32\" },\n    ],\n    outputs: [],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    name: \"nonces\",\n    type: \"function\",\n    inputs: [{ name: \"owner\", type: \"address\" }],\n    outputs: [{ type: \"uint256\" }],\n    stateMutability: \"view\",\n  },\n] as const;\n\nconst vaultAbi = [\n  {\n    name: \"deposit\",\n    type: \"function\",\n    inputs: [\n      { name: \"assets\", type: \"uint256\" },\n      { name: \"receiver\", type: \"address\" },\n    ],\n    outputs: [{ name: \"shares\", type: \"uint256\" }],\n    stateMutability: \"nonpayable\",\n  },\n] as const;\n\nfunction parseSignature(signature: Hex): { v: number; r: Hex; s: Hex } {\n  const r = `0x${signature.slice(2, 66)}` as Hex;\n  const s = `0x${signature.slice(66, 130)}` as Hex;\n  const v = parseInt(signature.slice(130, 132), 16);\n  return { v, r, s };\n}\n\nasync function depositWithEIP2612Permit(\n  publicClient: ReturnType<typeof createPublicClient>,\n  walletClient: ReturnType<typeof createWalletClient>,\n  vaultAddress: Address,\n  assetAddress: Address,\n  depositAmount: bigint,\n  assetDomainConfig: { name: string; version: string },\n) {\n  const account = walletClient.account!;\n  const chainId = await publicClient.getChainId();\n\n  // 1. Get current nonce for the permit\n  const nonce = await publicClient.readContract({\n    address: assetAddress,\n    abi: erc2612Abi,\n    functionName: \"nonces\",\n    args: [account.address],\n  });\n\n  // 2. Set deadline (1 hour from now)\n  const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600);\n\n  // 3. Create EIP-712 typed data for the permit\n  const typedData = {\n    domain: {\n      name: assetDomainConfig.name,\n      version: assetDomainConfig.version,\n      chainId,\n      verifyingContract: assetAddress,\n    },\n    types: {\n      Permit: [\n        { name: \"owner\", type: \"address\" },\n        { name: \"spender\", type: \"address\" },\n        { name: \"value\", type: \"uint256\" },\n        { name: \"nonce\", type: \"uint256\" },\n        { name: \"deadline\", type: \"uint256\" },\n      ],\n    },\n    primaryType: \"Permit\" as const,\n    message: {\n      owner: account.address,\n      spender: vaultAddress,\n      value: depositAmount,\n      nonce,\n      deadline,\n    },\n  };\n\n  // 4. Sign the permit (GASLESS — off-chain signature)\n  const signature = await walletClient.signTypedData(typedData);\n  const { v, r, s } = parseSignature(signature);\n\n  // 5. Execute permit on-chain (sets approval)\n  const permitHash = await walletClient.writeContract({\n    address: assetAddress,\n    abi: erc2612Abi,\n    functionName: \"permit\",\n    args: [account.address, vaultAddress, depositAmount, deadline, v, r, s],\n  });\n  await publicClient.waitForTransactionReceipt({ hash: permitHash });\n\n  // 6. Deposit into vault\n  const depositHash = await walletClient.writeContract({\n    address: vaultAddress,\n    abi: vaultAbi,\n    functionName: \"deposit\",\n    args: [depositAmount, account.address],\n  });\n  await publicClient.waitForTransactionReceipt({ hash: depositHash });\n\n  return { permitHash, depositHash };\n}\n\n// Example: Deposit 100 USDC using permit\nasync function main() {\n  const publicClient = createPublicClient({\n    chain: mainnet,\n    transport: http(),\n  });\n\n  const account = privateKeyToAccount(\"0x...\" as `0x${string}`);\n  const walletClient = createWalletClient({\n    chain: mainnet,\n    transport: http(),\n    account,\n  });\n\n  const depositAmount = parseUnits(\"100\", 6); // 100 USDC\n\n  await depositWithEIP2612Permit(\n    publicClient,\n    walletClient,\n    VAULT_ADDRESS,\n    USDC_ADDRESS,\n    depositAmount,\n    { name: \"USD Coin\", version: \"2\" }, // USDC domain config\n  );\n}\n```\n\nThis code has not been audited and is for educational purposes only. Always verify the token's domain separator configuration against its contract implementation.\n\n---\n\n## Method 1: Smart Contract Integration (Solidity)\n\nThis method is for developers building smart contracts that need to deposit into or withdraw from a Morpho Vault onchain.\n\nThe 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.\n\nSDK examples for Vault V2 will be added later.\n\n### Step 1: Approve the Vault\n\nBefore your contract can deposit tokens into a vault, it must first approve the vault contract to spend its tokens.\n\n```solidity\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Within your contract\naddress vaultAddress = 0x...; // Address of the Morpho Vault\naddress assetAddress = 0x...; // Address of the underlying asset (e.g., WETH)\nuint256 depositAmount = 1 ether;\n\n// Approve the vault to spend the asset\nIERC20(assetAddress).approve(vaultAddress, depositAmount);\n```\n\nIf 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.\n\n### Step 2: Deposit or Mint Assets\n\nChoose the function that best fits your needs.\n\n```solidity [deposit (V2)]\nimport { IVaultV2 } from \"@morpho-org/vault-v2/src/interfaces/IVaultV2.sol\";\n\n// Asset-first approach: Deposit a specific amount of the underlying token.\n// The contract will calculate and mint the corresponding number of shares.\nuint256 sharesMinted = IVaultV2(vaultAddress).deposit(depositAmount, address(this));\n```\n```solidity [mint (V2)]\nimport { IVaultV2 } from \"@morpho-org/vault-v2/src/interfaces/IVaultV2.sol\";\n\n// Shares-first approach: Mint a specific number of vault shares.\n// The contract will calculate and pull the required amount of the underlying asset.\nuint256 sharesToMint = 1 ether;\nuint256 assetsNeeded = IVaultV2(vaultAddress).mint(sharesToMint, address(this));\n```\n```solidity [deposit (V1)]\nimport { IMetaMorpho } from \"@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol\";\n\n// Asset-first approach: Deposit a specific amount of the underlying token.\n// The contract will calculate and mint the corresponding number of shares.\nuint256 sharesMinted = IMetaMorpho(vaultAddress).deposit(depositAmount, address(this));\n```\n```solidity [mint (V1)]\nimport { IMetaMorpho } from \"@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol\";\n\n// Shares-first approach: Mint a specific number of vault shares.\n// The contract will calculate and pull the required amount of the underlying asset.\nuint256 sharesToMint = 1 ether;\nuint256 assetsNeeded = IMetaMorpho(vaultAddress).mint(sharesToMint, address(this));\n```\n\n### Step 3: Withdraw or Redeem Assets\n\nSimilarly, you can withdraw by specifying either the asset amount or the share amount.\n\n```solidity [withdraw (V2)]\nimport { IVaultV2 } from \"@morpho-org/vault-v2/src/interfaces/IVaultV2.sol\";\n\n// Asset-first approach: Withdraw a specific amount of the underlying token.\nuint256 assetsToWithdraw = 1 ether;\nuint256 sharesBurned = IVaultV2(vaultAddress).withdraw(assetsToWithdraw, address(this), address(this));\n```\n```solidity [redeem (V2)]\nimport { IVaultV2 } from \"@morpho-org/vault-v2/src/interfaces/IVaultV2.sol\";\n\n// Shares-first approach (Recommended for full withdrawal): Redeem a specific number of shares.\nuint256 sharesToRedeem = IVaultV2(vaultAddress).balanceOf(address(this));\nuint256 assetsReceived = IVaultV2(vaultAddress).redeem(sharesToRedeem, address(this), address(this));\n```\n```solidity [withdraw (V1)]\nimport { IMetaMorpho } from \"@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol\";\n\n// Asset-first approach: Withdraw a specific amount of the underlying token.\nuint256 assetsToWithdraw = 1 ether;\nuint256 sharesBurned = IMetaMorpho(vaultAddress).withdraw(assetsToWithdraw, address(this), address(this));\n```\n```solidity [redeem (V1)]\nimport { IMetaMorpho } from \"@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol\";\n\n// Shares-first approach (Recommended for full withdrawal): Redeem a specific number of shares.\nuint256 sharesToRedeem = IMetaMorpho(vaultAddress).balanceOf(address(this));\nuint256 assetsReceived = IMetaMorpho(vaultAddress).redeem(sharesToRedeem, address(this), address(this));\n```\n\n### Full Example: Solidity Snippets\n\nHere are some example contracts demonstrating these interactions for both vault versions.\n\nThe 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.\n\n```solidity [Morpho Vault V2]\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport { IVaultV2 } from \"@morpho-org/vault-v2/src/interfaces/IVaultV2.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract VaultV2Interaction {\n    IVaultV2 public immutable vault;\n    IERC20 public immutable asset;\n\n    constructor(address _vault) {\n        vault = IVaultV2(_vault);\n        asset = IERC20(vault.asset());\n    }\n\n    /// @notice Deposits a specified amount of assets into the vault.\n    /// @param amount The amount of underlying assets to deposit.\n    function deposit(uint256 amount) external {\n        asset.approve(address(vault), amount);\n        vault.deposit(amount, msg.sender);\n    }\n\n    /// @notice Withdraws all assets from the vault for the caller.\n    function withdrawAll() external {\n        uint256 shares = vault.balanceOf(msg.sender);\n        if (shares > 0) {\n            vault.redeem(shares, msg.sender, msg.sender);\n        }\n    }\n}\n```\n```solidity [Morpho Vault V1]\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport { IMetaMorpho } from \"@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract VaultV1Interaction {\n    IMetaMorpho public immutable vault;\n    IERC20 public immutable asset;\n\n    constructor(address _vault) {\n        vault = IMetaMorpho(_vault);\n        asset = IERC20(vault.asset());\n    }\n\n    /// @notice Deposits a specified amount of assets into the vault.\n    /// @param amount The amount of underlying assets to deposit.\n    function deposit(uint256 amount) external {\n        asset.approve(address(vault), amount);\n        vault.deposit(amount, msg.sender);\n    }\n\n    /// @notice Withdraws all assets from the vault for the caller.\n    function withdrawAll() external {\n        uint256 shares = vault.balanceOf(msg.sender);\n        if (shares > 0) {\n            vault.redeem(shares, msg.sender, msg.sender);\n        }\n    }\n}\n```\n\n## Method 2: Offchain Integration (TypeScript SDK)\n\nThis 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**.\n\nCurrently, the released version of SDKs only support **Morpho Vaults V1**. The ones for **Morpho Vaults V2** are coming out soon.\n\n### Step 1: Setup\n\nFirst, install the necessary packages and set up your Viem client.\n\n```bash\nnpm install viem @morpho-org/blue-sdk @morpho-org/blue-sdk-viem @morpho-org/morpho-ts\n```\n\n```typescript\nimport { createWalletClient, http, publicActions, parseUnits } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { mainnet } from \"viem/chains\";\nimport { metaMorphoAbi } from \"@morpho-org/blue-sdk-viem\";\n\nconst vaultAddress = \"0x...\"; // The vault address\nconst assetAddress = \"0x...\"; // The vault's underlying asset address\nconst account = privateKeyToAccount(\"0x...\"); // The user's account\n\nconst client = createWalletClient({\n  account,\n  chain: mainnet,\n  transport: http(process.env.RPC_URL_MAINNET),\n}).extend(publicActions);\n```\n\n### Step 2: Approve the Vault\n\nBefore depositing, check the current allowance and approve if necessary.\n\n```typescript\n// 1. Check current allowance\nconst allowance = await client.readContract({\n  address: assetAddress,\n  abi: IERC20_ABI, // A standard ERC20 ABI\n  functionName: \"allowance\",\n  args: [account.address, vaultAddress],\n});\n\nconst amountToDeposit = parseUnits(\"1.0\", 18); // Example: 1 WETH\n\n// 2. Approve if allowance is insufficient\nif (allowance < amountToDeposit) {\n  const { request } = await client.simulateContract({\n    address: assetAddress,\n    abi: IERC20_ABI,\n    functionName: \"approve\",\n    args: [vaultAddress, amountToDeposit],\n  });\n  await client.writeContract(request);\n}\n```\n\n### Step 3: Deposit Assets\n\nCall the `deposit` function to add funds to the vault.\n\n```typescript\nconst { request: depositRequest } = await client.simulateContract({\n  address: vaultAddress,\n  abi: metaMorphoAbi,\n  functionName: \"deposit\",\n  args: [amountToDeposit, account.address], // (assets, receiver)\n});\n\nconst depositTxHash = await client.writeContract(depositRequest);\nconsole.log(\"Deposit successful:\", depositTxHash);\n```\n\n### Step 4: Withdraw Assets\n\nTo withdraw the full balance, first fetch the user's share balance, then call `redeem`.\n\n```typescript\n// 1. Get the user's share balance\nconst userShares = await client.readContract({\n  address: vaultAddress,\n  abi: metaMorphoAbi,\n  functionName: \"balanceOf\",\n  args: [account.address],\n});\n\n// 2. Redeem the shares for the underlying asset\nif (userShares > 0n) {\n  const { request: redeemRequest } = await client.simulateContract({\n    address: vaultAddress,\n    abi: metaMorphoAbi,\n    functionName: \"redeem\",\n    args: [userShares, account.address, account.address], // (shares, receiver, owner)\n  });\n  const redeemTxHash = await client.writeContract(redeemRequest);\n  console.log(\"Withdrawal successful:\", redeemTxHash);\n}\n```\n\nFor more detailed examples and advanced usage, including handling different wallet types and simulation states, explore the [Morpho SDKs documentation](/tools/offchain/sdks/get-started/).\n\n## Additional Considerations\n\n### Slippage for User Experience\n\nWhile not a security requirement when proper dead deposit protection is in place, implementing slippage tolerance can improve user experience in your application.\n\nHere's an educational example of how to implement a basic slippage check (1% tolerance):\n\n```solidity [Vault V2 with slippage check]\n// Educational example: Deposit with 1% slippage protection\nimport { IVaultV2 } from \"@morpho-org/vault-v2/src/interfaces/IVaultV2.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract VaultV2DepositWithSlippage {\n    function depositWithSlippage(\n        address vaultAddress,\n        uint256 depositAmount\n    ) external returns (uint256) {\n        IVaultV2 vault = IVaultV2(vaultAddress);\n        IERC20 asset = IERC20(vault.asset());\n\n        // 1. Preview expected shares\n        uint256 expectedShares = vault.previewDeposit(depositAmount);\n\n        // 2. Calculate minimum acceptable shares (1% slippage = 99% of expected)\n        uint256 minShares = expectedShares * 99 / 100;\n\n        // 3. Approve and execute deposit\n        asset.approve(vaultAddress, depositAmount);\n        uint256 sharesMinted = vault.deposit(depositAmount, msg.sender);\n\n        // 4. Verify slippage tolerance\n        require(sharesMinted >= minShares, \"Slippage tolerance exceeded\");\n\n        return sharesMinted;\n    }\n}\n```\n```solidity [Vault V1 with slippage check]\n// Educational example: Deposit with 1% slippage protection\nimport { IMetaMorpho } from \"@morpho-org/metamorpho/src/interfaces/IMetaMorpho.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract VaultV1DepositWithSlippage {\n    function depositWithSlippage(\n        address vaultAddress,\n        uint256 depositAmount\n    ) external returns (uint256) {\n        IMetaMorpho vault = IMetaMorpho(vaultAddress);\n        IERC20 asset = IERC20(vault.asset());\n\n        // 1. Preview expected shares\n        uint256 expectedShares = vault.previewDeposit(depositAmount);\n\n        // 2. Calculate minimum acceptable shares (1% slippage = 99% of expected)\n        uint256 minShares = expectedShares * 99 / 100;\n\n        // 3. Approve and execute deposit\n        asset.approve(vaultAddress, depositAmount);\n        uint256 sharesMinted = vault.deposit(depositAmount, msg.sender);\n\n        // 4. Verify slippage tolerance\n        require(sharesMinted >= minShares, \"Slippage tolerance exceeded\");\n\n        return sharesMinted;\n    }\n}\n```\n\nThese 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.\n\nSee also [Vault Mechanics: Slippage Considerations](/build/earn/concepts/vault-mechanics#additional-considerations-slippage) for more context."
  },
  "/build/earn/tutorials/get-data/": {
    "title": "Get Data",
    "url": "https://docs.morpho.org/build/earn/tutorials/get-data/",
    "section": "Build",
    "content": "## Before Starting\n\nIn this tutorial, you might see different ways to fetch data for Morpho Vaults:\n\n- **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.\n- **Typescript**: Using Typescript snippet. For Developers expecting to perform offchain computation.\n- **Smart Contract**: Fetching data directly onchain. This is best for real-time or trustless data.\n- **SDK**: [Examples Incoming] Using the Morpho SDKs for pre-built abstractions and faster development.\n\nAPI Endpoint: [api.morpho.org/graphql](https://api.morpho.org/graphql)\n\nReview 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.\n\nFor 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.\n\n## Discovery and Listing\n\n### Vaults List\n\n#### Morpho Vaults V2\n\n```graphql [API]\nquery {\n  vaultV2s(first: 1000, where: { chainId_in: [1, 8453] }) {\n    items {\n      address\n      symbol\n      name\n      listed\n      asset {\n        id\n        address\n        decimals\n      }\n      chain {\n        id\n        network\n      }\n    }\n  }\n} \n```\n\n{\" \"}\n\n```typescript\nimport \"dotenv/config\";\nimport { createPublicClient, http, PublicClient, parseAbiItem } from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\nexport async function createMainnetClient(): Promise<PublicClient> {\n  const client = createPublicClient({\n    chain: mainnet,\n    transport: http(process.env.RPC_URL_MAINNET!, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n  \n  return client;\n}\n\n// Morpho Vault V2 Factory contract address\nconst MORPHO_VAULT_V2_FACTORY_ADDRESS = \"0xA1D94F746dEfa1928926b84fB2596c06926C0405\";\n\n// Block range to search for vault creations\nconst START_BLOCK = 23716940n;\nconst END_BLOCK = 23717000n;\n\n// CreateVaultV2 event ABI\nconst CREATE_VAULT_V2_EVENT = parseAbiItem(\n  \"event CreateVaultV2(address indexed owner, address indexed asset, bytes32 salt, address indexed newVaultV2)\"\n);\n\ninterface VaultV2CreationEvent {\n  newVaultV2: string;\n  owner: string;\n  asset: string;\n  salt: string;\n  blockNumber: bigint;\n  transactionHash: string;\n}\n\nexport async function fetchNewVaultV2Creations(\n  client: PublicClient,\n  startBlock: bigint = START_BLOCK,\n  endBlock: bigint = END_BLOCK\n): Promise<VaultV2CreationEvent[]> {\n  console.log(`Fetching Vault V2 creations from block ${startBlock} to ${endBlock}...`);\n\n  // Get logs for CreateVaultV2 events\n  const logs = await client.getLogs({\n    address: MORPHO_VAULT_V2_FACTORY_ADDRESS,\n    event: CREATE_VAULT_V2_EVENT,\n    fromBlock: startBlock,\n    toBlock: endBlock,\n  });\n\n  console.log(`Found ${logs.length} Vault V2 creation(s)`);\n\n  // Parse and format the logs\n  const vaultCreations: VaultV2CreationEvent[] = logs.map((log) => ({\n    newVaultV2: log.args.newVaultV2!,\n    owner: log.args.owner!,\n    asset: log.args.asset!,\n    salt: log.args.salt!,\n    blockNumber: log.blockNumber!,\n    transactionHash: log.transactionHash!,\n  }));\n\n  return vaultCreations;\n}\n\nexport function displayVaultV2Creations(vaultCreations: VaultV2CreationEvent[]): void {\n  if (vaultCreations.length === 0) {\n    console.log(\"No new Vault V2s were created in the specified block range.\");\n    return;\n  }\n\n  console.log(\"\\n=== New MetaMorpho Vault V2s Created ===\");\n  vaultCreations.forEach((vault, index) => {\n    console.log(`\\n${index + 1}. Vault V2 Address: ${vault.newVaultV2}`);\n    console.log(`   Owner: ${vault.owner}`);\n    console.log(`   Asset: ${vault.asset}`);\n    console.log(`   Salt: ${vault.salt}`);\n    console.log(`   Block: ${vault.blockNumber}`);\n    console.log(`   Transaction: ${vault.transactionHash}`);\n  });\n}\n\nexport async function main(): Promise<void> {\n  try {\n    const client = await createMainnetClient();\n\n    // Fetch Vault V2 creations in the specified block range\n    const vaultCreations = await fetchNewVaultV2Creations(client, START_BLOCK, END_BLOCK);\n\n    // Display the results\n    displayVaultV2Creations(vaultCreations);\n\n  } catch (error) {\n    console.error(\"Error fetching Vault V2 creations:\", error);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```json\n{\n  \"message\": \"Fetching Vault V2 creations from block 23716940 to 23717000...\",\n  \"found\": \"Found 1 Vault V2 creation(s)\",\n  \"vaults\": [\n    {\n      \"address\": \"0x5E5b30c5fD07da26d1e515dfEDb1D37C93417652\",\n      \"owner\": \"0x46057881E0B9d190920FB823F840B837f65745d5\",\n      \"asset\": \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n      \"salt\": \"0x5dbd6b3d5444d58eb3b873a76f4a26158f4a960b67d87125ffcd305053e16a3a\",\n      \"blockNumber\": \"23716959\",\n      \"transactionHash\": \"0x73f2c14195c38ca887e44fed4e2bb9619a858ddea7337258d748a3079ef417f0\"\n    }\n  ]\n}\n```\n\nThis example demonstrates how to:\n- 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/).\n- Filter events within a specific block range\n- Extract all vault creation details from the event logs\n- Parse and format the results for easy consumption\n\n{\" \"}\n\nOne can listen to all `CreateVaultV2` events emitted from the `MorphoVaultV2Factory` contract. The contracts addresses are [here](/get-started/resources/addresses/).\n\n```solidity\n/// @notice Emitted when a new Morpho Vault V2 is created.\n/// @param owner The initial owner of the vault.\n/// @param asset The address of the underlying asset.\n/// @param salt The salt used for the vault's CREATE2 address.\n/// @param newVaultV2 The address of the newly created Vault V2.\nevent CreateVaultV2(\n    address indexed owner,\n    address indexed asset,\n    bytes32 salt,\n    address indexed newVaultV2\n);\n```\n\n#### Morpho Vaults V1\n\n```graphql [API]\nquery {\n  vaults(first: 1000, where: { chainId_in: [1, 8453] }) {\n    items {\n      address\n      symbol\n      name\n      listed\n      asset {\n        id\n        address\n        decimals\n      }\n      chain {\n        id\n        network\n      }\n    }\n  }\n} \n```\n\n{\" \"}\n\n```typescript\nimport \"dotenv/config\";\nimport { createPublicClient, http, PublicClient, parseAbiItem } from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\nexport async function createMainnetClient(): Promise<PublicClient> {\n  const client = createPublicClient({\n    chain: mainnet,\n    transport: http(process.env.RPC_URL_MAINNET!, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n  \n  return client;\n}\n\n// MetaMorpho Factory contract address\nconst MORPHO_VAULT_V1_FACTORY_ADDRESS = \"0x1897A8997241C1cD4bD0698647e4EB7213535c24\";\n\n// Block range to search for vault creations\nconst START_BLOCK = 22880720n;\nconst END_BLOCK = 22880740n;\n\n// CreateMetaMorpho event ABI\nconst CREATE_METAMORPHO_EVENT = parseAbiItem(\n  \"event CreateMetaMorpho(address indexed metaMorpho, address indexed caller, address initialOwner, uint256 initialTimelock, address indexed asset, string name, string symbol, bytes32 salt)\"\n);\n\ninterface VaultCreationEvent {\n  metaMorpho: string;\n  caller: string;\n  initialOwner: string;\n  initialTimelock: bigint;\n  asset: string;\n  name: string;\n  symbol: string;\n  salt: string;\n  blockNumber: bigint;\n  transactionHash: string;\n}\n\nexport async function fetchNewVaultCreations(\n  client: PublicClient,\n  startBlock: bigint = START_BLOCK,\n  endBlock: bigint = END_BLOCK\n): Promise<VaultCreationEvent[]> {\n  console.log(`Fetching vault creations from block ${startBlock} to ${endBlock}...`);\n  \n  // Get logs for CreateMetaMorpho events\n  const logs = await client.getLogs({\n    address: MORPHO_VAULT_V1_FACTORY_ADDRESS,\n    event: CREATE_METAMORPHO_EVENT,\n    fromBlock: startBlock,\n    toBlock: endBlock,\n  });\n\n  console.log(`Found ${logs.length} vault creation(s)`);\n\n  // Parse and format the logs\n  const vaultCreations: VaultCreationEvent[] = logs.map((log) => ({\n    metaMorpho: log.args.metaMorpho!,\n    caller: log.args.caller!,\n    initialOwner: log.args.initialOwner!,\n    initialTimelock: log.args.initialTimelock!,\n    asset: log.args.asset!,\n    name: log.args.name!,\n    symbol: log.args.symbol!,\n    salt: log.args.salt!,\n    blockNumber: log.blockNumber!,\n    transactionHash: log.transactionHash!,\n  }));\n\n  return vaultCreations;\n}\n\nexport function displayVaultCreations(vaultCreations: VaultCreationEvent[]): void {\n  if (vaultCreations.length === 0) {\n    console.log(\"No new vaults were created in the specified block range.\");\n    return;\n  }\n\n  console.log(\"\\n=== New Morpho Vaults V1 Created ===\");\n  vaultCreations.forEach((vault, index) => {\n    console.log(`\\n${index + 1}. Vault: ${vault.name} (${vault.symbol})`);\n    console.log(`   Address: ${vault.metaMorpho}`);\n    console.log(`   Asset: ${vault.asset}`);\n    console.log(`   Caller: ${vault.caller}`);\n    console.log(`   Initial Owner: ${vault.initialOwner}`);\n    console.log(`   Initial Timelock: ${vault.initialTimelock}`);\n    console.log(`   Salt: ${vault.salt}`);\n    console.log(`   Block: ${vault.blockNumber}`);\n    console.log(`   Transaction: ${vault.transactionHash}`);\n  });\n}\n\nexport async function main(): Promise<void> {\n  try {\n    const client = await createMainnetClient();\n    \n    // Fetch vault creations in the specified block range\n    const vaultCreations = await fetchNewVaultCreations(client, START_BLOCK, END_BLOCK);\n    \n    // Display the results\n    displayVaultCreations(vaultCreations);\n    \n  } catch (error) {\n    console.error(\"Error fetching vault creations:\", error);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```json\n{\n  \"message\": \"Fetching vault creations from block 22880720 to 22880740...\",\n  \"found\": \"1 vault creation(s)\",\n  \"vaults\": [\n    {\n      \"name\": \"Yearn Degen USDC\",\n      \"symbol\": \"yDG-USDC\",\n      \"address\": \"0xdC2Dd5189F70Fe2832D9caf7b17d27AA3D79dbE1\",\n      \"asset\": \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n      \"caller\": \"0xFc5F89d29CCaa86e5410a7ad9D9d280d4455C12B\",\n      \"initialOwner\": \"0xFc5F89d29CCaa86e5410a7ad9D9d280d4455C12B\",\n      \"initialTimelock\": \"0\",\n      \"salt\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n      \"blockNumber\": \"22880731\",\n      \"transactionHash\": \"0xa6c2906efec1a0f413038076a4f05f41b3d23e49d1af4543e54c1c0b69def6ba\"\n    }\n  ]\n}\n```\n\nThis example demonstrates how to:\n- Listen to `CreateMetaMorpho` events from the Morpho Vault V1 Factory contract on Ethereum (`0x1897A8997241C1cD4bD0698647e4EB7213535c24`). All addresses are [here](/get-started/resources/addresses/).\n- Filter events within a specific block range\n- Extract all vault creation details from the event logs\n- Parse and format the results for easy consumption\n\n{\" \"}\n\nOne can listen to all `CreateMetaMorpho` events emitted from the Morpho Vault V1 Factory contracts. The contracts addresses are [here](/get-started/resources/addresses/).\n\n```solidity\n/// @notice Emitted when a new MetaMorphoV1_1 vault is created.\n/// @param metaMorpho The address of the MetaMorphoV1_1 vault.\n/// @param caller The caller of the function.\n/// @param initialOwner The initial owner of the MetaMorphoV1_1 vault.\n/// @param initialTimelock The initial timelock of the MetaMorphoV1_1 vault.\n/// @param asset The address of the underlying asset.\n/// @param name The name of the MetaMorphoV1_1 vault.\n/// @param symbol The symbol of the MetaMorphoV1_1 vault.\n/// @param salt The salt used for the MetaMorphoV1_1 vault's CREATE2 address.\nevent CreateMetaMorpho(\n    address indexed metaMorpho,\n    address indexed caller,\n    address initialOwner,\n    uint256 initialTimelock,\n    address indexed asset,\n    string name,\n    string symbol,\n    bytes32 salt\n);\n```\n\n## Vault Metrics\n\n### Total Deposits & Assets\n\n#### Morpho Vaults V2\n\nEasiest to implement - perfect for most applications\n\n```graphql [Unique Vault]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    address\n     totalAssets\n      totalAssetsUsd\n      totalSupply\n      liquidity\n      liquidityUsd\n      idleAssetsUsd\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaultV2s(first: 100) {\n    items {\n      address\n      totalAssets\n      totalAssetsUsd\n      totalSupply\n      liquidityUsd\n      idleAssetsUsd\n      }\n    }\n  }\n```\n\n{\" \"}\n\nThe following example demonstrates how to:\n- Connect to the Ethereum mainnet using Viem\n- Fetch total deposits and assets from a Morpho Vault V2\n- Calculate and display formatted vault statistics including total supply, total assets, and USD value\n- Parse and format results for easy consumption\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns {PublicClient} A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// The address of the Morpho Vault V2\nconst VAULT_ADDRESS: Address = \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\";\n\n// Minimal ABI for an ERC-4626 compliant vault to get total assets, supply, and the underlying asset.\n// Vault V2 is ERC-4626 compliant and supports these standard functions.\nconst MINIMAL_VAULT_ABI = parseAbi([\n  \"function totalAssets() external view returns (uint256)\",\n  \"function totalSupply() external view returns (uint256)\",\n  \"function asset() external view returns (address)\",\n]);\n\n// Minimal ABI for an ERC-20 token to get its decimals.\nconst MINIMAL_ERC20_ABI = parseAbi([\n  \"function decimals() external view returns (uint8)\",\n]);\n\ninterface VaultStats {\n  vaultAddress: Address;\n  totalSupply: bigint;\n  totalAssets: bigint;\n  totalAssetsUsd: number;\n  assetAddress: Address;\n  assetDecimals: number;\n}\n\n/**\n * Fetches the key statistics for a given Morpho vault.\n * @param {PublicClient} client - The Viem public client.\n * @param {Address} vaultAddress - The address of the vault to query.\n * @returns {Promise<VaultStats>} An object containing the vault's stats.\n */\nexport async function getVaultStats(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<VaultStats> {\n  console.log(`Fetching stats for vault: ${vaultAddress}...`);\n\n  // Use multicall to fetch vault data in a single RPC request for efficiency\n  const [totalSupply, totalAssets, assetAddress] = await client.multicall({\n    contracts: [\n      {\n        address: vaultAddress,\n        abi: MINIMAL_VAULT_ABI,\n        functionName: \"totalSupply\",\n      },\n      {\n        address: vaultAddress,\n        abi: MINIMAL_VAULT_ABI,\n        functionName: \"totalAssets\",\n      },\n      {\n        address: vaultAddress,\n        abi: MINIMAL_VAULT_ABI,\n        functionName: \"asset\",\n      },\n    ],\n    allowFailure: false,\n  });\n\n  // Fetch the decimals of the underlying asset (in this case, USDC)\n  const assetDecimals = await client.readContract({\n    address: assetAddress,\n    abi: MINIMAL_ERC20_ABI,\n    functionName: \"decimals\",\n  });\n\n  // --- USD CONVERSION ---\n  // For this script, we use a manual price for the underlying asset (USDC).\n  // In a production environment, you should replace this with a dynamic price feed.\n  //\n  // HOW TO GET A DYNAMIC PRICE:\n  // 1. Use an onchain oracle (e.g., Chainlink) if your script runs in a smart contract context.\n  // 2. Use the Morpho API's `assetByAddress` query to get `priceUsd`.\n  // 3. Use a third-party price API like DefiLlama, CoinGecko, or a paid service.\n  //\n  // Since the underlying asset is USDC, its price is pegged to ~$1.00.\n  const underlyingAssetPriceUsd = 1.0;\n\n  // Format the totalAssets value from a BigInt to a floating-point number\n  const totalAssetsFormatted = parseFloat(\n    formatUnits(totalAssets, assetDecimals)\n  );\n\n  // Calculate the total value in USD\n  const totalAssetsUsd = totalAssetsFormatted * underlyingAssetPriceUsd;\n\n  return {\n    vaultAddress,\n    totalSupply,\n    totalAssets,\n    totalAssetsUsd,\n    assetAddress,\n    assetDecimals,\n  };\n}\n\n/**\n * Displays the fetched vault statistics in a clean, readable format.\n * @param {VaultStats} stats - The vault statistics object.\n */\nexport function displayVaultStats(stats: VaultStats): void {\n  console.log(\"\\n✅ --- Morpho Vault Stats --- ✅\");\n  console.log(`\\nVault Address: ${stats.vaultAddress}`);\n  console.log(`Underlying Asset: ${stats.assetAddress}`);\n\n  // The vault's shares (totalSupply) are typically 18 decimals, regardless of the underlying asset's decimals.\n  const totalSupplyFormatted = formatUnits(stats.totalSupply, 18);\n  const totalAssetsFormatted = formatUnits(stats.totalAssets, stats.assetDecimals);\n\n  console.log(\"\\n--- Totals ---\");\n  console.log(\n    `Total Supply (Shares): ${totalSupplyFormatted} (raw: ${stats.totalSupply})`\n  );\n  console.log(\n    `Total Assets (${stats.assetDecimals} decimals): ${totalAssetsFormatted} (raw: ${stats.totalAssets})`\n  );\n  console.log(\n    `Total Assets (USD):      $${stats.totalAssetsUsd.toLocaleString(\"en-US\", {\n      minimumFractionDigits: 2,\n      maximumFractionDigits: 2,\n    })}`\n  );\n  console.log(\"\\n---------------------------------\");\n}\n\n/**\n * Main function to run the script.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    const vaultStats = await getVaultStats(client, VAULT_ADDRESS);\n    displayVaultStats(vaultStats);\n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFetching stats for vault: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145...\n\n✅ --- Morpho Vault Stats --- ✅\n\nVault Address: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\nUnderlying Asset: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\n\n--- Totals ---\nTotal Supply (Shares): 406046.668299445014491638 (raw: 406046668299445014491638)\nTotal Assets (6 decimals): 409312.044166 (raw: 409312044166)\nTotal Assets (USD):      $409,312.04\n\n---------------------------------\n```\n\n{\" \"}\n\nAs 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.\n\n```solidity [Raw Contract Calls]\n/// @notice Returns the total assets deposited into a VaultV2 `vault`.\n    /// @dev This includes both idle assets in the vault and assets allocated to adapters.\n    /// @dev The value is computed by accruing interest and aggregating adapter positions.\n    /// @param vault The address of the VaultV2 vault.\n    /// @return totalAssets The total assets controlled by the vault.\n    function totalDepositVaultV2(address vault) public view returns (uint256 totalAssets) {\n        totalAssets = IVaultV2(vault).totalAssets();\n    }\n```\n\n#### On Morpho Vaults V1\n\nEasiest to implement - perfect for most applications\n\n```graphql [Unique Vault]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    state {\n      totalAssets\n      totalAssetsUsd\n      totalSupply\n    }\n    liquidity {\n      underlying\n      usd\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      state {\n        totalAssets\n        totalAssetsUsd\n        totalSupply\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThe following example demonstrates how to:\n- Connect to the Ethereum mainnet using Viem\n- Fetch total deposits and assets from a Morpho Vault V1\n- Calculate and display formatted vault statistics including total supply, total assets, and USD value\n- Parse and format results for easy consumption\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns {PublicClient} A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// The address of the Steakhouse USDC MetaMorpho Vault\nconst VAULT_ADDRESS: Address = \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\";\n\n// Minimal ABI for an ERC-4626 compliant vault to get total assets, supply, and the underlying asset.\nconst MINIMAL_VAULT_ABI = parseAbi([\n  \"function totalAssets() external view returns (uint256)\",\n  \"function totalSupply() external view returns (uint256)\",\n  \"function asset() external view returns (address)\",\n]);\n\n// Minimal ABI for an ERC-20 token to get its decimals.\nconst MINIMAL_ERC20_ABI = parseAbi([\n  \"function decimals() external view returns (uint8)\",\n]);\n\ninterface VaultStats {\n  vaultAddress: Address;\n  totalSupply: bigint;\n  totalAssets: bigint;\n  totalAssetsUsd: number;\n  assetAddress: Address;\n  assetDecimals: number;\n}\n\n/**\n * Fetches the key statistics for a given Morpho vault.\n * @param {PublicClient} client - The Viem public client.\n * @param {Address} vaultAddress - The address of the vault to query.\n * @returns {Promise<VaultStats>} An object containing the vault's stats.\n */\nexport async function getVaultStats(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<VaultStats> {\n  console.log(`Fetching stats for vault: ${vaultAddress}...`);\n\n  // Use multicall to fetch vault data in a single RPC request for efficiency\n  const [totalSupply, totalAssets, assetAddress] = await client.multicall({\n    contracts: [\n      {\n        address: vaultAddress,\n        abi: MINIMAL_VAULT_ABI,\n        functionName: \"totalSupply\",\n      },\n      {\n        address: vaultAddress,\n        abi: MINIMAL_VAULT_ABI,\n        functionName: \"totalAssets\",\n      },\n      {\n        address: vaultAddress,\n        abi: MINIMAL_VAULT_ABI,\n        functionName: \"asset\",\n      },\n    ],\n    allowFailure: false,\n  });\n\n  // Fetch the decimals of the underlying asset (in this case, USDC)\n  const assetDecimals = await client.readContract({\n    address: assetAddress,\n    abi: MINIMAL_ERC20_ABI,\n    functionName: \"decimals\",\n  });\n\n  // --- USD CONVERSION ---\n  // For this script, we use a manual price for the underlying asset (USDC).\n  // In a production environment, you should replace this with a dynamic price feed.\n  //\n  // HOW TO GET A DYNAMIC PRICE:\n  // 1. Use an onchain oracle (e.g., Chainlink) if your script runs in a smart contract context.\n  // 2. Use the Morpho API's `assetByAddress` query to get `priceUsd`.\n  // 3. Use a third-party price API like DefiLlama, CoinGecko, or a paid service.\n  //\n  // Since the underlying asset is USDC, its price is pegged to ~$1.00.\n  const underlyingAssetPriceUsd = 1.0;\n\n  // Format the totalAssets value from a BigInt to a floating-point number\n  const totalAssetsFormatted = parseFloat(\n    formatUnits(totalAssets, assetDecimals)\n  );\n\n  // Calculate the total value in USD\n  const totalAssetsUsd = totalAssetsFormatted * underlyingAssetPriceUsd;\n\n  return {\n    vaultAddress,\n    totalSupply,\n    totalAssets,\n    totalAssetsUsd,\n    assetAddress,\n    assetDecimals,\n  };\n}\n\n/**\n * Displays the fetched vault statistics in a clean, readable format.\n * @param {VaultStats} stats - The vault statistics object.\n */\nexport function displayVaultStats(stats: VaultStats): void {\n  console.log(\"\\n✅ --- Morpho Vault Stats --- ✅\");\n  console.log(`\\nVault Address: ${stats.vaultAddress}`);\n  console.log(`Underlying Asset: ${stats.assetAddress}`);\n\n  // The vault's shares (totalSupply) are typically 18 decimals, regardless of the underlying asset's decimals.\n  const totalSupplyFormatted = formatUnits(stats.totalSupply, 18);\n  const totalAssetsFormatted = formatUnits(stats.totalAssets, stats.assetDecimals);\n\n  console.log(\"\\n--- Totals ---\");\n  console.log(\n    `Total Supply (Shares): ${totalSupplyFormatted} (raw: ${stats.totalSupply})`\n  );\n  console.log(\n    `Total Assets (${stats.assetDecimals} decimals): ${totalAssetsFormatted} (raw: ${stats.totalAssets})`\n  );\n  console.log(\n    `Total Assets (USD):      $${stats.totalAssetsUsd.toLocaleString(\"en-US\", {\n      minimumFractionDigits: 2,\n      maximumFractionDigits: 2,\n    })}`\n  );\n  console.log(\"\\n---------------------------------\");\n}\n\n/**\n * Main function to run the script.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    const vaultStats = await getVaultStats(client, VAULT_ADDRESS);\n    displayVaultStats(vaultStats);\n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFetching stats for vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB...\n\n✅ --- Morpho Vault Stats --- ✅\n\nVault Address: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\nUnderlying Asset: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\n\n--- Totals ---\nTotal Supply (Shares): 151070805.545457516059431924 (raw: 151070805545457516059431924)\nTotal Assets (6 decimals): 164797857.365748 (raw: 164797857365748)\nTotal Assets (USD):      $164,797,857.37\n\n---------------------------------\n```\n\n{\" \"}\n\nAs it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain.\nFeel 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.\n\n```solidity [Raw Contract Calls]\n/// @notice Returns the total assets deposited into a MetaMorpho `vault`.\n    /// @param vault The address of the MetaMorpho vault.\n    function totalDepositVault(address vault) public view returns (uint256 totalAssets) {\n        totalAssets = IMetaMorpho(vault).totalAssets();\n    }\n```\n\n### APY (Native + Rewards)\n\n#### Morpho Vaults V2\n\n###### Morpho Vaults V2 can be eligible for 2 levels of rewards:\n\n- **Market level rewards:** These are inherited from the Morpho Markets V1 where the Morpho Vault V2 allocates assets.\n- **Vault level rewards:** \n  1. One type of rewards here are inherited from the Morpho Vaults V1 where the Morpho Vault V2 allocates assets.\n  2. Second type of rewards here are distributed directly to the Morpho Vault V2 itself.\n\nNote for Morpho Vault V2: all rewards appearing on the Morpho Api are displayed under `rewards` section directly.\n\n###### APY Components Breakdown:\n\n1. **Native APY:** The base yield earned from depositing assets into either Morpho Markets V1 or Morpho Vaults V1.\n2. **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`.\n3. **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)\n4. **Performance Fee Adjustment:** The performance fee is applied only to the Native APY component.\n5. **Management Fee Adjustment:** A time-based fee (annual rate, if applicable) deducted from the total assets regardless of performance.\n\nThe combination of these components results in the Net APY:\n```math\n\\text{Net APY}= \\text{Native APY} \\times (1 - \\text{Performance Fee}) + \\text{Underlying Token Yield}\n\n```\n\n```math\n\\phantom{\\text{Net APY} =} + \\sum \\text{Rewards APR} - \\text{Management Fee}\n```\n\nWhere:\n- Performance Fee is applied **only** to Native APY (as a percentage)\n- Management Fee is applied to total assets (as an annual rate)\n- Underlying Token Yield applies only to yield-bearing assets (0 otherwise)\n- Rewards APR is the sum of all reward incentives\n\n###### Important UI Reference one might find on apps:\n\n1. `avgApy` represents the Native APY (6h average vault APY excluding rewards, before deducting the performance fee)\n2. `avgNetApy` represents the complete APY (6h average vault APY including rewards, after deducting the performance fee)\n\n```graphql [Unique Vault]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    address\n    asset {\n      yield {\n        apr\n      }\n    }\n    avgApy\n    avgNetApy\n    performanceFee\n    managementFee\n    maxRate\n    rewards {\n      asset {\n        address\n        chain {\n          id\n        }\n      }\n      supplyApr\n      yearlySupplyTokens\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      address\n      asset {\n        yield {\n          apr\n        }\n      }\n      avgApy\n      avgNetApy\n      performanceFee\n      managementFee\n      maxRate\n      rewards {\n        asset {\n          address\n          chain {\n            id\n          }\n        }\n        supplyApr\n        yearlySupplyTokens\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n**Important Limitation:** The current onchain APY calculation for Vault V2 only supports vaults that allocate to **Morpho Vaults V1** (MetaMorpho) through `MorphoVaultV1Adapter`.\n\n**Rewards** APR are omitted. \n\nIf a Vault V2 allocates directly to Morpho Markets V1 via `MorphoMarketV1AdapterV2`, those allocations will be **excluded** from the APY calculation in the current implementation.\n\nFor 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.\n\nAs it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain.\nFeel free to refer to the [Morpho Vault V2 Snippets](https://github.com/morpho-org/vault-v2/blob/main/README.md) for extensive examples.\n\n```solidity\n/// @notice Returns the current supply APY of a VaultV2 vault.\n    /// @dev This is calculated as the weighted average APY across all adapters, accounting for fees and maxRate cap.\n    /// @dev Only works with Morpho Vault V1 adapters (MetaMorpho). For other adapter types, their contribution is skipped.\n    /// @dev The gross APY is capped by the annualized maxRate, then performance fee is applied, and management fee is subtracted.\n    /// @param vault The address of the VaultV2 vault.\n    /// @return avgSupplyApy The weighted average supply APY of the vault after all fees and caps (in WAD, 1e18 = 100%).\n    function supplyAPYVaultV2(address vault) public view returns (uint256 avgSupplyApy) {\n        uint256 totalAssets = IVaultV2(vault).totalAssets();\n        if (totalAssets == 0) return 0;\n\n        uint256 adapterCount = IVaultV2(vault).adaptersLength();\n        uint256 weightedSum;\n\n        for (uint256 i; i < adapterCount; ++i) {\n            address adapter = IVaultV2(vault).adapters(i);\n\n            // Try to detect if this is a Morpho Vault V1 Adapter\n            try IMorphoVaultV1Adapter(adapter).morphoVaultV1() returns (address vaultV1) {\n                // Get the real assets in this adapter\n                uint256 adapterRealAssets = IAdapter(adapter).realAssets();\n\n                // Calculate the APY of the underlying Morpho Vault V1\n                uint256 vaultV1APY = supplyAPYVaultV1(vaultV1);\n\n                // Weight by the adapter's real assets\n                weightedSum += vaultV1APY.wMulDown(adapterRealAssets);\n            } catch {\n                // If not a Morpho Vault V1 Adapter, skip for now\n                // TODO: add support for Morpho Market adapters\n                continue;\n            }\n        }\n\n        // Calculate the gross APY (weighted by total assets)\n        uint256 grossAPY = weightedSum.mulDivDown(WAD, totalAssets);\n\n        // Cap the gross APY at the annualized maxRate\n        // maxRate is a per-second rate, so we annualize it by multiplying by seconds in a year\n        uint64 maxRate = IVaultV2(vault).maxRate();\n        uint256 annualizedMaxRate = uint256(maxRate) * 365 days;\n        uint256 cappedAPY = Math.min(grossAPY, annualizedMaxRate);\n\n        // Apply performance fee (performance fee is taken on the capped yield)\n        uint96 performanceFee = IVaultV2(vault).performanceFee();\n        uint256 apyAfterPerformanceFee = cappedAPY.mulDivDown(WAD - performanceFee, WAD);\n\n        // Apply management fee (annualized rate that reduces the net APY)\n        // Management fee is stored as a per-second rate, so we multiply by seconds in a year\n        // Management fee is applied to the total assets (1 + APY), not just the principal\n        uint96 managementFee = IVaultV2(vault).managementFee();\n        uint256 annualManagementFee = uint256(managementFee) * 365 days;\n        uint256 netAnnualManagementFee = (WAD + cappedAPY).mulDivDown(annualManagementFee, WAD);\n\n        // Net APY = APY after performance fee - net annual management fee\n        avgSupplyApy = apyAfterPerformanceFee >= netAnnualManagementFee\n            ? apyAfterPerformanceFee - netAnnualManagementFee\n            : 0;\n    }\n```\n\n#### Morpho Vaults V1\n\n###### Morpho Vaults V1 can be eligible for 2 levels of rewards:\n\n- **Market level rewards:** These are inherited from the markets where the vault allocates assets, accessible via `state.allocation.market.state.rewards` (e.g., `supplyApr`).\n- **Vault level rewards:** These are distributed directly to the vault itself, accessible via `state.rewards` (e.g., `supplyApr`).\n\n###### APY Components Breakdown:\n\n1. **Native APY:** The base yield earned from depositing assets into markets.\n2. **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`.\n3. **Reward APRs:** Additional incentives from both:\n\n   - **Vault-level rewards:** Direct rewards to the vault via `state.rewards`\n   - **Market-level rewards:** Allocated proportionally from markets via `state.allocations.market.state.rewards` using weighted averages on allocations\n\n4. **Performance Fee Adjustment:** The performance fee is applied only to the Native APY component.\n\nThe combination of these components (adding rewards, subtracting fees) results in the Net APY.\n\n```math\nNet Apy = Native APY + Underlying Token Yield + Rewards APRs - Perf Fee_{onNativeApy}\n```\n\n###### Important UI Reference one might find on apps:\n\n1. `avgApy` represents the Native APY (6h average vault APY excluding rewards, before deducting the performance fee)\n2. `avgNetApy` represents the complete APY (6h average vault APY including rewards, after deducting the performance fee)\n\n```graphql [Unique Vault]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    asset {\n      yield {\n        apr\n      }\n    }\n    state {\n      apy\n      netApy\n      netApyWithoutRewards\n      avgApy\n      avgNetApy\n      dailyApy\n      dailyNetApy\n      weeklyApy\n      weeklyNetApy\n      monthlyApy\n      monthlyNetApy\n      rewards {\n        asset {\n          address\n          chain {\n            id\n          }\n        }\n        supplyApr\n        yearlySupplyTokens\n      }\n      allocation {\n        supplyAssets\n        supplyAssetsUsd\n        market {\n          uniqueKey\n          state {\n            rewards {\n              asset {\n                address\n                chain {\n                  id\n                }\n              }\n              supplyApr\n              borrowApr\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      asset {\n        yield {\n          apr\n        }\n      }\n      state {\n        apy\n        netApy\n        netApyWithoutRewards\n        avgApy\n        avgNetApy\n        dailyApy\n        dailyNetApy\n        weeklyApy\n        weeklyNetApy\n        monthlyApy\n        monthlyNetApy\n        rewards {\n          asset {\n            address\n            chain {\n              id\n            }\n          }\n          supplyApr\n          yearlySupplyTokens\n        }\n        allocation {\n          supplyAssets\n          supplyAssetsUsd\n          market {\n            uniqueKey\n            state {\n              rewards {\n                asset {\n                  address\n                  chain {\n                    id\n                  }\n                }\n                supplyApr\n                borrowApr\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n1. Rewards extra APY **are NOT** query-able onchain.\n2. **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.\n3. This example demonstrates how to:\n- Calculate the weighted average APY across all markets in the vault's withdrawal queue\n- Use multicall for efficient batch operations to fetch market data\n- Properly handle IRM (Interest Rate Model) calculations for each market\n- Account for asset allocation weights when computing the final vault APY\n- Display both percentage and raw WAD values for precision\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, { retryCount: 2 }),\n  });\n}\n\nconst VAULT_ADDRESS: Address = \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\";\n\nconst MORPHO_BLUE_ADDRESS: Address =\n  \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// Minimal ABIs with only the functions we need for this script.\nconst METAMORPHO_ABI = parseAbi([\n  \"function withdrawQueue(uint256) external view returns (bytes32)\",\n  \"function withdrawQueueLength() external view returns (uint256)\",\n]);\n\nconst MORPHO_BLUE_ABI = parseAbi([\n  \"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)\",\n  \"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n  \"function position(bytes32 id, address user) external view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral)\",\n]);\n\nconst IRM_ABI = parseAbi([\n    \"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) external view returns (uint256)\",\n  ]);\n\ntype MarketParams = {\n  loanToken: Address;\n  collateralToken: Address;\n  oracle: Address;\n  irm: Address;\n  lltv: bigint;\n};\n\ntype MarketState = {\n  totalSupplyAssets: bigint;\n  totalSupplyShares: bigint;\n  totalBorrowAssets: bigint;\n  totalBorrowShares: bigint;\n  lastUpdate: bigint;\n  fee: bigint;\n};\n\nconst WAD = 10n ** 18n;\nconst SECONDS_PER_YEAR = 31536000n;\nconst VIRTUAL_ASSETS = 1n; // To avoid division by zero\nconst VIRTUAL_SHARES = 10n ** 6n; // To avoid division by zero\n\nconst wMulDown = (x: bigint, y: bigint): bigint => (x * y) / WAD;\nconst wDivUp = (x: bigint, y: bigint): bigint => (x * WAD + y - 1n) / y;\n\nconst wTaylorCompounded = (x: bigint, n: bigint): bigint => {\n  const firstTerm = x * n;\n  const secondTerm = (firstTerm * firstTerm) / (2n * WAD);\n  const thirdTerm = (secondTerm * firstTerm) / (3n * WAD);\n  return firstTerm + secondTerm + thirdTerm;\n};\n\n/** Converts a share amount to its corresponding asset amount, rounding down. */\nconst toAssetsDown = (\n  shares: bigint,\n  totalAssets: bigint,\n  totalShares: bigint\n): bigint => {\n  if (totalShares === 0n) return shares;\n  return (shares * (totalAssets + VIRTUAL_ASSETS)) / (totalShares + VIRTUAL_SHARES);\n};\n\n/**\n * Accrues interest on a market from its last update time to the current block's timestamp.\n * This is crucial for getting the real-time state of the market.\n */\nfunction accrueInterests(\n  marketState: MarketState,\n  borrowRate: bigint,\n  blockTimestamp: bigint\n): MarketState {\n  const elapsed = blockTimestamp - marketState.lastUpdate;\n  if (elapsed === 0n || marketState.totalBorrowAssets === 0n) return marketState;\n  const interest = wMulDown(marketState.totalBorrowAssets, wTaylorCompounded(borrowRate, elapsed));\n  return { ...marketState, totalSupplyAssets: marketState.totalSupplyAssets + interest, totalBorrowAssets: marketState.totalBorrowAssets + interest };\n}\n\n/**\n * Calculates the current supply APY and market state for a single Morpho V1 market.\n */\nasync function getMarketStateAndApy(\n  client: PublicClient,\n  marketId: `0x${string}`,\n  blockTimestamp: bigint\n): Promise<{ state: MarketState; apy: bigint }> {\n  const [marketStateResult, marketParamsResult] = await client.multicall({\n    contracts: [\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"market\", args: [marketId] },\n      { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"idToMarketParams\", args: [marketId] },\n    ],\n    allowFailure: false,\n  });\n\n  const staleMarketState: MarketState = {\n    totalSupplyAssets: marketStateResult[0], totalSupplyShares: marketStateResult[1],\n    totalBorrowAssets: marketStateResult[2], totalBorrowShares: marketStateResult[3],\n    lastUpdate: marketStateResult[4], fee: marketStateResult[5],\n  };\n\n  const params: MarketParams = {\n    loanToken: marketParamsResult[0], collateralToken: marketParamsResult[1],\n    oracle: marketParamsResult[2], irm: marketParamsResult[3], lltv: marketParamsResult[4],\n  };\n\n  // If the IRM address is zero, the market has no interest model, so APY is 0.\n  if (params.irm === \"0x0000000000000000000000000000000000000000\") {\n    return { state: staleMarketState, apy: 0n };\n  }\n\n  const borrowRate = await client.readContract({\n    address: params.irm, abi: IRM_ABI, functionName: \"borrowRateView\", args: [params, staleMarketState],\n  }) as bigint;\n\n  const state = accrueInterests(staleMarketState, borrowRate, blockTimestamp);\n  const borrowApy = wTaylorCompounded(borrowRate, SECONDS_PER_YEAR);\n  const utilization = state.totalSupplyAssets > 0n ? wDivUp(state.totalBorrowAssets, state.totalSupplyAssets) : 0n;\n  const apy = wMulDown(wMulDown(borrowApy, utilization), WAD - state.fee);\n\n  return { state, apy };\n}\n\n/**\n * Calculates the vault's underlying APY by performing a weighted average\n * of the supply APYs of all markets where it has supplied assets.\n */\nexport async function calculateVaultApy(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<bigint> {\n  console.log(\"Fetching vault's withdrawal queue length...\");\n  \n  // First get the length of the withdraw queue\n  const queueLength = await client.readContract({\n    address: vaultAddress, \n    abi: METAMORPHO_ABI, \n    functionName: \"withdrawQueueLength\",\n  }) as bigint;\n  \n  if (queueLength === 0n) {\n    console.log(\"Vault has no markets. APY is 0.\");\n    return 0n;\n  }\n\n  console.log(`Fetching ${queueLength} market(s) from withdrawal queue...`);\n  \n  // Get all market IDs using multicall\n  const calls = Array.from({ length: Number(queueLength) }, (_, i) => ({\n    address: vaultAddress,\n    abi: METAMORPHO_ABI,\n    functionName: \"withdrawQueue\" as const,\n    args: [BigInt(i)],\n  }));\n\n  const results = await client.multicall({\n    contracts: calls,\n    allowFailure: false,\n  });\n\n  const withdrawQueue = results.map(result => result as `0x${string}`);\n\n  console.log(`Found ${withdrawQueue.length} market(s). Fetching allocations and APYs...`);\n  const block = await client.getBlock({ blockTag: \"latest\" });\n\n  const marketDataPromises = withdrawQueue.map(async (marketId) => {\n    const [{ state, apy }, { 0: supplyShares }] = await Promise.all([\n      getMarketStateAndApy(client, marketId, block.timestamp),\n      client.readContract({\n        address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"position\", args: [marketId, vaultAddress],\n      }),\n    ]);\n    const allocation = toAssetsDown(supplyShares as bigint, state.totalSupplyAssets, state.totalSupplyShares);\n    return { supplyApy: apy, allocation };\n  });\n\n  const marketData = await Promise.all(marketDataPromises);\n\n  let totalWeightedApy = 0n;\n  let totalAllocation = 0n;\n\n  marketData.forEach(({ supplyApy, allocation }) => {\n    if (allocation > 0n) {\n      totalWeightedApy += supplyApy * allocation;\n      totalAllocation += allocation;\n    }\n  });\n\n  if (totalAllocation === 0n) {\n    console.log(\"Vault has zero total allocation. APY is 0.\");\n    return 0n;\n  }\n  \n  return totalWeightedApy / totalAllocation;\n}\n\n/**\n * Displays the final calculated vault APY.\n */\nexport function displayVaultApy(apy: bigint): void {\n  // To format a WAD-scaled number (18 decimals) as a percentage, we format it with 16 decimals.\n  const formattedApy = formatUnits(apy, 16);\n  \n  console.log(\"\\n✅ --- Morpho Vault Underlying APY --- ✅\");\n  console.log(`\\nCalculated Vault APY: ${formattedApy}%`);\n  console.log(`(Raw WAD value: ${apy})`);\n  console.log(\"\\n---------------------------------------\");\n}\n\n/**\n * Main function to run the script.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    const vaultApy = await calculateVaultApy(client, VAULT_ADDRESS);\n    displayVaultApy(vaultApy);\n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFetching vault's withdrawal queue length...\nFetching 4 market(s) from withdrawal queue...\nFound 4 market(s). Fetching allocations and APYs...\n\n✅ --- Morpho Vault Underlying APY --- ✅\n\nCalculated Vault APY: 3.2576470788039398%\n(Raw WAD value: 32576470788039398)\n\n---------------------------------------\n```\n\n{\" \"}\n\nAs it is important to accrue interests on the underlying markets, Morpho Association provided a library to accrue them onchain.\nFeel 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.\n\n```solidity\n/// @notice Returns the current APY of a MetaMorpho vault.\n    /// @dev It is computed as the sum of all APY of enabled markets weighted by the supply on these markets.\n    /// @param vault The address of the MetaMorpho vault.\n    function supplyAPYVault(address vault) public view returns (uint256 avgSupplyApy) {\n        uint256 ratio;\n        uint256 queueLength = IMetaMorpho(vault).withdrawQueueLength();\n\n        uint256 totalAmount = totalDepositVault(vault);\n\n        for (uint256 i; i < queueLength; ++i) {\n            Id idMarket = IMetaMorpho(vault).withdrawQueue(i);\n\n            MarketParams memory marketParams = morpho.idToMarketParams(idMarket);\n            Market memory market = morpho.market(idMarket);\n\n            uint256 currentSupplyAPY = supplyAPYMarket(marketParams, market);\n            uint256 vaultAsset = vaultAssetsInMarket(vault, marketParams);\n            ratio += currentSupplyAPY.wMulDown(vaultAsset);\n        }\n\n        avgSupplyApy = ratio.mulDivDown(WAD - IMetaMorpho(vault).fee(), totalAmount);\n    }\n```\n\n### Share Price (Token Value)\n\n**Why You Shouldn't Calculate Manually**\n\nComputing 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.\n\n**How ERC-4626 Calculates Share Price**\n\nThe standard includes **virtual offsets** to prevent inflation attacks and ensure consistency:\n\n- **Virtual Assets**: `+1` added to totalAssets\n- **Virtual Shares**: `+10^DECIMALS_OFFSET` added to totalSupply\n  - DECIMALS_OFFSET matches the underlying asset decimals (6 for USDC, 18 for WETH)\n\n**Formula** for pricing 1 share (10^18 wei):\n\n```math\n\\text{sharePrice} = \\frac{10^{18} \\times (\\text{totalAssets} + 1)}{\\text{totalSupply} + 10^{\\text{DECIMALS\\_OFFSET}}}\n```\n\nThe result is in raw underlying asset units. To get the human-readable price, divide by `10^assetDecimals`.\n\n**Recommended Methods:**\n- **API**: Use the `sharePrice` field (already computed correctly)\n- **Onchain**: Use `convertToAssets(10^18)` instead of manual calculation\n\n**Practical Example with USDC Vault**\n\nUsing real data from a USDC vault (6 decimals):\n\n```math\n\\text{totalAssets: } 473{,}435{,}155{,}471{,}028 \\text{ (raw USDC units)}\n```\n\n```math\n\\text{totalSupply: } 427{,}784{,}657{,}006{,}652{,}956{,}819{,}706{,}379 \\text{ (raw share units)}\n```\n\nApplying the formula:\n\n```math\n\\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)}\n```\n\nConverting to human-readable:\n\n```math\n\\frac{1{,}106{,}713}{10^6} = 1.106713 \\text{ USDC per share}\n```\n\nThis matches the API's `sharePrice` field value!\n\n#### Morpho Vaults V2\n\nMorpho Api for Morpho Vaults V2 provides only `totalAssets`& `totalSupply` at the moment. One has to do the maths explained above.\n\n```graphql [Unique Vault]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    totalAssets\n    totalSupply\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      address\n      totalSupply\n      totalAssets\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis 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.\n\nThe script shows how to:\n- Connect to Ethereum mainnet using Viem.\n- Use the `convertToAssets` function to determine how many underlying assets correspond to one full vault share token.\n- Fetch vault and underlying asset details (symbols, decimals) using `multicall` for efficiency.\n- Format the raw price into a human-readable string (e.g., \"1.008 USDC\").\n- Calculate the USD value of the vault token.\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// The address of the Morpho Vault V2\nconst VAULT_V2_ADDRESS: Address = \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\";\n\n// Minimal ABIs for an ERC-4626 vault and an ERC-20 token.\n// Vault V2 is ERC-4626 compliant and supports these standard functions.\nconst VAULT_V2_ABI = parseAbi([\n  \"function convertToAssets(uint256 shares) view returns (uint256 assets)\",\n  \"function totalAssets() view returns (uint256)\",\n  \"function totalSupply() view returns (uint256)\",\n  \"function asset() view returns (address)\",\n  \"function symbol() view returns (string)\",\n]);\n\nconst ERC20_ABI = parseAbi([\n  \"function decimals() view returns (uint8)\",\n  \"function symbol() view returns (string)\",\n]);\n\ninterface VaultPriceInfo {\n  vaultAddress: Address;\n  vaultSymbol: string;\n  sharePriceInAssets: bigint; // Raw value from convertToAssets\n  underlyingAsset: {\n    address: Address;\n    symbol: string;\n    decimals: number;\n  };\n  formattedPrice: string; // e.g., \"1.026 USDC\"\n  usdPrice: number;\n}\n\n/**\n * Calculates the price of a single vault share in terms of its underlying asset.\n * This function demonstrates the standard ERC-4626 method for pricing shares.\n * @param client The Viem public client.\n * @param vaultAddress The address of the Morpho Vault V2.\n * @returns A promise that resolves to a VaultPriceInfo object.\n */\nexport async function calculateVaultTokenPrice(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<VaultPriceInfo> {\n  console.log(`Calculating token price for vault: ${vaultAddress}...`);\n\n  // A single vault share token has 18 decimals.\n  const oneShare = 10n ** 18n;\n\n  // Use multicall to fetch vault and underlying asset data efficiently.\n  const [\n    assetsPerShare,\n    underlyingAssetAddress,\n    vaultSymbol,\n    totalSupply,\n    totalAssets,\n  ] = await client.multicall({\n    contracts: [\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"convertToAssets\",\n        args: [oneShare],\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"asset\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"symbol\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"totalSupply\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"totalAssets\",\n      },\n    ],\n    allowFailure: false,\n  });\n\n  // Fetch details of the underlying asset (e.g., USDC).\n  const [underlyingDecimals, underlyingSymbol] = await client.multicall({\n    contracts: [\n      {\n        address: underlyingAssetAddress,\n        abi: ERC20_ABI,\n        functionName: \"decimals\",\n      },\n      {\n        address: underlyingAssetAddress,\n        abi: ERC20_ABI,\n        functionName: \"symbol\",\n      },\n    ],\n    allowFailure: false,\n  });\n\n  // For USD conversion, a dynamic price feed is recommended.\n  // For this example with USDC, we can hardcode the price as ~$1.0.\n  const underlyingAssetPriceUsd = 1.0;\n  const formattedAssetsPerShare = formatUnits(\n    assetsPerShare,\n    underlyingDecimals\n  );\n  const usdPrice = parseFloat(formattedAssetsPerShare) * underlyingAssetPriceUsd;\n\n  return {\n    vaultAddress,\n    vaultSymbol,\n    sharePriceInAssets: assetsPerShare,\n    underlyingAsset: {\n      address: underlyingAssetAddress,\n      symbol: underlyingSymbol,\n      decimals: underlyingDecimals,\n    },\n    formattedPrice: `${formattedAssetsPerShare} ${underlyingSymbol}`,\n    usdPrice,\n  };\n}\n\n/**\n * Displays the calculated vault token price information in a clean format.\n * @param priceInfo The object containing the price information.\n */\nexport function displayVaultTokenPrice(priceInfo: VaultPriceInfo): void {\n  console.log(\"\\n✅ --- Morpho Vault V2 Token Price --- ✅\");\n  console.log(`\\nVault: ${priceInfo.vaultSymbol} (${priceInfo.vaultAddress})`);\n  console.log(\n    `Underlying Asset: ${priceInfo.underlyingAsset.symbol} (${priceInfo.underlyingAsset.address})`\n  );\n\n  console.log(\"\\n--- Price ---\");\n  console.log(`1 ${priceInfo.vaultSymbol} = ${priceInfo.formattedPrice}`);\n  console.log(\n    `Price (raw units): ${\n      priceInfo.sharePriceInAssets\n    } (with ${priceInfo.underlyingAsset.decimals} decimals)`\n  );\n  console.log(\n    `Price (USD): $${priceInfo.usdPrice.toLocaleString(\"en-US\", {\n      minimumFractionDigits: 4,\n      maximumFractionDigits: 4,\n    })}`\n  );\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Main function to orchestrate the script execution.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    const priceInfo = await calculateVaultTokenPrice(client, VAULT_V2_ADDRESS);\n    displayVaultTokenPrice(priceInfo);\n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nCalculating token price for vault: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145...\n\n--- Morpho Vault V2 Token Price ---\n\nVault: kUSDC (0x04422053aDDbc9bB2759b248B574e3FCA76Bc145)\nUnderlying Asset: USDC (0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)\n\n--- Price ---\n1 kUSDC = 1.008451 USDC\nPrice (raw units): 1008451 (with 6 decimals)\nPrice (USD): $1.0085\n\n----------------------------------------\n```\n\n{\" \"}\n\n```solidity\n// Get the price of 1 vault token in underlying asset units\n// Works for both Vault V1 and V2 as they are both ERC-4626 compliant\nuint256 oneShare = 10**IERC20Metadata(vault).decimals();\nuint256 priceInAssets = IERC4626(vault).convertToAssets(oneShare);\n\n// Alternative: Calculate manually using total supply and total assets\nuint256 totalSupply = IERC20(vault).totalSupply();\nuint256 totalAssets = IERC4626(vault).totalAssets();\nuint256 priceManual = (totalAssets * oneShare) / totalSupply;\n\n// Both methods return the same result:\n// Price = how many underlying assets 1 vault token is worth\n```\n\n**Key Functions:**\n- `convertToAssets(shares)`: ERC-4626 standard function that converts vault shares to underlying assets\n- `totalAssets()`: Total underlying assets managed by the vault\n- `totalSupply()`: Total vault tokens in circulation\n\n**Price Formula:** `Price = totalAssets / totalSupply`\n\nThe `convertToAssets` approach is recommended as it handles edge cases and follows the ERC-4626 standard.\n\n**Note:** Both Morpho Vault V1 and V2 are ERC-4626 compliant, so the same functions work for both versions.\n\n#### Morpho Vaults V1\n\n```graphql [Unique Vault]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    state {\n      sharePrice\n      sharePriceUsd\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      state {\n        sharePrice\n        sharePriceUsd\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis 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.\n\nThe script shows how to:\n- Connect to Ethereum mainnet using Viem.\n- Use the `convertToAssets` function to determine how many underlying assets correspond to one full vault share token.\n- Fetch vault and underlying asset details (symbols, decimals) using `multicall` for efficiency.\n- Format the raw price into a human-readable string (e.g., \"1.026 USDC\").\n- Calculate the USD value of the vault token.\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// The address of the Steakhouse USDC MetaMorpho Vault\nconst VAULT_ADDRESS: Address = \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\";\n\n// Minimal ABIs for an ERC-4626 vault and an ERC-20 token.\nconst METAMORPHO_ABI = parseAbi([\n  \"function convertToAssets(uint256 shares) view returns (uint256 assets)\",\n  \"function totalAssets() view returns (uint256)\",\n  \"function totalSupply() view returns (uint256)\",\n  \"function asset() view returns (address)\",\n  \"function symbol() view returns (string)\",\n]);\n\nconst ERC20_ABI = parseAbi([\n  \"function decimals() view returns (uint8)\",\n  \"function symbol() view returns (string)\",\n]);\n\ninterface VaultPriceInfo {\n  vaultAddress: Address;\n  vaultSymbol: string;\n  sharePriceInAssets: bigint; // Raw value from convertToAssets\n  underlyingAsset: {\n    address: Address;\n    symbol: string;\n    decimals: number;\n  };\n  formattedPrice: string; // e.g., \"1.026 USDC\"\n  usdPrice: number;\n}\n\n/**\n * Calculates the price of a single vault share in terms of its underlying asset.\n * This function demonstrates the standard ERC-4626 method for pricing shares.\n * @param client The Viem public client.\n * @param vaultAddress The address of the MetaMorpho vault.\n * @returns A promise that resolves to a VaultPriceInfo object.\n */\nexport async function calculateVaultTokenPrice(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<VaultPriceInfo> {\n  console.log(`Calculating token price for vault: ${vaultAddress}...`);\n\n  // A single vault share token has 18 decimals.\n  const oneShare = 10n ** 18n;\n\n  // Use multicall to fetch vault and underlying asset data efficiently.\n  const [\n    assetsPerShare,\n    underlyingAssetAddress,\n    vaultSymbol,\n    totalSupply,\n    totalAssets,\n  ] = await client.multicall({\n    contracts: [\n      {\n        address: vaultAddress,\n        abi: METAMORPHO_ABI,\n        functionName: \"convertToAssets\",\n        args: [oneShare],\n      },\n      {\n        address: vaultAddress,\n        abi: METAMORPHO_ABI,\n        functionName: \"asset\",\n      },\n      {\n        address: vaultAddress,\n        abi: METAMORPHO_ABI,\n        functionName: \"symbol\",\n      },\n      {\n        address: vaultAddress,\n        abi: METAMORPHO_ABI,\n        functionName: \"totalSupply\",\n      },\n      {\n        address: vaultAddress,\n        abi: METAMORPHO_ABI,\n        functionName: \"totalAssets\",\n      },\n    ],\n    allowFailure: false,\n  });\n\n  // Fetch details of the underlying asset (e.g., USDC).\n  const [underlyingDecimals, underlyingSymbol] = await client.multicall({\n    contracts: [\n      {\n        address: underlyingAssetAddress,\n        abi: ERC20_ABI,\n        functionName: \"decimals\",\n      },\n      {\n        address: underlyingAssetAddress,\n        abi: ERC20_ABI,\n        functionName: \"symbol\",\n      },\n    ],\n    allowFailure: false,\n  });\n\n  // For USD conversion, a dynamic price feed is recommended.\n  // For this example with USDC, we can hardcode the price as ~$1.0.\n  const underlyingAssetPriceUsd = 1.0;\n  const formattedAssetsPerShare = formatUnits(\n    assetsPerShare,\n    underlyingDecimals\n  );\n  const usdPrice = parseFloat(formattedAssetsPerShare) * underlyingAssetPriceUsd;\n\n  return {\n    vaultAddress,\n    vaultSymbol,\n    sharePriceInAssets: assetsPerShare,\n    underlyingAsset: {\n      address: underlyingAssetAddress,\n      symbol: underlyingSymbol,\n      decimals: underlyingDecimals,\n    },\n    formattedPrice: `${formattedAssetsPerShare} ${underlyingSymbol}`,\n    usdPrice,\n  };\n}\n\n/**\n * Displays the calculated vault token price information in a clean format.\n * @param priceInfo The object containing the price information.\n */\nexport function displayVaultTokenPrice(priceInfo: VaultPriceInfo): void {\n  console.log(\"\\n✅ --- MetaMorpho Vault Token Price --- ✅\");\n  console.log(`\\nVault: ${priceInfo.vaultSymbol} (${priceInfo.vaultAddress})`);\n  console.log(\n    `Underlying Asset: ${priceInfo.underlyingAsset.symbol} (${priceInfo.underlyingAsset.address})`\n  );\n\n  console.log(\"\\n--- Price ---\");\n  console.log(`1 ${priceInfo.vaultSymbol} = ${priceInfo.formattedPrice}`);\n  console.log(\n    `Price (raw units): ${\n      priceInfo.sharePriceInAssets\n    } (with ${priceInfo.underlyingAsset.decimals} decimals)`\n  );\n  console.log(\n    `Price (USD): $${priceInfo.usdPrice.toLocaleString(\"en-US\", {\n      minimumFractionDigits: 4,\n      maximumFractionDigits: 4,\n    })}`\n  );\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Main function to orchestrate the script execution.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    const priceInfo = await calculateVaultTokenPrice(client, VAULT_ADDRESS);\n    displayVaultTokenPrice(priceInfo);\n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```json\nCalculating token price for vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB...\n\n--- Morpho Vault Token Price ---\n\nVault: steakUSDC (0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB)\nUnderlying Asset: USDC (0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)\n\n--- Price ---\n1 steakUSDC = 1.090931 USDC\nPrice (raw units): 1090931 (with 6 decimals)\nPrice (USD): $1.0909\n\n----------------------------------------\n```\n\n{\" \"}\n\n```solidity\n// Get the price of 1 vault token in underlying asset units\nuint256 oneShare = 10**IERC20Metadata(vault).decimals();\nuint256 priceInAssets = IMetaMorpho(vault).convertToAssets(oneShare);\n\n// Alternative: Calculate manually using total supply and total assets\nuint256 totalSupply = IERC20(vault).totalSupply();\nuint256 totalAssets = IMetaMorpho(vault).totalAssets();\nuint256 priceManual = (totalAssets * oneShare) / totalSupply;\n\n// Both methods return the same result:\n// Price = how many underlying assets 1 vault token is worth\n```\n\n**Key Functions:**\n- `convertToAssets(shares)`: ERC-4626 standard function that converts vault shares to underlying assets\n- `totalAssets()`: Total underlying assets managed by the vault\n- `totalSupply()`: Total vault tokens in circulation\n\n**Price Formula:** `Price = totalAssets / totalSupply`\n\nThe `convertToAssets` approach is recommended as it handles edge cases and follows the ERC-4626 standard.\n\n## Allocation & Strategy\n\n### Current Allocations\n\n#### Morpho Vaults V2\n\n**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:\n- **Morpho Markets V1** (via `MorphoMarketV1AdapterV2`)\n- **Morpho Vaults V1** (via `MorphoVaultV1Adapter`)\n- Any future Morpho protocol with an enabled adapter\n\n```graphql [Unique Vault]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    totalAssetsUsd\n    totalAssets\n    totalSupply\n    adapters {\n      items {\n        address\n        assets\n        assetsUsd\n        type\n      }\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      address\n      totalAssetsUsd\n      totalAssets\n      totalSupply\n      adapters {\n        items {\n          address\n          assets\n          assetsUsd\n          type\n        }\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates how to:\n- Fetch all adapters from the Vault V2 and detect their types\n- Retrieve allocations from each adapter (MorphoMarketV1AdapterV2 or MorphoVaultV1Adapter)\n- Calculate idle assets held directly by the vault\n- Determine allocation amounts and percentages across all destinations\n- Display formatted allocation results with adapter breakdown\n- Use multicall for efficient batch operations\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n  keccak256,\n  encodeAbiParameters,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, { retryCount: 2 }),\n  });\n}\n\nconst VAULT_V2_ADDRESS: Address = \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\";\nconst MORPHO_BLUE_ADDRESS: Address =\n  \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// Minimal ABIs with only the functions we need for this script.\nconst VAULT_V2_ABI = parseAbi([\n  \"function adaptersLength() external view returns (uint256)\",\n  \"function adapters(uint256) external view returns (address)\",\n  \"function asset() external view returns (address)\",\n  \"function totalAssets() external view returns (uint256)\",\n]);\n\nconst ADAPTER_ABI = parseAbi([\n  \"function realAssets() external view returns (uint256)\",\n  \"function morpho() external view returns (address)\",\n  \"function morphoVaultV1() external view returns (address)\",\n  \"function marketParamsListLength() external view returns (uint256)\",\n  \"function marketParamsList(uint256) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n]);\n\nconst MORPHO_BLUE_ABI = parseAbi([\n  \"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)\",\n  \"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n  \"function position(bytes32 id, address user) external view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral)\",\n]);\n\nconst IRM_ABI = parseAbi([\n  \"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) external view returns (uint256)\",\n]);\n\nconst MINIMAL_ERC20_ABI = parseAbi([\n  \"function decimals() view returns (uint8)\",\n  \"function balanceOf(address) view returns (uint256)\",\n]);\n\nconst MORPHO_VAULT_V1_ABI = parseAbi([\n  \"function asset() external view returns (address)\",\n  \"function balanceOf(address) external view returns (uint256)\",\n  \"function convertToAssets(uint256) external view returns (uint256)\",\n]);\n\ntype MarketParams = {\n  loanToken: Address;\n  collateralToken: Address;\n  oracle: Address;\n  irm: Address;\n  lltv: bigint;\n};\n\ntype MarketState = {\n  totalSupplyAssets: bigint;\n  totalSupplyShares: bigint;\n  totalBorrowAssets: bigint;\n  totalBorrowShares: bigint;\n  lastUpdate: bigint;\n  fee: bigint;\n};\n\nenum AdapterType {\n  MorphoMarketV1 = \"MorphoMarketV1Adapter\",\n  MorphoVaultV1 = \"MorphoVaultV1Adapter\",\n  Unknown = \"Unknown\"\n}\n\ninterface AllocationDestination {\n  type: \"Market\" | \"Vault\" | \"Idle\";\n  id?: `0x${string}`; // Market ID for markets\n  address?: Address; // Vault address for vaults\n  allocatedAssets: bigint;\n  percentage: number;\n}\n\ninterface AdapterAllocation {\n  adapterAddress: Address;\n  adapterType: AdapterType;\n  destinations: AllocationDestination[];\n  totalAssets: bigint;\n}\n\ninterface VaultV2Allocations {\n  idle: AllocationDestination;\n  adapters: AdapterAllocation[];\n  totalAllocated: bigint;\n}\n\nconst WAD = 10n ** 18n;\nconst VIRTUAL_ASSETS = 1n; // To avoid division by zero\nconst VIRTUAL_SHARES = 10n ** 6n; // To avoid division by zero\n\nconst wMulDown = (x: bigint, y: bigint): bigint => (x * y) / WAD;\nconst wTaylorCompounded = (x: bigint, n: bigint): bigint => {\n  const firstTerm = x * n;\n  const secondTerm = (firstTerm * firstTerm) / (2n * WAD);\n  const thirdTerm = (secondTerm * firstTerm) / (3n * WAD);\n  return firstTerm + secondTerm + thirdTerm;\n};\n\n/** Converts a share amount to its corresponding asset amount, rounding down. */\nconst toAssetsDown = (shares: bigint, totalAssets: bigint, totalShares: bigint): bigint => {\n  if (totalShares === 0n) return shares;\n  return (shares * (totalAssets + VIRTUAL_ASSETS)) / (totalShares + VIRTUAL_SHARES);\n};\n\n/** Detects the adapter type by trying to call specific functions */\nasync function detectAdapterType(client: PublicClient, adapterAddress: Address): Promise<AdapterType> {\n  try {\n    // Try to call morphoVaultV1() - if it succeeds, it's a MorphoVaultV1Adapter\n    await client.readContract({\n      address: adapterAddress,\n      abi: ADAPTER_ABI,\n      functionName: \"morphoVaultV1\",\n    });\n    return AdapterType.MorphoVaultV1;\n  } catch {\n    try {\n      // Try to call morpho() - if it succeeds, it's a MorphoMarketV1AdapterV2\n      await client.readContract({\n        address: adapterAddress,\n        abi: ADAPTER_ABI,\n        functionName: \"morpho\",\n      });\n      return AdapterType.MorphoMarketV1;\n    } catch {\n      return AdapterType.Unknown;\n    }\n  }\n}\n\n/** Fetches allocations from a MorphoMarketV1AdapterV2 */\nasync function getMarketAdapterAllocations(\n  client: PublicClient,\n  adapterAddress: Address,\n  blockTimestamp: bigint\n): Promise<AllocationDestination[]> {\n  const marketListLength = await client.readContract({\n    address: adapterAddress,\n    abi: ADAPTER_ABI,\n    functionName: \"marketParamsListLength\",\n  }) as bigint;\n\n  if (marketListLength === 0n) {\n    return [];\n  }\n\n  const calls = Array.from({ length: Number(marketListLength) }, (_, i) => ({\n    address: adapterAddress,\n    abi: ADAPTER_ABI,\n    functionName: \"marketParamsList\" as const,\n    args: [BigInt(i)],\n  }));\n\n  const marketParamsList = await client.multicall({ contracts: calls, allowFailure: false });\n\n  const destinations: AllocationDestination[] = [];\n\n  for (const marketParamsResult of marketParamsList) {\n    const params: MarketParams = {\n      loanToken: marketParamsResult[0],\n      collateralToken: marketParamsResult[1],\n      oracle: marketParamsResult[2],\n      irm: marketParamsResult[3],\n      lltv: marketParamsResult[4],\n    };\n\n    // Calculate market ID\n    const marketId = keccak256(\n      encodeAbiParameters(\n        [\n          { type: \"address\" },\n          { type: \"address\" },\n          { type: \"address\" },\n          { type: \"address\" },\n          { type: \"uint256\" },\n        ],\n        [params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]\n      )\n    ) as `0x${string}`;\n\n    // Get adapter's position in this market\n    const [marketState, { 0: supplyShares }] = await Promise.all([\n      client.readContract({\n        address: MORPHO_BLUE_ADDRESS,\n        abi: MORPHO_BLUE_ABI,\n        functionName: \"market\",\n        args: [marketId],\n      }),\n      client.readContract({\n        address: MORPHO_BLUE_ADDRESS,\n        abi: MORPHO_BLUE_ABI,\n        functionName: \"position\",\n        args: [marketId, adapterAddress],\n      }),\n    ]);\n\n    const allocatedAssets = toAssetsDown(\n      supplyShares as bigint,\n      marketState[0] as bigint,\n      marketState[1] as bigint\n    );\n\n    if (allocatedAssets > 0n) {\n      destinations.push({\n        type: \"Market\",\n        id: marketId,\n        allocatedAssets,\n        percentage: 0, // Will be calculated later\n      });\n    }\n  }\n\n  return destinations;\n}\n\n/** Fetches allocations from a MorphoVaultV1Adapter */\nasync function getVaultAdapterAllocations(\n  client: PublicClient,\n  adapterAddress: Address\n): Promise<AllocationDestination[]> {\n  const morphoVaultV1Address = await client.readContract({\n    address: adapterAddress,\n    abi: ADAPTER_ABI,\n    functionName: \"morphoVaultV1\",\n  }) as Address;\n\n  // Get the adapter's balance in the Morpho Vault V1\n  const shares = await client.readContract({\n    address: morphoVaultV1Address,\n    abi: MORPHO_VAULT_V1_ABI,\n    functionName: \"balanceOf\",\n    args: [adapterAddress],\n  }) as bigint;\n\n  // Convert shares to assets\n  const allocatedAssets = await client.readContract({\n    address: morphoVaultV1Address,\n    abi: MORPHO_VAULT_V1_ABI,\n    functionName: \"convertToAssets\",\n    args: [shares],\n  }) as bigint;\n\n  if (allocatedAssets > 0n) {\n    return [\n      {\n        type: \"Vault\",\n        address: morphoVaultV1Address,\n        allocatedAssets,\n        percentage: 0, // Will be calculated later\n      },\n    ];\n  }\n\n  return [];\n}\n\n/**\n * Fetches all allocations for a Vault V2\n * @returns VaultV2Allocations object containing idle assets and adapter allocations\n */\nexport async function getVaultV2Allocations(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<VaultV2Allocations> {\n  // Get idle assets (vault's direct balance)\n  const [underlyingAssetAddress, idleAssets, adaptersLength] = await client.multicall({\n    contracts: [\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"asset\" },\n      {\n        address: vaultAddress,\n        abi: MINIMAL_ERC20_ABI,\n        functionName: \"balanceOf\",\n        args: [vaultAddress],\n      } as any,\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"adaptersLength\" },\n    ],\n    allowFailure: false,\n  });\n\n  const adapterCount = Number(adaptersLength);\n\n  if (adapterCount === 0) {\n    console.log(\"Vault has no adapters. Only idle assets available.\");\n    return {\n      idle: {\n        type: \"Idle\",\n        allocatedAssets: idleAssets as bigint,\n        percentage: 100,\n      },\n      adapters: [],\n      totalAllocated: idleAssets as bigint,\n    };\n  }\n\n  // Fetch all adapter addresses\n  const adapterCalls = Array.from({ length: adapterCount }, (_, i) => ({\n    address: vaultAddress,\n    abi: VAULT_V2_ABI,\n    functionName: \"adapters\" as const,\n    args: [BigInt(i)],\n  }));\n\n  const adapterAddresses = (await client.multicall({\n    contracts: adapterCalls,\n    allowFailure: false,\n  })) as Address[];\n\n  console.log(`Found ${adapterAddresses.length} adapter(s). Fetching allocations...`);\n\n  const block = await client.getBlock({ blockTag: \"latest\" });\n  const adapterAllocations: AdapterAllocation[] = [];\n\n  // Process each adapter\n  for (const adapterAddress of adapterAddresses) {\n    const adapterType = await detectAdapterType(client, adapterAddress);\n    let destinations: AllocationDestination[] = [];\n\n    if (adapterType === AdapterType.MorphoMarketV1) {\n      destinations = await getMarketAdapterAllocations(client, adapterAddress, block.timestamp);\n    } else if (adapterType === AdapterType.MorphoVaultV1) {\n      destinations = await getVaultAdapterAllocations(client, adapterAddress);\n    }\n\n    const totalAssets = destinations.reduce((sum, d) => sum + d.allocatedAssets, 0n);\n\n    if (totalAssets > 0n || destinations.length > 0) {\n      adapterAllocations.push({\n        adapterAddress,\n        adapterType,\n        destinations,\n        totalAssets,\n      });\n    }\n  }\n\n  // Calculate total allocated across all destinations\n  const totalInAdapters = adapterAllocations.reduce((sum, a) => sum + a.totalAssets, 0n);\n  const totalAllocated = (idleAssets as bigint) + totalInAdapters;\n\n  // Calculate percentages\n  const idleAllocation: AllocationDestination = {\n    type: \"Idle\",\n    allocatedAssets: idleAssets as bigint,\n    percentage: totalAllocated > 0n ? Number(((idleAssets as bigint) * 10000n) / totalAllocated) / 100 : 0,\n  };\n\n  // Update percentages for all adapter destinations\n  for (const adapter of adapterAllocations) {\n    for (const destination of adapter.destinations) {\n      destination.percentage =\n        totalAllocated > 0n ? Number((destination.allocatedAssets * 10000n) / totalAllocated) / 100 : 0;\n    }\n  }\n\n  return {\n    idle: idleAllocation,\n    adapters: adapterAllocations,\n    totalAllocated,\n  };\n}\n\n/**\n * Displays the vault's allocations in a formatted table, including idle assets and adapter destinations.\n */\nexport async function displayAllocations(client: PublicClient, vaultAddress: Address, allocations: VaultV2Allocations): Promise<void> {\n  const underlyingAssetAddress = await client.readContract({address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"asset\"});\n  const underlyingAssetDecimals = await client.readContract({address: underlyingAssetAddress, abi: MINIMAL_ERC20_ABI, functionName: \"decimals\"});\n\n  console.log(\"\\n✅ --- Morpho Vault V2 Allocations --- ✅\");\n  console.log(`\\nVault Address: ${vaultAddress}`);\n  console.log(`Total Allocated: ${formatUnits(allocations.totalAllocated, underlyingAssetDecimals)}`);\n  console.log(\"--------------------------------------------------------------------------------------------------\");\n\n  // Display idle assets\n  console.log(\"\\n🏦 Idle Assets:\");\n  console.log(\"--------------------------------------------------------------------------------------------------\");\n  const formattedIdle = formatUnits(allocations.idle.allocatedAssets, underlyingAssetDecimals);\n  console.log(\n    `Idle (in vault)`.padEnd(68),\n    `${parseFloat(formattedIdle).toLocaleString('en-US', {maximumFractionDigits: 2}).padStart(20)}`,\n    `${allocations.idle.percentage.toFixed(2).padStart(10)}%`\n  );\n\n  // Display adapter allocations\n  if (allocations.adapters.length === 0) {\n    console.log(\"\\n📦 Adapters: No adapters configured for this vault.\");\n  } else {\n    console.log(`\\n📦 Adapters (${allocations.adapters.length}):`);\n\n    for (const adapter of allocations.adapters) {\n      console.log(\"--------------------------------------------------------------------------------------------------\");\n      console.log(`\\nAdapter: ${adapter.adapterAddress}`);\n      console.log(`Type: ${adapter.adapterType}`);\n      console.log(`Total in Adapter: ${formatUnits(adapter.totalAssets, underlyingAssetDecimals)}`);\n\n      if (adapter.destinations.length === 0) {\n        console.log(\"  No allocations in this adapter.\");\n      } else {\n        console.log(\"\\n  Destinations:\");\n        console.log(\"  \" + \"-\".repeat(94));\n        console.log(\"  \" + \"Destination\".padEnd(68), \"Allocation\".padEnd(20), \"Percentage\");\n        console.log(\"  \" + \"-\".repeat(94));\n\n        for (const dest of adapter.destinations) {\n          const formattedAssets = formatUnits(dest.allocatedAssets, underlyingAssetDecimals);\n          let destinationLabel = \"\";\n\n          if (dest.type === \"Market\") {\n            destinationLabel = `Market: ${dest.id}`;\n          } else if (dest.type === \"Vault\") {\n            destinationLabel = `Vault: ${dest.address}`;\n          }\n\n          console.log(\n            `  ${destinationLabel.padEnd(68)}`,\n            `${parseFloat(formattedAssets).toLocaleString('en-US', {maximumFractionDigits: 2}).padStart(20)}`,\n            `${dest.percentage.toFixed(2).padStart(10)}%`\n          );\n        }\n      }\n    }\n  }\n\n  console.log(\"--------------------------------------------------------------------------------------------------\");\n}\n\n/**\n * Main function to run the script.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    const allocations = await getVaultV2Allocations(client, VAULT_V2_ADDRESS);\n    await displayAllocations(client, VAULT_V2_ADDRESS, allocations);\n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFound 1 adapter(s). Fetching allocations...\n\n✅ --- Morpho Vault V2 Allocations --- ✅\n\nVault Address: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\nTotal Allocated: 380947.871852\n--------------------------------------------------------------------------------------------------\n\n🏦 Idle Assets:\n--------------------------------------------------------------------------------------------------\nIdle (in vault)                                                                         0       0.00%\n\n📦 Adapters (1):\n--------------------------------------------------------------------------------------------------\n\nAdapter: 0x0c2D17F72965944e7755C992E052b725Ab5AA5Ea\nType: MorphoVaultV1Adapter\nTotal in Adapter: 380947.871852\n\n  Destinations:\n  ----------------------------------------------------------------------------------------------\n  Destination                                                          Allocation           Percentage\n  ----------------------------------------------------------------------------------------------\n  Vault: 0x6C26793c7F1e2785c09b460676e797b716f0Bc8E                              380,947.87     100.00%\n--------------------------------------------------------------------------------------------------\n```\n\n{\" \"}\n\n#### Morpho Vaults V1\n\n**Morpho Vaults V1** allocate exclusively to Morpho Markets V1. The vault uses two queues to manage capital flow:\n- **Supply Queue**: Determines the order markets receive new deposits\n- **Withdraw Queue**: Determines the order markets are tapped for withdrawals\n\nThe Morpho Vaults V1 allocations fall here into markets existing in those queues.\n\n```graphql [Unique Vault]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    state {\n      allocation {\n        market {\n          uniqueKey\n          loanAsset {\n            name\n          }\n          collateralAsset {\n            name\n          }\n          oracleAddress\n          irmAddress\n          lltv\n        }\n        supplyCap\n        supplyAssets\n        supplyAssetsUsd\n      }\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      state {\n        allocation {\n          market {\n            uniqueKey\n            loanAsset {\n              name\n            }\n            collateralAsset {\n              name\n            }\n            oracleAddress\n            irmAddress\n            lltv\n          }\n          supplyCap\n          supplyAssets\n          supplyAssetsUsd\n        }\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates how to:\n- Fetch the vault's withdrawal queue and iterate through all markets\n- Calculate real-time market states with proper interest accrual\n- Determine asset allocation amounts and percentages across markets\n- Display formatted allocation results with proper decimal handling\n- Use multicall for efficient batch operations to retrieve market data\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, { retryCount: 2 }),\n  });\n}\n\nconst VAULT_ADDRESS: Address = \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\";\nconst MORPHO_BLUE_ADDRESS: Address =\n  \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// Minimal ABIs with only the functions we need for this script.\nconst METAMORPHO_ABI = parseAbi([\n  \"function withdrawQueue(uint256) external view returns (bytes32)\",\n  \"function withdrawQueueLength() external view returns (uint256)\",\n  \"function asset() external view returns (address)\",\n]);\n\nconst MORPHO_BLUE_ABI = parseAbi([\n  \"function market(bytes32 id) external view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)\",\n  \"function idToMarketParams(bytes32 id) external view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n  \"function position(bytes32 id, address user) external view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral)\",\n]);\n\nconst IRM_ABI = parseAbi([\n    \"function borrowRateView((address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee) market) external view returns (uint256)\",\n  ]);\n\nconst MINIMAL_ERC20_ABI = parseAbi([\n    \"function decimals() view returns (uint8)\",\n]);\n\ntype MarketParams = {\n  loanToken: Address;\n  collateralToken: Address;\n  oracle: Address;\n  irm: Address;\n  lltv: bigint;\n};\n\ntype MarketState = {\n  totalSupplyAssets: bigint;\n  totalSupplyShares: bigint;\n  totalBorrowAssets: bigint;\n  totalBorrowShares: bigint;\n  lastUpdate: bigint;\n  fee: bigint;\n};\n\ninterface MarketAllocationInfo {\n  marketId: `0x${string}`;\n  allocatedAssets: bigint;\n  percentage: number;\n}\n\nconst WAD = 10n ** 18n;\nconst VIRTUAL_ASSETS = 1n; // To avoid division by zero\nconst VIRTUAL_SHARES = 10n ** 6n; // To avoid division by zero\n\nconst wMulDown = (x: bigint, y: bigint): bigint => (x * y) / WAD;\nconst wTaylorCompounded = (x: bigint, n: bigint): bigint => {\n  const firstTerm = x * n;\n  const secondTerm = (firstTerm * firstTerm) / (2n * WAD);\n  const thirdTerm = (secondTerm * firstTerm) / (3n * WAD);\n  return firstTerm + secondTerm + thirdTerm;\n};\n\n/** Converts a share amount to its corresponding asset amount, rounding down. */\nconst toAssetsDown = (shares: bigint, totalAssets: bigint, totalShares: bigint): bigint => {\n  if (totalShares === 0n) return shares;\n  return (shares * (totalAssets + VIRTUAL_ASSETS)) / (totalShares + VIRTUAL_SHARES);\n};\n\n/** Accrues interest on a market from its last update time to the current block's timestamp. */\nfunction accrueInterests(marketState: MarketState, borrowRate: bigint, blockTimestamp: bigint): MarketState {\n  const elapsed = blockTimestamp - marketState.lastUpdate;\n  if (elapsed === 0n || marketState.totalBorrowAssets === 0n) return marketState;\n  const interest = wMulDown(marketState.totalBorrowAssets, wTaylorCompounded(borrowRate, elapsed));\n  return { ...marketState, totalSupplyAssets: marketState.totalSupplyAssets + interest, totalBorrowAssets: marketState.totalBorrowAssets + interest };\n}\n\n/** Fetches the real-time state of a market after accruing interest. */\nasync function getCurrentMarketState(client: PublicClient, marketId: `0x${string}`, blockTimestamp: bigint): Promise<MarketState> {\n    const [marketStateResult, marketParamsResult] = await client.multicall({\n        contracts: [\n          { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"market\", args: [marketId] },\n          { address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"idToMarketParams\", args: [marketId] },\n        ],\n        allowFailure: false,\n      });\n\n  const staleMarketState: MarketState = {\n    totalSupplyAssets: marketStateResult[0], totalSupplyShares: marketStateResult[1],\n    totalBorrowAssets: marketStateResult[2], totalBorrowShares: marketStateResult[3],\n    lastUpdate: marketStateResult[4], fee: marketStateResult[5],\n  };\n\n  const params: MarketParams = {\n    loanToken: marketParamsResult[0], collateralToken: marketParamsResult[1],\n    oracle: marketParamsResult[2], irm: marketParamsResult[3], lltv: marketParamsResult[4],\n  };\n\n  if (params.irm === \"0x0000000000000000000000000000000000000000\") {\n    return staleMarketState; // No IRM, no interest to accrue.\n  }\n\n  const borrowRate = await client.readContract({\n    address: params.irm, abi: IRM_ABI, functionName: \"borrowRateView\", args: [params, staleMarketState],\n  }) as bigint;\n  \n  return accrueInterests(staleMarketState, borrowRate, blockTimestamp);\n}\n\n/**\n * Calculates the vault's asset allocation across all markets in its withdraw queue.\n * @returns An array of MarketAllocationInfo objects.\n */\nexport async function getVaultAllocations(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<MarketAllocationInfo[]> {\n  const queueLength = await client.readContract({ address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"withdrawQueueLength\" }) as bigint;\n  if (queueLength === 0n) {\n    console.log(\"Vault has no markets in its withdraw queue.\");\n    return [];\n  }\n\n  const calls = Array.from({ length: Number(queueLength) }, (_, i) => ({\n    address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"withdrawQueue\" as const, args: [BigInt(i)],\n  }));\n  const marketIds = (await client.multicall({ contracts: calls, allowFailure: false })) as `0x${string}`[];\n  \n  console.log(`Found ${marketIds.length} market(s). Fetching allocations...`);\n  const block = await client.getBlock({ blockTag: \"latest\" });\n\n  const marketDataPromises = marketIds.map(async (marketId) => {\n    const [marketState, { 0: supplyShares }] = await Promise.all([\n      getCurrentMarketState(client, marketId, block.timestamp),\n      client.readContract({ address: MORPHO_BLUE_ADDRESS, abi: MORPHO_BLUE_ABI, functionName: \"position\", args: [marketId, vaultAddress] }),\n    ]);\n    const allocatedAssets = toAssetsDown(supplyShares as bigint, marketState.totalSupplyAssets, marketState.totalSupplyShares);\n    return { marketId, allocatedAssets };\n  });\n\n  const allocations = await Promise.all(marketDataPromises);\n\n  const totalAllocatedAssets = allocations.reduce((sum, { allocatedAssets }) => sum + allocatedAssets, 0n);\n\n  if (totalAllocatedAssets === 0n) {\n    console.log(\"Vault has zero total allocation across all markets.\");\n    return allocations.map(a => ({ ...a, percentage: 0 }));\n  }\n\n  return allocations.map(({ marketId, allocatedAssets }) => ({\n    marketId,\n    allocatedAssets,\n    percentage: Number((allocatedAssets * 10000n) / totalAllocatedAssets) / 100, // For percentage with 2 decimals\n  }));\n}\n\n/**\n * Displays the vault's market allocations in a formatted table.\n */\nexport async function displayAllocations(client: PublicClient, vaultAddress: Address, allocations: MarketAllocationInfo[]): Promise<void> {\n  if (allocations.length === 0) {\n    console.log(\"No market allocations to display.\");\n    return;\n  }\n  const underlyingAssetAddress = await client.readContract({address: vaultAddress, abi:METAMORPHO_ABI, functionName: \"asset\"});\n  const underlyingAssetDecimals = await client.readContract({address: underlyingAssetAddress, abi:MINIMAL_ERC20_ABI, functionName: \"decimals\"});\n\n  console.log(\"\\n✅ --- Morpho Vault Market Allocations --- ✅\");\n  console.log(`\\nVault Address: ${vaultAddress}`);\n  console.log(\"--------------------------------------------------------------------------------------------------\");\n  console.log(\"Market ID\".padEnd(68), \"Allocation\".padEnd(20), \"Percentage\");\n  console.log(\"--------------------------------------------------------------------------------------------------\");\n  \n  allocations.forEach(({ marketId, allocatedAssets, percentage }) => {\n    const formattedAssets = formatUnits(allocatedAssets, underlyingAssetDecimals);\n    console.log(\n      `${marketId}`,\n      `${parseFloat(formattedAssets).toLocaleString('en-US', {maximumFractionDigits: 2}).padStart(20)}`,\n      `${percentage.toFixed(2).padStart(10)}%`\n    );\n  });\n  console.log(\"--------------------------------------------------------------------------------------------------\");\n}\n\n/**\n * Main function to run the script.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    const allocations = await getVaultAllocations(client, VAULT_ADDRESS);\n    await displayAllocations(client, VAULT_ADDRESS, allocations);\n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFound 4 market(s). Fetching allocations...\n\n✅ --- Morpho Vault Market Allocations --- ✅\n\nVault Address: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\n--------------------------------------------------------------------------------------------------\nMarket ID                                                            Allocation           Percentage\n--------------------------------------------------------------------------------------------------\n0x54efdee08e272e929034a8f26f7ca34b1ebe364b275391169b28c6d7db24dbc8                    0       0.00%\n0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64       110,890,214.88      67.28%\n0x3a85e619751152991742810df6ec69ce473daef99e28a64ab2340d7b7ccfee49         48,440,342.6      29.39%\n0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc         5,467,834.41       3.31%\n--------------------------------------------------------------------------------------------------\n```\n\n{\" \"}\n\n### Vault Queues\n\n**Morpho Vaults V1** allocate exclusively to Morpho Markets V1. The vault uses two queues to manage capital flow:\n- **Supply Queue**: Determines the order markets receive new deposits\n- **Withdraw Queue**: Determines the order markets are tapped for withdrawals\n\nThe Morpho Vaults V1 allocations fall here into markets existing in those queues.\n\n```graphql [Unique Vault]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    state {\n      totalAssets\n      lastTotalAssets\n      allocation {\n        supplyQueueIndex\n        withdrawQueueIndex\n        market {\n          uniqueKey\n        }\n      }\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      state {\n        totalAssets\n        lastTotalAssets\n        allocation {\n          supplyQueueIndex\n          withdrawQueueIndex\n          market {\n            uniqueKey\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates how to retrieve and display vault queue information including:\n- Supply queue: Markets where the vault can supply liquidity (ordered by priority)\n- Withdraw queue: Markets from which the vault withdraws liquidity during redemptions (ordered by priority)\n- Market details including loan/collateral tokens, LLTV, oracle, and IRM addresses\n- Queue positions and summary statistics\n- Efficient multicall operations to fetch all market data\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// The address of the Steakhouse USDC MetaMorpho Vault\nconst VAULT_ADDRESS: Address = \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\";\n\n// Morpho V1 contract address\nconst MORPHO_BLUE_ADDRESS: Address = \"0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\";\n\n// MetaMorpho ABI for queue operations\nconst METAMORPHO_ABI = parseAbi([\n  \"function supplyQueueLength() view returns (uint256)\",\n  \"function withdrawQueueLength() view returns (uint256)\",\n  \"function supplyQueue(uint256 index) view returns (bytes32)\",\n  \"function withdrawQueue(uint256 index) view returns (bytes32)\",\n  \"function asset() view returns (address)\",\n]);\n\n// Morpho V1 ABI for market parameters\nconst MORPHO_BLUE_ABI = parseAbi([\n  \"function idToMarketParams(bytes32 id) view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)\",\n]);\n\n// ERC20 ABI for token information\nconst ERC20_ABI = parseAbi([\n  \"function symbol() view returns (string)\",\n  \"function name() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n]);\n\ninterface MarketInfo {\n  id: `0x${string}`;\n  loanToken: {\n    address: Address;\n    symbol: string;\n    name: string;\n  };\n  collateralToken: {\n    address: Address;\n    symbol: string;\n    name: string;\n  };\n  oracle: Address;\n  irm: Address;\n  lltv: bigint;\n  lltvPercentage: number;\n}\n\ninterface VaultQueues {\n  vaultAddress: Address;\n  vaultAsset: {\n    address: Address;\n    symbol: string;\n  };\n  supplyQueue: {\n    length: number;\n    markets: MarketInfo[];\n  };\n  withdrawQueue: {\n    length: number;\n    markets: MarketInfo[];\n  };\n}\n\n/**\n * Converts LLTV from WAD format to percentage\n */\nfunction formatLLTV(lltv: bigint): number {\n  return Number(formatUnits(lltv, 18)) * 100;\n}\n\n/**\n * Fetches token information for a given address\n */\nasync function getTokenInfo(\n  client: PublicClient,\n  tokenAddress: Address\n): Promise<{ address: Address; symbol: string; name: string }> {\n  try {\n    const [symbol, name] = await client.multicall({\n      contracts: [\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n        { address: tokenAddress, abi: ERC20_ABI, functionName: \"name\" },\n      ],\n      allowFailure: false,\n    });\n\n    return {\n      address: tokenAddress,\n      symbol,\n      name,\n    };\n  } catch (error) {\n    // If token info fails, return address as fallback\n    return {\n      address: tokenAddress,\n      symbol: `Token(${tokenAddress.slice(0, 6)}...)`,\n      name: `Unknown Token ${tokenAddress.slice(0, 6)}...`,\n    };\n  }\n}\n\n/**\n * Fetches market information for a given market ID\n */\nasync function getMarketInfo(\n  client: PublicClient,\n  marketId: `0x${string}`\n): Promise<MarketInfo> {\n  // Get market parameters from Morpho V1\n  const [loanToken, collateralToken, oracle, irm, lltv] = await client.readContract({\n    address: MORPHO_BLUE_ADDRESS,\n    abi: MORPHO_BLUE_ABI,\n    functionName: \"idToMarketParams\",\n    args: [marketId],\n  }) as [Address, Address, Address, Address, bigint];\n\n  // Fetch token information for both loan and collateral tokens\n  const [loanTokenInfo, collateralTokenInfo] = await Promise.all([\n    getTokenInfo(client, loanToken),\n    getTokenInfo(client, collateralToken),\n  ]);\n\n  return {\n    id: marketId,\n    loanToken: loanTokenInfo,\n    collateralToken: collateralTokenInfo,\n    oracle,\n    irm,\n    lltv,\n    lltvPercentage: formatLLTV(lltv),\n  };\n}\n\n/**\n * Retrieves both supply and withdraw queues for a MetaMorpho vault.\n * @param client The Viem public client.\n * @param vaultAddress The address of the MetaMorpho vault.\n * @returns A promise that resolves to a VaultQueues object.\n */\nexport async function getVaultQueues(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<VaultQueues> {\n  console.log(`Fetching queue information for vault: ${vaultAddress}...`);\n\n  // Get queue lengths and vault asset\n  const [supplyQueueLength, withdrawQueueLength, vaultAsset] = await client.multicall({\n    contracts: [\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"supplyQueueLength\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"withdrawQueueLength\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"asset\" },\n    ],\n    allowFailure: false,\n  });\n\n  console.log(`Supply queue length: ${supplyQueueLength}, Withdraw queue length: ${withdrawQueueLength}`);\n\n  // Get vault asset information\n  const vaultAssetInfo = await getTokenInfo(client, vaultAsset);\n\n  // Fetch supply queue market IDs\n  const supplyQueueCalls = Array.from({ length: Number(supplyQueueLength) }, (_, i) => ({\n    address: vaultAddress,\n    abi: METAMORPHO_ABI,\n    functionName: \"supplyQueue\" as const,\n    args: [BigInt(i)],\n  }));\n\n  // Fetch withdraw queue market IDs\n  const withdrawQueueCalls = Array.from({ length: Number(withdrawQueueLength) }, (_, i) => ({\n    address: vaultAddress,\n    abi: METAMORPHO_ABI,\n    functionName: \"withdrawQueue\" as const,\n    args: [BigInt(i)],\n  }));\n\n  // Execute multicalls to get market IDs\n  const [supplyQueueIds, withdrawQueueIds] = await Promise.all([\n    supplyQueueLength > 0n ? client.multicall({ contracts: supplyQueueCalls, allowFailure: false }) : [],\n    withdrawQueueLength > 0n ? client.multicall({ contracts: withdrawQueueCalls, allowFailure: false }) : [],\n  ]);\n\n  // Get unique market IDs to avoid duplicate API calls\n  const allMarketIds = new Set([\n    ...(supplyQueueIds as `0x${string}`[]),\n    ...(withdrawQueueIds as `0x${string}`[]),\n  ]);\n\n  console.log(`Fetching market details for ${allMarketIds.size} unique markets...`);\n\n  const marketInfoPromises = Array.from(allMarketIds).map((marketId) =>\n    getMarketInfo(client, marketId)\n  );\n\n  const marketInfos = await Promise.all(marketInfoPromises);\n  const marketInfoMap = new Map(marketInfos.map((info) => [info.id, info]));\n\n  // Build supply and withdraw queues with market information\n  const supplyQueue = {\n    length: Number(supplyQueueLength),\n    markets: (supplyQueueIds as `0x${string}`[]).map((id) => marketInfoMap.get(id)!),\n  };\n\n  const withdrawQueue = {\n    length: Number(withdrawQueueLength),\n    markets: (withdrawQueueIds as `0x${string}`[]).map((id) => marketInfoMap.get(id)!),\n  };\n\n  return {\n    vaultAddress,\n    vaultAsset: {\n      address: vaultAssetInfo.address,\n      symbol: vaultAssetInfo.symbol,\n    },\n    supplyQueue,\n    withdrawQueue,\n  };\n}\n\n/**\n * Displays market information in a formatted table row.\n */\nfunction displayMarketRow(market: MarketInfo, index: number): void {\n  const shortId = `${market.id.slice(0, 8)}...${market.id.slice(-8)}`;\n  const loanTokenDisplay = `${market.loanToken.symbol}`;\n  const collateralTokenDisplay = `${market.collateralToken.symbol}`;\n  const lltvDisplay = `${market.lltvPercentage.toFixed(2)}%`;\n\n  console.log(\n    `${(index + 1).toString().padStart(3)} | ` +\n    `${shortId.padEnd(20)} | ` +\n    `${loanTokenDisplay.padEnd(12)} | ` +\n    `${collateralTokenDisplay.padEnd(15)} | ` +\n    `${lltvDisplay.padStart(8)}`\n  );\n}\n\n/**\n * Displays the vault queues in a formatted manner.\n */\nexport function displayVaultQueues(queues: VaultQueues): void {\n  console.log(\"\\n✅ --- Morpho Vault Queues --- ✅\");\n  console.log(`\\nVault: ${queues.vaultAddress}`);\n  console.log(`Asset: ${queues.vaultAsset.symbol} (${queues.vaultAsset.address})`);\n\n  // Display Supply Queue\n  console.log(`\\n--- Supply Queue (${queues.supplyQueue.length} markets) ---`);\n  if (queues.supplyQueue.length === 0) {\n    console.log(\"No markets in supply queue\");\n  } else {\n    console.log(\"Pos | Market ID            | Loan Token   | Collateral Token | LLTV\");\n    console.log(\"----+----------------------+--------------+------------------+---------\");\n    queues.supplyQueue.markets.forEach((market, index) => {\n      displayMarketRow(market, index);\n    });\n  }\n\n  // Display Withdraw Queue\n  console.log(`\\n--- Withdraw Queue (${queues.withdrawQueue.length} markets) ---`);\n  if (queues.withdrawQueue.length === 0) {\n    console.log(\"No markets in withdraw queue\");\n  } else {\n    console.log(\"Pos | Market ID            | Loan Token   | Collateral Token | LLTV\");\n    console.log(\"----+----------------------+--------------+------------------+---------\");\n    queues.withdrawQueue.markets.forEach((market, index) => {\n      displayMarketRow(market, index);\n    });\n  }\n\n  console.log(\"\\n--- Queue Summary ---\");\n  console.log(`Total Supply Queue Length: ${queues.supplyQueue.length}`);\n  console.log(`Total Withdraw Queue Length: ${queues.withdrawQueue.length}`);\n  \n  // Check for markets in both queues\n  const supplyMarketIds = new Set(queues.supplyQueue.markets.map(m => m.id));\n  const withdrawMarketIds = new Set(queues.withdrawQueue.markets.map(m => m.id));\n  const commonMarkets = queues.withdrawQueue.markets.filter(m => supplyMarketIds.has(m.id));\n  \n  if (commonMarkets.length > 0) {\n    console.log(`Markets in both queues: ${commonMarkets.length}`);\n  }\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Displays detailed market information.\n */\nexport function displayMarketDetails(queues: VaultQueues): void {\n  const allMarkets = new Map<string, MarketInfo>();\n  \n  // Collect all unique markets\n  [...queues.supplyQueue.markets, ...queues.withdrawQueue.markets].forEach(market => {\n    allMarkets.set(market.id, market);\n  });\n\n  if (allMarkets.size === 0) {\n    console.log(\"\\nNo markets to display details for.\");\n    return;\n  }\n\n  console.log(\"\\n--- Market Details ---\");\n  Array.from(allMarkets.values()).forEach((market, index) => {\n    console.log(`\\n${index + 1}. Market ${market.id}`);\n    console.log(`   Loan Token: ${market.loanToken.name} (${market.loanToken.symbol})`);\n    console.log(`   Collateral: ${market.collateralToken.name} (${market.collateralToken.symbol})`);\n    console.log(`   LLTV: ${market.lltvPercentage.toFixed(2)}%`);\n    console.log(`   Oracle: ${market.oracle}`);\n    console.log(`   IRM: ${market.irm}`);\n  });\n}\n\n/**\n * Main function to run the script.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    \n    // Get vault queues\n    const queues = await getVaultQueues(client, VAULT_ADDRESS);\n    \n    // Display results\n    displayVaultQueues(queues);\n    \n    // Optionally display detailed market information\n    // displayMarketDetails(queues);\n    \n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFetching queue information for vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB...\nSupply queue length: 4, Withdraw queue length: 4\nFetching market details for 4 unique markets...\n\n--- Morpho Vault Queues ---\n\nVault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\nAsset: USDC (0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)\n\n--- Supply Queue (4 markets) ---\nPos | Market ID            | Loan Token   | Collateral Token | LLTV\n----+----------------------+--------------+------------------+---------\n  1 | 0x64d65c...883fcc64  | USDC         | cbBTC           |   86.00%\n  2 | 0x3a85e6...7ccfee49  | USDC         | WBTC            |   86.00%\n  3 | 0xb32349...acbc86cc  | USDC         | wstETH          |   86.00%\n  4 | 0x54efde...db24dbc8  | USDC         | Token(0x0000...) |    0.00%\n\n--- Withdraw Queue (4 markets) ---\nPos | Market ID            | Loan Token   | Collateral Token | LLTV\n----+----------------------+--------------+------------------+---------\n  1 | 0x54efde...db24dbc8  | USDC         | Token(0x0000...) |    0.00%\n  2 | 0x64d65c...883fcc64  | USDC         | cbBTC           |   86.00%\n  3 | 0x3a85e6...7ccfee49  | USDC         | WBTC            |   86.00%\n  4 | 0xb32349...acbc86cc  | USDC         | wstETH          |   86.00%\n\n--- Queue Summary ---\nTotal Supply Queue Length: 4\nTotal Withdraw Queue Length: 4\nMarkets in both queues: 4\n\n----------------------------------------\n```\n\n{\" \"}\n\n```solidity\n// Get queue lengths\nuint256 supplyQueueLength = IMetaMorpho(vault).supplyQueueLength();\nuint256 withdrawQueueLength = IMetaMorpho(vault).withdrawQueueLength();\n\n// Fetch supply queue markets\nbytes32[] memory supplyQueueIds = new bytes32[](supplyQueueLength);\nfor (uint256 i = 0; i < supplyQueueLength; i++) {\n    supplyQueueIds[i] = IMetaMorpho(vault).supplyQueue(i);\n}\n\n// Fetch withdraw queue markets\nbytes32[] memory withdrawQueueIds = new bytes32[](withdrawQueueLength);\nfor (uint256 i = 0; i < withdrawQueueLength; i++) {\n    withdrawQueueIds[i] = IMetaMorpho(vault).withdrawQueue(i);\n}\n\n// Get market parameters for each market ID\nfor (uint256 i = 0; i < supplyQueueIds.length; i++) {\n    (\n        address loanToken,\n        address collateralToken,\n        address oracle,\n        address irm,\n        uint256 lltv\n    ) = IMorpho(morpho).idToMarketParams(supplyQueueIds[i]);\n\n    // Process market information...\n}\n```\n\n**Key Functions:**\n- **Queue Lengths**: `supplyQueueLength()`, `withdrawQueueLength()`\n- **Queue Access**: `supplyQueue(index)`, `withdrawQueue(index)`\n- **Market Details**: `IMorpho.idToMarketParams(marketId)` returns market configuration\n\n**Queue Behavior:**\n- **Supply Queue**: Ordered by priority for new liquidity allocation\n- **Withdraw Queue**: Ordered by priority for liquidity withdrawal during redemptions\n- **Position Matters**: Lower index = higher priority in queue operations\n- **Market IDs**: Each queue contains bytes32 market identifiers\n\n**Important Notes:**\n- Markets can appear in both queues with different positions\n- Empty queues return length 0, accessing invalid indices will revert\n- Market parameters are retrieved from the main Morpho V1 contract\n\n## Configuration & Governance\n\n### Vault Parameters\n\n#### Morpho Vaults V2\n\n```graphql [Unique Vault]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    address\n    name\n    listed\n    metadata {\n      description\n      forumLink\n      image\n    }\n    allocators {\n      allocator {\n        address\n      }\n    }\n    owner {\n      address\n    }\n    curators {\n      items {\n        addresses {\n          address\n        }\n      }\n    }\n    sentinels {\n      sentinel {\n        address\n      }\n    }\n    timelocks {\n      duration\n      selector\n      functionName\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      address\n      name\n      listed\n      metadata {\n        description\n        forumLink\n        image\n      }\n      allocators {\n        allocator {\n          address\n        }\n      }\n      owner {\n        address\n      }\n      curators {\n        items {\n          addresses {\n            address\n          }\n        }\n      }\n      sentinels {\n        sentinel {\n          address\n        }\n      }\n      timelocks {\n        duration\n        selector\n        functionName\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates how to retrieve comprehensive Vault V2 configuration including:\n- Basic vault information (name, symbol, decimals)\n- Asset details and financial metrics (totalAssets, totalSupply, fees)\n- Governance roles (owner, curator)\n- Adapter configuration (adaptersLength, adapters, adapterRegistry, liquidityAdapter)\n- Vault gates (receiveAssetsGate, sendSharesGate, receiveSharesGate)\n- Timelock settings for all critical functions (addAdapter, removeAdapter, setAdapterRegistry, etc.)\n- Abdication status for each function\n- Max rate and fee configuration\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// The address of the Morpho Vault V2\nconst VAULT_V2_ADDRESS: Address = \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\";\n\n// Morpho Vault V2 ABI for configuration retrieval\nconst VAULT_V2_ABI = parseAbi([\n  \"function name() view returns (string)\",\n  \"function symbol() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n  \"function asset() view returns (address)\",\n  \"function totalAssets() view returns (uint256)\",\n  \"function totalSupply() view returns (uint256)\",\n  \"function owner() view returns (address)\",\n  \"function curator() view returns (address)\",\n  \"function adaptersLength() view returns (uint256)\",\n  \"function adapters(uint256) view returns (address)\",\n  \"function adapterRegistry() view returns (address)\",\n  \"function liquidityAdapter() view returns (address)\",\n  \"function timelock(bytes4) view returns (uint256)\",\n  \"function abdicated(bytes4) view returns (bool)\",\n  \"function receiveAssetsGate() view returns (address)\",\n  \"function sendSharesGate() view returns (address)\",\n  \"function receiveSharesGate() view returns (address)\",\n  \"function maxRate() view returns (uint256)\",\n  \"function performanceFee() view returns (uint256)\",\n  \"function managementFee() view returns (uint256)\",\n]);\n\nconst ERC20_ABI = parseAbi([\n  \"function name() view returns (string)\",\n  \"function symbol() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n]);\n\n// Function selectors for timelock queries\nconst FUNCTION_SELECTORS = {\n  setReceiveAssetsGate: \"0x04dbf0ce\",\n  addAdapter: \"0x60d54d41\",\n  increaseRelativeCap: \"0x2438525b\",\n  setReceiveSharesGate: \"0x2cb19f98\",\n  setForceDeallocatePenalty: \"0x3e9d2ac7\",\n  increaseTimelock: \"0x47966291\",\n  removeAdapter: \"0x585cd34b\",\n  setSendSharesGate: \"0xc21ad028\",\n  increaseAbsoluteCap: \"0xf6f98fd5\",\n  setAdapterRegistry: \"0x5b34b823\",\n} as const;\n\nconst FUNCTION_NAMES: Record<string, string> = {\n  \"0x04dbf0ce\": \"setReceiveAssetsGate\",\n  \"0x60d54d41\": \"addAdapter\",\n  \"0x2438525b\": \"increaseRelativeCap\",\n  \"0x2cb19f98\": \"setReceiveSharesGate\",\n  \"0x3e9d2ac7\": \"setForceDeallocatePenalty\",\n  \"0x47966291\": \"increaseTimelock\",\n  \"0x585cd34b\": \"removeAdapter\",\n  \"0xc21ad028\": \"setSendSharesGate\",\n  \"0xf6f98fd5\": \"increaseAbsoluteCap\",\n  \"0x5b34b823\": \"setAdapterRegistry\",\n};\n\ninterface TimelockInfo {\n  selector: string;\n  functionName: string;\n  duration: number;\n  isAbdicated: boolean;\n}\n\ninterface VaultV2Configuration {\n  // Basic Info\n  address: Address;\n  name: string;\n  symbol: string;\n  decimals: number;\n\n  // Asset Info\n  asset: {\n    address: Address;\n    name: string;\n    symbol: string;\n    decimals: number;\n  };\n\n  // Financial Info\n  totalAssets: bigint;\n  totalSupply: bigint;\n  performanceFee: number; // As percentage\n  managementFee: number; // As percentage\n  maxRate: bigint;\n\n  // Governance\n  owner: Address;\n  curator: Address;\n\n  // Adapters\n  adaptersLength: number;\n  adapters: Address[];\n  adapterRegistry: Address;\n  liquidityAdapter: Address;\n\n  // Gates\n  receiveAssetsGate: Address;\n  sendSharesGate: Address;\n  receiveSharesGate: Address;\n\n  // Timelocks\n  timelocks: TimelockInfo[];\n}\n\n/**\n * Helper function to handle zero address cases\n */\nfunction handleZeroAddress(address: Address): string {\n  return address === \"0x0000000000000000000000000000000000000000\"\n    ? \"Not set (0x0)\"\n    : address;\n}\n\n/**\n * Helper function to format timelock duration\n */\nfunction formatTimelock(seconds: number): string {\n  if (seconds === 0) return \"0s (No timelock)\";\n  const days = Math.floor(seconds / 86400);\n  const hours = Math.floor((seconds % 86400) / 3600);\n  const minutes = Math.floor((seconds % 3600) / 60);\n\n  if (days > 0) return `${days}d ${hours}h ${minutes}m`;\n  if (hours > 0) return `${hours}h ${minutes}m`;\n  if (minutes > 0) return `${minutes}m`;\n  return `${seconds}s`;\n}\n\n/**\n * Retrieves comprehensive Vault V2 configuration information.\n * @param client The Viem public client.\n * @param vaultAddress The address of the Morpho Vault V2.\n * @returns A promise that resolves to a VaultV2Configuration object.\n */\nexport async function getVaultV2Configuration(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<VaultV2Configuration> {\n  console.log(`Fetching configuration for Vault V2: ${vaultAddress}...`);\n\n  // First multicall to get basic vault information\n  const [\n    name,\n    symbol,\n    decimals,\n    assetAddress,\n    totalAssets,\n    totalSupply,\n    owner,\n    curator,\n    adaptersLength,\n    adapterRegistry,\n    liquidityAdapter,\n    receiveAssetsGate,\n    sendSharesGate,\n    receiveSharesGate,\n    maxRate,\n    performanceFee,\n    managementFee,\n  ] = await client.multicall({\n    contracts: [\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"name\" },\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"symbol\" },\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"decimals\" },\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"asset\" },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"totalAssets\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"totalSupply\",\n      },\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"owner\" },\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"curator\" },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"adaptersLength\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"adapterRegistry\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"liquidityAdapter\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"receiveAssetsGate\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"sendSharesGate\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"receiveSharesGate\",\n      },\n      { address: vaultAddress, abi: VAULT_V2_ABI, functionName: \"maxRate\" },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"performanceFee\",\n      },\n      {\n        address: vaultAddress,\n        abi: VAULT_V2_ABI,\n        functionName: \"managementFee\",\n      },\n    ],\n    allowFailure: false,\n  });\n\n  // Fetch adapter addresses\n  const adaptersLengthNum = Number(adaptersLength);\n  const adapters: Address[] = [];\n  if (adaptersLengthNum > 0) {\n    const adapterCalls = Array.from({ length: adaptersLengthNum }, (_, i) => ({\n      address: vaultAddress,\n      abi: VAULT_V2_ABI,\n      functionName: \"adapters\" as const,\n      args: [BigInt(i)],\n    }));\n    const adapterResults = await client.multicall({\n      contracts: adapterCalls,\n      allowFailure: false,\n    });\n    adapters.push(...(adapterResults as Address[]));\n  }\n\n  // Fetch asset information\n  const [assetName, assetSymbol, assetDecimals] = await client.multicall({\n    contracts: [\n      { address: assetAddress, abi: ERC20_ABI, functionName: \"name\" },\n      { address: assetAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n      { address: assetAddress, abi: ERC20_ABI, functionName: \"decimals\" },\n    ],\n    allowFailure: false,\n  });\n\n  // Fetch timelock information for all critical functions\n  const timelocks: TimelockInfo[] = [];\n  for (const [selector, functionName] of Object.entries(FUNCTION_NAMES)) {\n    const [duration, isAbdicated] = await client.multicall({\n      contracts: [\n        {\n          address: vaultAddress,\n          abi: VAULT_V2_ABI,\n          functionName: \"timelock\",\n          args: [selector as `0x${string}`],\n        },\n        {\n          address: vaultAddress,\n          abi: VAULT_V2_ABI,\n          functionName: \"abdicated\",\n          args: [selector as `0x${string}`],\n        },\n      ],\n      allowFailure: false,\n    });\n\n    timelocks.push({\n      selector,\n      functionName,\n      duration: Number(duration),\n      isAbdicated: Boolean(isAbdicated),\n    });\n  }\n\n  // Calculate fees as percentages\n  const performanceFeePercent = Number(formatUnits(performanceFee, 18)) * 100;\n  const managementFeePercent = Number(formatUnits(managementFee, 18)) * 100;\n\n  return {\n    address: vaultAddress,\n    name,\n    symbol,\n    decimals,\n    asset: {\n      address: assetAddress,\n      name: assetName,\n      symbol: assetSymbol,\n      decimals: assetDecimals,\n    },\n    totalAssets,\n    totalSupply,\n    performanceFee: performanceFeePercent,\n    managementFee: managementFeePercent,\n    maxRate,\n    owner,\n    curator,\n    adaptersLength: adaptersLengthNum,\n    adapters,\n    adapterRegistry,\n    liquidityAdapter,\n    receiveAssetsGate,\n    sendSharesGate,\n    receiveSharesGate,\n    timelocks,\n  };\n}\n\n/**\n * Displays the Vault V2 configuration in a formatted manner.\n */\nexport function displayVaultV2Configuration(\n  config: VaultV2Configuration\n): void {\n  console.log(\"\\n✅ --- Morpho Vault V2 Configuration --- ✅\");\n\n  console.log(\"\\n--- Basic Information ---\");\n  console.log(`Vault Name: ${config.name}`);\n  console.log(`Vault Symbol: ${config.symbol}`);\n  console.log(`Vault Address: ${config.address}`);\n  console.log(`Vault Decimals: ${config.decimals}`);\n\n  console.log(\"\\n--- Asset Information ---\");\n  console.log(`Asset Name: ${config.asset.name}`);\n  console.log(`Asset Symbol: ${config.asset.symbol}`);\n  console.log(`Asset Address: ${config.asset.address}`);\n  console.log(`Asset Decimals: ${config.asset.decimals}`);\n\n  console.log(\"\\n--- Financial Information ---\");\n  console.log(\n    `Total Assets: ${formatUnits(config.totalAssets, config.asset.decimals)} ${config.asset.symbol}`\n  );\n  console.log(\n    `Total Supply: ${formatUnits(config.totalSupply, config.decimals)} ${config.symbol}`\n  );\n  console.log(\n    `Performance Fee: ${config.performanceFee.toFixed(4)}% (annual)`\n  );\n  console.log(\n    `Management Fee: ${config.managementFee.toFixed(4)}% (annual)`\n  );\n\n  // Calculate and display max rate as APR\n  const maxRateNumber = Number(config.maxRate);\n  const secondsPerYear = 31557600; // 365.25 days\n  const maxRateAPR =\n    maxRateNumber > 0\n      ? ((maxRateNumber / 1e18) * secondsPerYear * 100).toFixed(2)\n      : \"0\";\n  console.log(`Max Rate: ${maxRateAPR}% APR`);\n\n  console.log(\"\\n--- Governance ---\");\n  console.log(`Owner: ${config.owner}`);\n  console.log(`Curator: ${handleZeroAddress(config.curator)}`);\n\n  console.log(\"\\n--- Adapters ---\");\n  console.log(`Adapters Length: ${config.adaptersLength}`);\n  console.log(`Adapter Registry: ${config.adapterRegistry}`);\n  console.log(`Liquidity Adapter: ${config.liquidityAdapter}`);\n  if (config.adapters.length > 0) {\n    console.log(`Configured Adapters:`);\n    config.adapters.forEach((adapter, i) => {\n      console.log(`  ${i + 1}. ${adapter}`);\n    });\n  }\n\n  console.log(\"\\n--- Vault Gates ---\");\n  console.log(\n    `Receive Assets Gate: ${handleZeroAddress(config.receiveAssetsGate)}`\n  );\n  console.log(`Send Shares Gate: ${handleZeroAddress(config.sendSharesGate)}`);\n  console.log(\n    `Receive Shares Gate: ${handleZeroAddress(config.receiveSharesGate)}`\n  );\n\n  console.log(\"\\n--- Timelocks & Abdications ---\");\n  console.log(\"Function\".padEnd(30), \"Duration\".padEnd(20), \"Abdicated\");\n  console.log(\"-\".repeat(70));\n  config.timelocks.forEach((tl) => {\n    console.log(\n      tl.functionName.padEnd(30),\n      formatTimelock(tl.duration).padEnd(20),\n      tl.isAbdicated ? \"Yes\" : \"No\"\n    );\n  });\n\n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Main function to run the script.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n\n    // Get Vault V2 configuration\n    const config = await getVaultV2Configuration(client, VAULT_V2_ADDRESS);\n    displayVaultV2Configuration(config);\n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```\nFetching configuration for Vault V2: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145...\n\n--- Morpho Vault V2 Configuration ---\n\n--- Basic Information ---\nVault Name: Keyrock USDC\nVault Symbol: kUSDC\nVault Address: 0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\nVault Decimals: 18\n\n--- Asset Information ---\nAsset Name: USD Coin\nAsset Symbol: USDC\nAsset Address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\nAsset Decimals: 6\n\n--- Financial Information ---\nTotal Assets: 380908.53096 USDC\nTotal Supply: 377706.886328436653684714 kUSDC\nPerformance Fee: 0.0000% (annual)\nManagement Fee: 0.0000% (annual)\nMax Rate: 15.01% APR\n\n--- Governance ---\nOwner: 0xbA75546ACD56b3a9142f94F179b03970eE4283Fd\nCurator: 0xbA75546ACD56b3a9142f94F179b03970eE4283Fd\n\n--- Adapters ---\nAdapters Length: 1\nAdapter Registry: 0x3696c5eAe4a7Ffd04Ea163564571E9CD8Ed9364e\nLiquidity Adapter: 0x0c2D17F72965944e7755C992E052b725Ab5AA5Ea\nConfigured Adapters:\n  1. 0x0c2D17F72965944e7755C992E052b725Ab5AA5Ea\n\n--- Vault Gates ---\nReceive Assets Gate: Not set (0x0)\nSend Shares Gate: Not set (0x0)\nReceive Shares Gate: Not set (0x0)\n\n--- Timelocks & Abdications ---\nFunction                       Duration             Abdicated\n----------------------------------------------------------------------\nsetReceiveAssetsGate           7d 0h 0m             No\naddAdapter                     3d 0h 0m             No\nincreaseRelativeCap            3d 0h 0m             No\nsetReceiveSharesGate           7d 0h 0m             No\nsetForceDeallocatePenalty      3d 0h 0m             No\nincreaseTimelock               7d 0h 0m             No\nremoveAdapter                  7d 0h 0m             No\nsetSendSharesGate              7d 0h 0m             No\nincreaseAbsoluteCap            3d 0h 0m             No\nsetAdapterRegistry             0s (No timelock)     Yes\n\n----------------------------------------\n```\n\n{\" \"}\n\n```solidity\n// Basic vault information\nstring memory vaultName = IMorphoVaultV2(vault).name();\nstring memory vaultSymbol = IMorphoVaultV2(vault).symbol();\nuint8 vaultDecimals = IMorphoVaultV2(vault).decimals();\naddress assetAddress = IMorphoVaultV2(vault).asset();\n\n// Financial metrics\nuint256 totalAssets = IMorphoVaultV2(vault).totalAssets();\nuint256 totalSupply = IMorphoVaultV2(vault).totalSupply();\nuint256 performanceFee = IMorphoVaultV2(vault).performanceFee(); // In WAD (18 decimals)\nuint256 managementFee = IMorphoVaultV2(vault).managementFee(); // In WAD (18 decimals)\nuint256 maxRate = IMorphoVaultV2(vault).maxRate(); // Max rate in WAD per second\n\n// Governance roles\naddress owner = IMorphoVaultV2(vault).owner();\naddress curator = IMorphoVaultV2(vault).curator();\n\n// Adapter configuration\nuint256 adaptersLength = IMorphoVaultV2(vault).adaptersLength();\naddress adapterRegistry = IMorphoVaultV2(vault).adapterRegistry();\naddress liquidityAdapter = IMorphoVaultV2(vault).liquidityAdapter();\n\n// Get specific adapter by index\nfor (uint256 i = 0; i < adaptersLength; i++) {\n    address adapter = IMorphoVaultV2(vault).adapters(i);\n    // Process adapter...\n}\n\n// Vault gates\naddress receiveAssetsGate = IMorphoVaultV2(vault).receiveAssetsGate();\naddress sendSharesGate = IMorphoVaultV2(vault).sendSharesGate();\naddress receiveSharesGate = IMorphoVaultV2(vault).receiveSharesGate();\n\n// Timelock and abdication for specific function\nbytes4 functionSelector = bytes4(keccak256(\"addAdapter(address,uint256,uint256)\"));\nuint256 timelockDuration = IMorphoVaultV2(vault).timelock(functionSelector);\nbool isAbdicated = IMorphoVaultV2(vault).abdicated(functionSelector);\n```\n\n**Key Functions:**\n- **Basic Info**: `name()`, `symbol()`, `decimals()`, `asset()`\n- **Financial**: `totalAssets()`, `totalSupply()`, `performanceFee()`, `managementFee()`, `maxRate()`\n- **Roles**: `owner()`, `curator()`\n- **Adapters**: `adaptersLength()`, `adapters(index)`, `adapterRegistry()`, `liquidityAdapter()`\n- **Gates**: `receiveAssetsGate()`, `sendSharesGate()`, `receiveSharesGate()`\n- **Timelocks**: `timelock(bytes4 selector)`, `abdicated(bytes4 selector)`\n\n**Important Notes:**\n- Vault V2 uses adapters for asset allocation instead of direct market queues\n- Timelocks are function-specific, identified by their 4-byte selector\n- Abdication means a function's control has been permanently given up (timelock set to infinity)\n- High-risk functions typically have 7-day timelocks, medium-risk have 3-day timelocks\n- Gates control access to deposit/withdrawal/transfer operations (address(0) means no gate)\n\n#### Morpho Vaults V1\n\n```graphql [Unique Vault]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    name\n    listed\n    metadata {\n      description\n    }\n    allocators {\n      address\n    }\n    state {\n      owner\n      curator\n      guardian\n      timelock\n      curators {\n         name\n        socials {\n          type\n          url\n          }\n        image\n      }\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      name\n      listed\n      metadata {\n        description\n      }\n      allocators {\n        address\n      }\n      state {\n        owner\n        curator\n        guardian\n        timelock\n        curators {\n          name\n          socials {\n            type\n            url\n          }\n          image\n        }\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\nThis example demonstrates how to retrieve comprehensive vault configuration including:\n- Basic vault information (name, symbol, decimals)\n- Asset details and financial metrics\n- Governance roles and permissions\n- Timelock settings and pending changes\n- Queue lengths and allocator status\n- Proper handling of zero addresses for unset roles\n\n```typescript\nimport \"dotenv/config\";\nimport {\n  createPublicClient,\n  http,\n  formatUnits,\n  PublicClient,\n  parseAbi,\n  Address,\n  formatEther,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\n/**\n * Creates and configures a Viem Public Client for the Ethereum mainnet.\n * It reads the RPC URL from the .env file.\n * @returns A configured Viem public client.\n */\nexport function createMainnetClient(): PublicClient {\n  const rpcUrl = process.env.RPC_URL_MAINNET;\n  if (!rpcUrl) {\n    throw new Error(\n      \"RPC_URL_MAINNET is not set in the .env file. Please add it.\"\n    );\n  }\n\n  return createPublicClient({\n    chain: mainnet,\n    transport: http(rpcUrl, {\n      retryCount: 2,\n      batch: {\n        batchSize: 100,\n        wait: 200,\n      },\n    }),\n    batch: {\n      multicall: {\n        batchSize: 2048,\n        wait: 100,\n      },\n    },\n  });\n}\n\n// The address of the Steakhouse USDC MetaMorpho Vault\nconst VAULT_ADDRESS: Address = \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\";\n\n// Comprehensive MetaMorpho ABI for configuration retrieval\nconst METAMORPHO_ABI = parseAbi([\n  \"function name() view returns (string)\",\n  \"function symbol() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n  \"function asset() view returns (address)\",\n  \"function totalAssets() view returns (uint256)\",\n  \"function totalSupply() view returns (uint256)\",\n  \"function owner() view returns (address)\",\n  \"function curator() view returns (address)\",\n  \"function guardian() view returns (address)\",\n  \"function feeRecipient() view returns (address)\",\n  \"function skimRecipient() view returns (address)\",\n  \"function fee() view returns (uint96)\",\n  \"function timelock() view returns (uint256)\",\n  \"function lastTotalAssets() view returns (uint256)\",\n  \"function isAllocator(address) view returns (bool)\",\n  \"function supplyQueueLength() view returns (uint256)\",\n  \"function withdrawQueueLength() view returns (uint256)\",\n  \"function supplyQueue(uint256) view returns (bytes32)\",\n  \"function withdrawQueue(uint256) view returns (bytes32)\",\n  \"function pendingTimelock() view returns (uint192 value, uint64 validAt)\",\n  \"function pendingGuardian() view returns (address value, uint64 validAt)\",\n  \"function MORPHO() view returns (address)\",\n]);\n\nconst ERC20_ABI = parseAbi([\n  \"function name() view returns (string)\",\n  \"function symbol() view returns (string)\",\n  \"function decimals() view returns (uint8)\",\n]);\n\ninterface VaultConfiguration {\n  // Basic Info\n  address: Address;\n  name: string;\n  symbol: string;\n  decimals: number;\n  \n  // Asset Info\n  asset: {\n    address: Address;\n    name: string;\n    symbol: string;\n    decimals: number;\n  };\n  \n  // Financial Info\n  totalAssets: bigint;\n  totalSupply: bigint;\n  lastTotalAssets: bigint;\n  performanceFee: number; // As percentage\n  \n  // Governance & Roles\n  owner: Address | null;\n  curator: Address | null;\n  guardian: Address | null;\n  feeRecipient: Address | null;\n  skimRecipient: Address | null;\n  \n  // Configuration\n  timelock: bigint;\n  morphoAddress: Address;\n  \n  // Pending Changes\n  pendingTimelock: {\n    value: bigint | null;\n    validAt: bigint | null;\n  };\n  pendingGuardian: {\n    value: Address | null;\n    validAt: bigint | null;\n  };\n  \n  // Queue Lengths\n  supplyQueueLength: number;\n  withdrawQueueLength: number;\n}\n\ninterface AllocatorInfo {\n  address: Address;\n  isAllocator: boolean;\n}\n\n/**\n * Helper function to handle zero address cases\n */\nfunction handleZeroAddress(address: Address): Address | null {\n  return address === \"0x0000000000000000000000000000000000000000\" ? null : address;\n}\n\n/**\n * Helper function to format timelock duration\n */\nfunction formatTimelock(timelock: bigint): string {\n  const seconds = Number(timelock);\n  const days = Math.floor(seconds / 86400);\n  const hours = Math.floor((seconds % 86400) / 3600);\n  const minutes = Math.floor((seconds % 3600) / 60);\n  \n  if (days > 0) return `${days}d ${hours}h ${minutes}m`;\n  if (hours > 0) return `${hours}h ${minutes}m`;\n  if (minutes > 0) return `${minutes}m`;\n  return `${seconds}s`;\n}\n\n/**\n * Helper function to format pending values\n */\nfunction formatPendingValue(validAt: bigint | null): string {\n  if (!validAt || validAt === 0n) return \"None\";\n  const validAtDate = new Date(Number(validAt) * 1000);\n  return validAtDate.toISOString();\n}\n\n/**\n * Retrieves comprehensive vault configuration information.\n * @param client The Viem public client.\n * @param vaultAddress The address of the MetaMorpho vault.\n * @returns A promise that resolves to a VaultConfiguration object.\n */\nexport async function getVaultConfiguration(\n  client: PublicClient,\n  vaultAddress: Address\n): Promise<VaultConfiguration> {\n  console.log(`Fetching configuration for vault: ${vaultAddress}...`);\n\n  // First multicall to get basic vault information\n  const [\n    name,\n    symbol,\n    decimals,\n    assetAddress,\n    totalAssets,\n    totalSupply,\n    lastTotalAssets,\n    owner,\n    curator,\n    guardian,\n    feeRecipient,\n    skimRecipient,\n    fee,\n    timelock,\n    morphoAddress,\n    supplyQueueLength,\n    withdrawQueueLength,\n    pendingTimelockData,\n    pendingGuardianData,\n  ] = await client.multicall({\n    contracts: [\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"name\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"symbol\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"decimals\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"asset\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"totalAssets\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"totalSupply\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"lastTotalAssets\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"owner\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"curator\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"guardian\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"feeRecipient\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"skimRecipient\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"fee\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"timelock\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"MORPHO\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"supplyQueueLength\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"withdrawQueueLength\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"pendingTimelock\" },\n      { address: vaultAddress, abi: METAMORPHO_ABI, functionName: \"pendingGuardian\" },\n    ],\n    allowFailure: false,\n  });\n\n  // Second multicall to get asset information\n  const [assetName, assetSymbol, assetDecimals] = await client.multicall({\n    contracts: [\n      { address: assetAddress, abi: ERC20_ABI, functionName: \"name\" },\n      { address: assetAddress, abi: ERC20_ABI, functionName: \"symbol\" },\n      { address: assetAddress, abi: ERC20_ABI, functionName: \"decimals\" },\n    ],\n    allowFailure: false,\n  });\n\n  // Process pending values\n  const pendingTimelock = {\n    value: pendingTimelockData[0] > 0n ? pendingTimelockData[0] : null,\n    validAt: pendingTimelockData[1] > 0n ? pendingTimelockData[1] : null,\n  };\n\n  const pendingGuardian = {\n    value: handleZeroAddress(pendingGuardianData[0]),\n    validAt: pendingGuardianData[1] > 0n ? pendingGuardianData[1] : null,\n  };\n\n  // Calculate performance fee as percentage\n  const performanceFee = Number(formatUnits(fee, 18)) * 100;\n\n  return {\n    address: vaultAddress,\n    name,\n    symbol,\n    decimals,\n    asset: {\n      address: assetAddress,\n      name: assetName,\n      symbol: assetSymbol,\n      decimals: assetDecimals,\n    },\n    totalAssets,\n    totalSupply,\n    lastTotalAssets,\n    performanceFee,\n    owner: handleZeroAddress(owner),\n    curator: handleZeroAddress(curator),\n    guardian: handleZeroAddress(guardian),\n    feeRecipient: handleZeroAddress(feeRecipient),\n    skimRecipient: handleZeroAddress(skimRecipient),\n    timelock,\n    morphoAddress,\n    pendingTimelock,\n    pendingGuardian,\n    supplyQueueLength: Number(supplyQueueLength),\n    withdrawQueueLength: Number(withdrawQueueLength),\n  };\n}\n\n/**\n * Checks allocator status for a list of addresses.\n * @param client The Viem public client.\n * @param vaultAddress The address of the MetaMorpho vault.\n * @param addresses Array of addresses to check.\n * @returns A promise that resolves to an array of AllocatorInfo objects.\n */\nexport async function checkAllocators(\n  client: PublicClient,\n  vaultAddress: Address,\n  addresses: Address[]\n): Promise<AllocatorInfo[]> {\n  if (addresses.length === 0) return [];\n\n  const calls = addresses.map((address) => ({\n    address: vaultAddress,\n    abi: METAMORPHO_ABI,\n    functionName: \"isAllocator\" as const,\n    args: [address],\n  }));\n\n  const results = await client.multicall({\n    contracts: calls,\n    allowFailure: false,\n  });\n\n  return addresses.map((address, index) => ({\n    address,\n    isAllocator: results[index] as boolean,\n  }));\n}\n\n/**\n * Displays the vault configuration in a formatted manner.\n */\nexport function displayVaultConfiguration(config: VaultConfiguration): void {\n  console.log(\"\\n✅ --- Morpho Vault Configuration --- ✅\");\n  \n  console.log(\"\\n--- Basic Information ---\");\n  console.log(`Vault Name: ${config.name}`);\n  console.log(`Vault Symbol: ${config.symbol}`);\n  console.log(`Vault Address: ${config.address}`);\n  console.log(`Vault Decimals: ${config.decimals}`);\n  \n  console.log(\"\\n--- Asset Information ---\");\n  console.log(`Asset Name: ${config.asset.name}`);\n  console.log(`Asset Symbol: ${config.asset.symbol}`);\n  console.log(`Asset Address: ${config.asset.address}`);\n  console.log(`Asset Decimals: ${config.asset.decimals}`);\n  \n  console.log(\"\\n--- Financial Information ---\");\n  console.log(`Total Assets: ${formatUnits(config.totalAssets, config.asset.decimals)} ${config.asset.symbol}`);\n  console.log(`Total Supply: ${formatUnits(config.totalSupply, config.decimals)} ${config.symbol}`);\n  console.log(`Last Total Assets: ${formatUnits(config.lastTotalAssets, config.asset.decimals)} ${config.asset.symbol}`);\n  console.log(`Performance Fee: ${config.performanceFee.toFixed(4)}%`);\n  \n  console.log(\"\\n--- Governance & Roles ---\");\n  console.log(`Owner: ${config.owner || \"Not set\"}`);\n  console.log(`Curator: ${config.curator || \"Not set\"}`);\n  console.log(`Guardian: ${config.guardian || \"Not set\"}`);\n  console.log(`Fee Recipient: ${config.feeRecipient || \"Not set\"}`);\n  console.log(`Skim Recipient: ${config.skimRecipient || \"Not set\"}`);\n  \n  console.log(\"\\n--- Configuration ---\");\n  console.log(`Timelock: ${formatTimelock(config.timelock)}`);\n  console.log(`Morpho Address: ${config.morphoAddress}`);\n  \n  console.log(\"\\n--- Pending Changes ---\");\n  console.log(`Pending Timelock: ${config.pendingTimelock.value ? formatTimelock(config.pendingTimelock.value) : \"None\"}`);\n  console.log(`  Valid At: ${formatPendingValue(config.pendingTimelock.validAt)}`);\n  console.log(`Pending Guardian: ${config.pendingGuardian.value || \"None\"}`);\n  console.log(`  Valid At: ${formatPendingValue(config.pendingGuardian.validAt)}`);\n  \n  console.log(\"\\n--- Queue Information ---\");\n  console.log(`Supply Queue Length: ${config.supplyQueueLength}`);\n  console.log(`Withdraw Queue Length: ${config.withdrawQueueLength}`);\n  \n  console.log(\"\\n----------------------------------------\");\n}\n\n/**\n * Displays allocator information.\n */\nexport function displayAllocators(allocators: AllocatorInfo[]): void {\n  if (allocators.length === 0) {\n    console.log(\"\\nNo allocators checked.\");\n    return;\n  }\n\n  console.log(\"\\n--- Allocator Status ---\");\n  allocators.forEach(({ address, isAllocator }) => {\n    console.log(`${address}: ${isAllocator ? \"✅ Allocator\" : \"❌ Not Allocator\"}`);\n  });\n}\n\n/**\n * Main function to run the script.\n */\nexport async function main(): Promise<void> {\n  try {\n    const client = createMainnetClient();\n    \n    // Get vault configuration\n    const config = await getVaultConfiguration(client, VAULT_ADDRESS);\n    displayVaultConfiguration(config);\n    \n    // Example: Check allocator status for some addresses (optional)\n    const addressesToCheck: Address[] = [\n      // Add any addresses you want to check here\n      // \"0x1234567890123456789012345678901234567890\",\n    ];\n    \n    if (addressesToCheck.length > 0) {\n      const allocators = await checkAllocators(client, VAULT_ADDRESS, addressesToCheck);\n      displayAllocators(allocators);\n    }\n    \n  } catch (error) {\n    console.error(\"An error occurred during script execution:\", error);\n    process.exit(1);\n  }\n}\n\n// Run the script if executed directly\nif (require.main === module) {\n  main();\n}\n```\n\n**Example Output:**\n\n```json\nFetching configuration for vault: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB...\n\n--- Morpho Vault Configuration ---\n\n--- Basic Information ---\nVault Name: Steakhouse USDC\nVault Symbol: steakUSDC\nVault Address: 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\nVault Decimals: 18\n\n--- Asset Information ---\nAsset Name: USD Coin\nAsset Symbol: USDC\nAsset Address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\nAsset Decimals: 6\n\n--- Financial Information ---\nTotal Assets: 164441677.475477 USDC\nTotal Supply: 150734916.783575645489233854 steakUSDC\nLast Total Assets: 164440150.994583 USDC\nPerformance Fee: 0.0000%\n\n--- Governance & Roles ---\nOwner: 0x0A0e559bc3b0950a7e448F0d4894db195b9cf8DD\nCurator: 0x827e86072B06674a077f592A531dcE4590aDeCdB\nGuardian: 0xaa0500198B4425DfC4E272FbE42C8E64E21fc03d\nFee Recipient: 0x255c7705e8BB334DfCae438197f7C4297988085a\nSkim Recipient: Not set\n\n--- Configuration ---\nTimelock: 7d 0h 0m\nMorpho Address: 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb\n\n--- Pending Changes ---\nPending Timelock: None\n  Valid At: None\nPending Guardian: None\n  Valid At: None\n\n--- Queue Information ---\nSupply Queue Length: 4\nWithdraw Queue Length: 4\n\n----------------------------------------\n```\n\n{\" \"}\n\n```solidity\n// Basic vault information\nstring memory vaultName = IMetaMorpho(vault).name();\nstring memory vaultSymbol = IMetaMorpho(vault).symbol();\nuint8 vaultDecimals = IMetaMorpho(vault).decimals();\naddress assetAddress = IMetaMorpho(vault).asset();\n\n// Financial metrics\nuint256 totalAssets = IMetaMorpho(vault).totalAssets();\nuint256 totalSupply = IMetaMorpho(vault).totalSupply();\nuint96 performanceFee = IMetaMorpho(vault).fee(); // In WAD (18 decimals)\n\n// Governance roles\naddress owner = IMetaMorpho(vault).owner();\naddress curator = IMetaMorpho(vault).curator();\naddress guardian = IMetaMorpho(vault).guardian();\naddress feeRecipient = IMetaMorpho(vault).feeRecipient();\n\n// Configuration\nuint256 timelock = IMetaMorpho(vault).timelock();\nuint256 supplyQueueLength = IMetaMorpho(vault).supplyQueueLength();\nuint256 withdrawQueueLength = IMetaMorpho(vault).withdrawQueueLength();\n\n// Check allocator status\nbool isAllocator = IMetaMorpho(vault).isAllocator(userAddress);\n\n// Pending changes\n(uint192 pendingTimelockValue, uint64 pendingTimelockValidAt) =\n    IMetaMorpho(vault).pendingTimelock();\n(address pendingGuardianValue, uint64 pendingGuardianValidAt) =\n    IMetaMorpho(vault).pendingGuardian();\n```\n\n**Key Functions:**\n- **Basic Info**: `name()`, `symbol()`, `decimals()`, `asset()`\n- **Financial**: `totalAssets()`, `totalSupply()`, `fee()`, `lastTotalAssets()`\n- **Roles**: `owner()`, `curator()`, `guardian()`, `feeRecipient()`, `skimRecipient()`\n- **Configuration**: `timelock()`, `isAllocator()`, `MORPHO()`\n- **Queues**: `supplyQueueLength()`, `withdrawQueueLength()`\n- **Pending**: `pendingTimelock()`, `pendingGuardian()`\n\n**Note:** Always check for zero addresses when roles are not set. The `fee()` returns a value in WAD format (18 decimals).\n\n### Risk Indicators\n\n#### Morpho Vault Warnings\n\nWarning `type` can be:\n\n- `unrecognized_deposit_asset`,\n- `unrecognized_vault_curator`,\n- `not_whitelisted`\n\nWarning `level` is either:\n\n- YELLOW,\n- RED.\n\n```graphql [API]\nquery {\n  vaultV2s(first: 5) {\n    items {\n      name\n      warnings {\n        type\n        level\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n```graphql [API]\nquery {\n  vaults {\n    items {\n      name\n      warnings {\n        type\n        level\n      }\n    }\n  }\n}\n```\n\n## Fee Wrapper\n\n### FeeWrapper List\n\n```graphql [Unique FeeWrapper]\nquery VaultV2ByAddress {\n  vaultV2ByAddress(\n    address: \"0xd4468EF3745c315949a97090eD27b3F73b9b7C02\"\n    chainId: 8453\n  ) {\n    type\n    address\n    name\n  }\n}\n```\n\n```graphql [All FeeWrappers]\nquery VaultV2s {\n  vaultV2s(skip: 0, first: 20, where: { type_in: [FeeWrapper] }) {\n    items {\n      address\n      name\n    }\n  }\n}\n```\n\n{\" \"}\n\n### FeeWrapper Exposure\n\n```graphql [Unique FeeWrapper]\nquery VaultV2ByAddress {\n  vaultV2ByAddress(\n    address: \"0xd4468EF3745c315949a97090eD27b3F73b9b7C02\"\n    chainId: 8453\n  ) {\n    type\n    adapters {\n      items {\n        type\n        address\n        ... on MorphoVaultV2Adapter {\n          address\n          innerVault {\n            address\n            name\n          }\n        }\n      }\n    }\n    historicalState {\n      sharePrice(options: {\n        startTimestamp: 1771015645\n        endTimestamp: 1771915645\n        interval: HOUR\n      }) {\n        x\n        y\n      }\n    }\n  }\n}\n```\n\n```graphql [All FeeWrappers]\nquery VaultV2s {\n  vaultV2s(skip: 0, first: 20, where: { type_in: [FeeWrapper] }) {\n    items {\n      type\n      address\n      adapters {\n        items {\n          type\n          address\n          ... on MorphoVaultV2Adapter {\n            address\n            innerVault {\n              address\n              name\n            }\n          }\n        }\n      }\n      historicalState {\n        sharePrice(options: {\n          startTimestamp: 1771015645\n          endTimestamp: 1771915645\n          interval: HOUR\n        }) {\n          x\n          y\n        }\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n### FeeWrapper Yield\n\n```graphql [Unique FeeWrapper]\nquery VaultV2ByAddress {\n  vaultV2ByAddress(\n    address: \"0xd4468EF3745c315949a97090eD27b3F73b9b7C02\"\n    chainId: 8453\n  ) {\n    type\n    apy\n    avgNetApyExcludingRewards\n    avgNetApy\n    performanceFee\n    performanceFeeRecipient\n    managementFee\n    managementFeeRecipient\n    rewards {\n      asset {\n        symbol\n        address\n      }\n      supplyApr\n    }\n  }\n}\n```\n\n```graphql [All FeeWrappers]\nquery VaultV2s {\n  vaultV2s(skip: 0, first: 20, where: { type_in: [FeeWrapper] }) {\n    items {\n      type\n      address\n      apy\n      avgNetApyExcludingRewards\n      avgNetApy\n      performanceFee\n      performanceFeeRecipient\n      managementFee\n      managementFeeRecipient\n      rewards {\n        asset {\n          symbol\n          address\n        }\n        supplyApr\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n## Position Tracking\n\n### User All Vaults Position\n\n#### Morpho Vaults V2 & V1\n\n```graphql\nquery GetUserVaultPositions($address: String!, $chainId: Int!) {\n  userByAddress(address: $address, chainId: $chainId) {\n    id\n    vaultV2Positions {\n      shares\n      vault {\n        address\n        symbol\n      }\n    }\n    vaultPositions {\n      state {\n        shares\n      }\n      vault {\n        address\n        symbol\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n### Vault Depositors\n\n#### Morpho Vaults V2\n\n```graphql [Unique Vault]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    positions(first: 10, skip:0) {\n      items {\n        user {\n          address\n        }\n        assets\n        assetsUsd\n        shares\n      }\n    }\n    totalSupply\n    asset {\n      address\n      symbol\n    }\n  }\n}\n```\n\n{\" \"}\n\n#### Morpho Vaults V1\n\n```graphql [Unique Vault]\nquery {\n  vaultPositions(\n    first: 10\n    orderBy: Shares\n    orderDirection: Desc\n    where: { vaultAddress_in: [\"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"] }\n  ) {\n    items {\n      user {\n        address\n      }\n      state {\n        shares\n        assets\n        assetsUsd\n      }\n    }\n  }\n}\n```\n\n```graphql [Set of Vaults]\nquery {\n  vaultPositions(\n    first: 10\n    orderBy: Shares\n    orderDirection: Desc\n    where: {\n      vaultAddress_in: [\n        \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n        \"0x73e65DBD630f90604062f6E02fAb9138e713edD9\"\n      ]\n    }\n  ) {\n    items {\n      vault {\n        address\n      }\n      user {\n        address\n      }\n      state {\n        shares\n        assets\n        assetsUsd\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n### Transaction History\n\n#### Morpho Vaults V2\n\n```graphql [Unique Vault]\nquery {\n  vaultV2transactions(\n    first: 10\n    skip: 0\n    where: { vaultAddress_in: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\" }\n  ) {\n    items {\n      vault {\n        address\n      }\n      type\n      shares\n      blockNumber\n      timestamp\n      txHash\n      txIndex\n    }\n  }\n}\n```\n\n{\" \"}\n\n#### Morpho Vaults V1\n\n```graphql [Unique Vault]\nquery {\n  transactions(\n    first: 10\n    orderBy: Timestamp\n    orderDirection: Desc\n    where: { vaultAddress_in: [\"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"] }\n  ) {\n    items {\n      blockNumber\n      hash\n      type\n      user {\n        address\n      }\n    }\n  }\n}\n```\n\n{\" \"}\n\n## Historical Data\n\n### APY Historical State\n\n#### Morpho Vaults v2\n\nComing soon.\n\n#### Morpho Vaults V1\n\n```graphql [Unique Vault]\nquery VaultApys($options: TimeseriesOptions) {\n  vaultByAddress(address: \"0x73e65DBD630f90604062f6E02fAb9138e713edD9\") {\n    address\n    historicalState {\n      apy(options: $options) {\n        x\n        y\n      }\n      netApy(options: $options) {\n        x\n        y\n      }\n    }\n  }\n}\n```\n\n```graphql [All Vaults]\nquery VaultApys($options: TimeseriesOptions) {\n  vaults(first: 10, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      historicalState {\n        apy(options: $options) {\n          x\n          y\n        }\n        netApy(options: $options) {\n          x\n          y\n        }\n      }\n    }\n  }\n}\n```\n\nWith those variables:\n\n```json\n{\n  \"options\": {\n    \"startTimestamp\": 1740000000,\n    \"endTimestamp\": 1742564817,\n    \"interval\": \"DAY\"\n  }\n}\n```\n\n{\" \"}"
  },
  "/build/earn/tutorials/rewards/": {
    "title": "Integrate Rewards for Earn Products",
    "url": "https://docs.morpho.org/build/earn/tutorials/rewards/",
    "section": "Build",
    "content": "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.\n\n## What's Unique for Earn Products\n\nWhen building earn products, understand that vault depositors earn rewards from **two sources**:\n\n1. **Direct Vault Campaigns**: Rewards distributed directly to vault depositors\n2. **Forwarded Market Campaigns**: Rewards from underlying markets where the vault allocates liquidity\n\n**Critical integration requirement:**\n```\nNet APY = Vault Native APY + Vault Campaign Rewards APR + Forwarded Market Rewards APR\n```\n\n## Integration Steps\n\nFollow the centralized rewards tutorials with vault-specific considerations:\n\n### Step 1: Fetch Vault Rewards Data\n\n**Follow:** [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)\n\n**Vault-specific notes:**\n- Query both `state.rewards` and `state.allocation[].market.state.rewards`\n- Calculate weighted average for market rewards based on allocation\n- Use `supplyAssetsUsd` to determine weights\n- Alternatively, use `netApy` convenience field for simple total APY\n\n### Step 2: Display Rewards in Your UI\n\n**Follow:** [Integrate Rewards Display](/build/rewards/tutorials/integrate-display)\n\n**Vault-specific notes:**\n- Prominently display Net APY (native + all rewards)\n- Show breakdown: base yield vs. rewards\n- List reward tokens with their respective APRs\n- Optionally show which markets contribute to forwarded rewards\n\n### Step 3: Enable Reward Claiming\n\n**Follow:** [Claim Rewards](/build/rewards/tutorials/claim-rewards)\n\n**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.\n\n## Complete Integration Example\n\nFor a full working reference implementation:\n\n**See:** [Complete Rewards Integration Guide](/build/rewards/guides/complete-integration)\n\nThis guide includes production-ready code using the [morpho-merkl-recipe](https://github.com/morpho-org/merkl-morpho-recipe).\n\n## Quick Reference\n\n| Task                      | Main Tutorial                                                       | Vault-Specific Consideration                |\n|---------------------------|---------------------------------------------------------------------|---------------------------------------------|\n| **Understanding rewards** | [Reward Campaigns](/build/rewards/concepts/reward-campaigns)        | Understand forwarding mechanism             |\n| **Distribution system**   | [Distribution Systems](/build/rewards/concepts/distribution-system) | Same Merkl/URD for all users                |\n| **Fetch rewards**         | [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)   | Query two API locations, manual aggregation |\n| **Display rewards**       | [Integrate Display](/build/rewards/tutorials/integrate-display)     | Show total APY breakdown                    |\n| **Claim rewards**         | [Claim Rewards](/build/rewards/tutorials/claim-rewards)             | Same process for all users                  |\n\n## Need Help?\n\n- **Conceptual questions**: [Rewards for Lenders Concept](/build/earn/concepts/rewards)\n- **Main rewards guide**: [Rewards Integration Guide](/build/rewards/get-started)\n- **Technical support**: [help.morpho.org](https://help.morpho.org)\n- **Example code**: [morpho-merkl-recipe](https://github.com/morpho-org/merkl-morpho-recipe)"
  },
  "/build/rewards/concepts/distribution-system/": {
    "title": "Merkl Distribution System",
    "url": "https://docs.morpho.org/build/rewards/concepts/distribution-system/",
    "section": "Build",
    "content": "[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).\n\n## How Merkl Works\n\n### Offchain Computation\nMerkl's infrastructure continuously monitors onchain activity and calculates earned rewards:\n- Monitors onchain activity directly via RPC nodes\n- Proprietary indexing infrastructure\n- Real-time event processing\n\nThis is necessary because:\n1. **Complex logic**: Reward calculations involve historical data, forwarding, and blacklisting\n2. **Gas efficiency**: Computing onchain would be prohibitively expensive\n3. **Flexibility**: Allows for sophisticated distribution strategies\n\n### Merkle Tree Generation & Onchain Distribution\nEvery 8 hours, Merkl generates a new Merkle tree containing all claimable rewards. The Merkle root is posted onchain, making rewards claimable.\n- Rewards are recalculated every 8 hours\n- Users see their accruing rewards in near real-time\n\n### User Claims\nUsers can claim their rewards by submitting a transaction with their Merkle proof.\n- Low waiting period between earning and claiming\n\n## Key Characteristics\n\n**Standardized Integration**\n- Consistent API across all protocols using Merkl\n- Well-documented claiming process\n- Community-supported SDKs and tools\n\n**Multi-Protocol Support**\n- Same infrastructure used by many DeFi protocols\n- Familiar UX for users who've claimed rewards elsewhere\n- Centralized infrastructure for reward discovery\n\n## When to Use\n\nIntegrate Merkl for:\n- All new reward programs (July 2025 onwards)\n- Current MORPHO token distributions\n- Third-party incentive programs\n- Real-time reward tracking\n\n## Integration Points\n\n**For Claiming Rewards:** head to the [Integrate Rewards Claim](/build/rewards/tutorials/claim-rewards) section.\n\n**For Displaying Rewards:** head to the [Integrate Rewards Display](/build/rewards/tutorials/integrate-display) section."
  },
  "/build/rewards/concepts/reward-campaigns/": {
    "title": "Reward Campaigns on Morpho",
    "url": "https://docs.morpho.org/build/rewards/concepts/reward-campaigns/",
    "section": "Build",
    "content": "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.\n\n## What Are Reward Campaigns?\n\nMerkl 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.\n\nWhen creating a campaign through Merkl's interface, you select:\n- The lending market or vault you want to incentivize\n- The reward token to distribute\n- The campaign duration and reward budget\n- The specific user behavior to reward (supply or borrow)\n\nIt is also possible to incentivize a simple collateral deposit (without the borrow action required).\n\n## Distribution Strategies\n\nMerkl offers two main categories of reward distribution for Morpho:\n\n1. **Vault-Level Incentives** - Target deposits into specific Morpho Vaults\n2. **Market-Level Incentives** - Target activity within Morpho Markets\n\n### Vault-Level Incentives\n\n**Strategy: Supply to a Morpho Vault**\n\nThis 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.\n\n**How it works:**\n- Rewards are distributed linearly over the campaign duration\n- Users earn rewards based on their vault deposit amount and duration\n- All depositors into the targeted vault are eligible\n- Only one reward rate applies (vault supply rewards)\n\n**Use cases:**\n- Bootstrap a new vault to attract initial liquidity\n- Increase deposits into an established vault\n- Provide additional yield to vault depositors beyond base APY\n\n### Market-Level Incentives\n\n**Strategy: Incentivize Activity in Morpho V1 Markets**\n\nMarket-level strategies provide more granular control, allowing you to target specific behaviors within Morpho V1 Markets. You can incentivize:\n\n- **Supply**: Reward users who lend assets to a market\n- **Borrow**: Reward users who borrow assets from a market\n\nAdditionally, you can choose between:\n- **Specific market targeting**: Incentivize activity in one particular market\n- **Token-based targeting**: Incentivize use of a specific token across all markets\n\n**Distribution Options:**\n\n1. **Supply to a specific market**: Rewards users who supply assets to a particular Morpho V1 market.\n\n2. **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).\n\n3. **Borrow from a specific market**: Rewards users who borrow assets from a particular Morpho V1 market.\n\n4. **Borrow a token from any market**: Rewards users who borrow a specific token across all Morpho V1 markets.\n\n**How it works:**\n- Campaigns distribute rewards linearly over a defined period\n- Each campaign can have separate rates for supply and borrow\n- Users earn rewards based on their position size and duration\n- Rates are expressed as annualized amounts per token\n\n**Use cases:**\n- Bootstrap a new market by incentivizing early suppliers or borrowers\n- Encourage borrowing to increase market utilization\n- Reward specific collateral types to diversify market risk\n- Create token-wide incentives across the entire Morpho ecosystem\n\n## Combining Multiple Campaigns\n\nMerkl API provides an APR for each campaign (vault and market ones).\n\nVault depositors may be eligible for rewards from **multiple campaigns simultaneously**:\n\n1. **Direct vault-level rewards**: From campaigns directly targeting the vault\n2. **Forwarded market-level rewards**: From campaigns targeting markets where the vault allocates liquidity\n\n**Total Vault APY:**\n```\nTotal APY = Base Vault APY + Vault Campaign APR + Σ(Forwarded Market Campaign APR)\n```\n\nWhere:\n- **Base Vault APY**: Native lending yield from the vault's market allocations\n- **Vault Campaign APR**: Direct vault-level incentives\n- **Forwarded Market Campaign APR**: Sum of all market-level rewards from allocated markets\n\n## Reward Forwarding\n\nOne of the most important features of Morpho's reward system is **automatic reward forwarding** for vault depositors.\n\n### How Forwarding Works\n\nWhen 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.\n\n**The forwarding mechanism:**\n1. Market-level supply campaigns distribute rewards to suppliers\n2. Vaults that supply to these markets earn rewards at the vault contract level\n3. Merkl's offchain computation reallocates these rewards to individual vault depositors\n4. Vault depositors can claim these market-level rewards directly\n\nThis happens transparently in the background, ensuring that:\n- Vault depositors benefit from all market-level campaigns\n- No manual intervention is required\n- Rewards are distributed fairly based on deposit amounts and duration\n\nForwarding works for Morpho Vaults V1 and Morpho Vaults V2.\n\n### Integration Considerations\n\nAs an integrator, you should display:\n- **Direct vault campaigns**: Campaigns explicitly targeting the vault\n- **Forwarded market campaigns**: Campaigns targeting markets where the vault allocates, with rewards forwarded to depositors\n- **Combined APR**: Total reward APR from both sources\n\nUsers expect to see the full picture of their potential earnings, including both direct and forwarded rewards.\n\n## Blacklisting\n\nCampaign creators can **blacklist specific addresses** from earning rewards. This is commonly used to:\n\n- Prevent self-incentivization when protocols bootstrap their own markets\n- Exclude treasury addresses that provide initial liquidity\n- Remove addresses that don't align with campaign goals\n\n**Example:**\nIf a protocol creates a market and deposits its treasury to provide initial liquidity, it can blacklist its treasury address. This ensures:\n- Reward budget goes entirely to external users\n- No circular incentive flow\n- Fair distribution among community participants\n\nBlacklisting 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.\n\n## Historical Context: Legacy Reward Systems\n\n**Historical Note**  \n\nPrior 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.\"\n\nThese legacy programs:\n- Used weekly distribution cycles (vs. Merkl's 8-hour cycles)\n- Had different API endpoints and claiming processes\n- May still have unclaimed rewards for users with historical positions\n\n**For integrators:**\n- Support both Merkl (current) and URD (legacy) claiming. \n- See [URD Technical Details](/get-started/resources/contracts/rewards/) for legacy support\n\n## Querying Active Campaigns\n\nYou can see how to retrieve campaigns data in the [Fetch Rewards Data section](/build/rewards/tutorials/fetch-rewards-data).\n\n## Next Steps\n\n- **Create campaigns**: Follow the [Create a Rewards Program tutorial](/build/rewards/tutorials/create-program)\n- **Understand distribution**: Read about [Distribution System](/build/rewards/concepts/distribution-system)\n- **Fetch data**: Follow the [Fetch Rewards Data tutorial](/build/rewards/tutorials/fetch-rewards-data)\n- **Display rewards**: See the [Integrate Display tutorial](/build/rewards/tutorials/integrate-display)"
  },
  "/build/rewards/get-started/": {
    "title": "Integrating Morpho Rewards",
    "url": "https://docs.morpho.org/build/rewards/get-started/",
    "section": "Build",
    "content": "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.\n\n## Understanding the Rewards Ecosystem\n\nRewards on Morpho are distributed through **two primary systems**:\n\n1. **Merkl** (Primary - Current Standard)\n2. **Morpho URD** (Legacy - Historical Programs)\n\n**Important Migration Notice**\n\nThe 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).\n\n**What this means for integrators:**\n- **New programs**: All new MORPHO rewards and third-party rewards are distributed via Merkl\n- **Historical programs**: Some rewards from older programs remain claimable via the Morpho URD (Universal Rewards Distributor)\n- **Complete integration**: Support both systems to provide users access to all available rewards\n\n**Important: Non-Claimable Addresses**\n\nIf 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.\n\nRewards allocated to addresses that cannot claim aren't recoverable or redirectable after the fact and will stay permanently unclaimable.\n\n## Merkl: The Current Standard\n\n[Merkl](https://merkl.xyz/) is a third-party rewards distribution platform that now handles Morpho ecosystem rewards. It offers:\n\n- **Flexible distribution**: Rewards updated every 8 hours\n- **Multi-protocol support**: Used across DeFi, not just Morpho\n- **Automated calculations**: Offchain computation of eligible rewards\n- **Standardized claiming**: Consistent API and claiming process\n\n**When to use Merkl:**\n- All new reward programs (July 2025 onwards)\n- Third-party incentive programs\n- Current MORPHO token distributions\n\n## Morpho URD: Legacy Support\n\nThe Universal Rewards Distributor (URD) was Morpho's native rewards system. While new programs use Merkl, the URD still holds claimable rewards from historical programs.\n\n**When to support URD:**\n- Legacy MORPHO distributions (pre-July 2025)\n- Historical vault and market rewards distributions\n- Unclaimed rewards from completed campaigns\n\n## Who Should Integrate Rewards?\n\nYou should integrate rewards if you're building:\n\n- **Earn Products**: Display additional APR from rewards alongside base vault yield\n- **Borrow Products**: Show borrowers incentives for taking loans\n- **Portfolio Dashboards**: Provide users with a complete view of their Morpho earnings\n- **Aggregators**: Compare total yields (base + rewards) across protocols\n- **Reward Platforms**: Create specialized UIs for rewards discovery and claiming\n\n## What You'll Need to Integrate\n\nA complete rewards integration involves three main components:\n\n### 1. Rewards Discovery & Display\nFetch and display available rewards for vaults and markets:\n- Query reward rates from Merkl API or Morpho API\n- Calculate total APY (base yield + reward APR)\n- Show reward token types and amounts\n- Display program timelines and eligibility\n\n### 2. User Balance Tracking\nShow users their accrued and claimable rewards:\n- Fetch user-specific reward balances\n- Display rewards by token and program\n- Calculate USD values of rewards\n- Update balances in real-time\n\n### 3. Claiming Interface\nEnable users to claim their rewards:\n- Support Merkl claim flow (primary)\n- Support Morpho URD claim flow (legacy)\n- Handle transaction signing and confirmation\n- Provide claim status feedback\n\n## Integration Paths\n\nFirst, [Understand Reward Programs](/build/rewards/concepts/reward-campaigns) and learn the different program types.\n\nChoose your integration approach based on your needs:\n\n### Quick Start (Display Only)\nJust want to show rewards APR alongside base yield? Start here:\n1. [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) - Learn to query both APIs\n2. [Integrate Display](/build/rewards/tutorials/integrate-display) - Show rewards in your UI\n\n### Full Integration (Display + Claiming)\nBuilding a complete product? Follow this path:\n\n1. [Merkl Distribution System](/build/rewards/concepts/distribution-system) - Understand Distribution\n2. [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data) - Query rewards information\n3. [Claim Rewards](/build/rewards/tutorials/claim-rewards) - Implement claiming for both systems\n4. [Complete Integration Guide](/build/rewards/guides/complete-integration) - See a full working example\n\n### Creating Rewards (Issuers)\nAre you a protocol or DAO looking to create a rewards program?\n1. [Create a Program](/build/rewards/tutorials/create-program) - Step-by-step program creation\n\n## Need Help?\n\n- **Technical Support**: Visit [help.morpho.org](https://help.morpho.org)\n- **Merkl Support**: Reach out via [Merkl's documentation](https://docs.merkl.xyz/)"
  },
  "/build/rewards/guides/complete-integration/": {
    "title": "Complete Integration Example",
    "url": "https://docs.morpho.org/build/rewards/guides/complete-integration/",
    "section": "Build",
    "content": "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.\n\n**Example Repository**  \n**[morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe)**\n\nThis is an educational Next.js application that showcases how to:\n- Fetch vault metrics and rewards from Morpho API\n- Query user claimable rewards from both Merkl and Morpho URD\n- Display combined APY (base + rewards)\n- Implement claim functionality for both systems\n\n**⚠️ Educational Purpose**: This is a learning resource. Additional security measures, testing, and auditing are required before production use.\n\n## Repository Overview\n\n### Tech Stack\n\n- **Next.js 15** - React framework\n- **TypeScript** - Type safety\n- **Morpho API** - GraphQL for vault/market data\n- **Merkl API** - REST API for Merkl rewards\n- **Morpho Rewards API** - REST API for URD rewards\n\n### Project Structure\n\n```\nsrc/\n├── app/              # Next.js app router\n├── components/       # React components\n│   ├── VaultMetricsPanel.tsx      # Display vault APY + rewards\n│   ├── UserRewardsPanel.tsx       # User claimable rewards\n│   ├── VaultRewardsDisplay.tsx    # Rewards breakdown\n│   └── ClaimImplementationPanel.tsx # Claim code examples\n├── hooks/            # React hooks\n│   ├── useVaultData.ts            # Fetch vault data\n│   └── useClipboard.ts            # Utility hook\n├── lib/              # Core logic\n│   ├── api.ts                     # API clients\n│   ├── claiming.ts                # Claim functions\n│   ├── simulation.ts              # Transaction simulation\n│   └── helpers/\n│       └── rewards.ts             # Reward calculations\n└── types/            # TypeScript types\n    └── index.ts\n```\n\n## Key Concepts Demonstrated\n\n### 1. Combining Morpho and Merkl Data\n\nThe demo shows how to fetch and combine data from multiple sources to provide a complete picture:\n\n**File: `src/lib/api.ts`**\n\n```typescript\nexport async function getVaultData(vaultAddress: string, chainId: number) {\n  // Fetch from Morpho API\n  const morphoData = await fetchMorphoVault(vaultAddress, chainId);\n\n  // Extract rewards information\n  const rewards = morphoData.vault.state.rewards.map((r) => ({\n    token: r.asset.symbol,\n    apr: parseFloat(r.supplyApr),\n    yearlySupplyTokens: r.yearlySupplyTokens,\n  }));\n\n  // Calculate combined APY\n  const baseApy = parseFloat(morphoData.vault.state.apy);\n  const rewardsApr = rewards.reduce((sum, r) => sum + r.apr, 0);\n\n  return {\n    vault: morphoData.vault,\n    baseApy,\n    rewardsApr,\n    totalApy: baseApy + rewardsApr,\n    rewards,\n  };\n}\n```\n\n### 2. Fetching User Rewards from Both Systems\n\n**File: `src/lib/helpers/rewards.ts`**\n\n```typescript\nexport async function getUserRewards(userAddress: string, chainId: number) {\n  const [merklRewards, urdRewards] = await Promise.all([\n    fetchMerklUserRewards(userAddress, chainId),\n    fetchURDUserRewards(userAddress),\n  ]);\n\n  return {\n    merkl: merklRewards,\n    urd: urdRewards,\n    combined: combineRewardsByToken(merklRewards, urdRewards),\n  };\n}\n\nfunction combineRewardsByToken(merkl: Reward[], urd: Reward[]) {\n  const combined = new Map<string, Reward>();\n\n  for (const reward of [...merkl, ...urd]) {\n    if (combined.has(reward.token)) {\n      const existing = combined.get(reward.token)!;\n      existing.amount += reward.amount;\n    } else {\n      combined.set(reward.token, { ...reward });\n    }\n  }\n\n  return Array.from(combined.values());\n}\n```\n\n### 3. Implementing Claims\n\n**File: `src/lib/claiming.ts`**\n\nThe demo includes claim implementations for both systems:\n\n**Merkl Claim:**\n\n```typescript\nexport async function claimMerklRewards(\n  userAddress: string,\n  chainId: number,\n  walletClient: WalletClient\n) {\n  // 1. Fetch claim data\n  const claimData = await fetch(\n    `https://api.merkl.xyz/v4/claim?user=${userAddress}&chainId=${chainId}`\n  ).then((r) => r.json());\n\n  // 2. Execute claim transaction\n  const hash = await walletClient.writeContract({\n    address: MERKL_DISTRIBUTOR_ADDRESS,\n    abi: MERKL_ABI,\n    functionName: \"claim\",\n    args: [\n      claimData.user,\n      claimData.tokens,\n      claimData.amounts,\n      claimData.proofs,\n    ],\n  });\n\n  // 3. Wait for confirmation\n  return await walletClient.waitForTransactionReceipt({ hash });\n}\n```\n\n**URD Claim:**\n\n```typescript\nexport async function claimURDRewards(\n  userAddress: string,\n  walletClient: WalletClient\n) {\n  // 1. Fetch all distributions\n  const distributions = await fetch(\n    `https://rewards.morpho.org/v1/users/${userAddress}/distributions`\n  ).then((r) => r.json());\n\n  const results = [];\n\n  // 2. Claim each distribution\n  for (const dist of distributions) {\n    // Check if already claimed\n    const claimed = await checkClaimedAmount(\n      dist.distributor,\n      userAddress,\n      dist.asset.address\n    );\n\n    if (BigInt(claimed) >= BigInt(dist.claimable)) {\n      continue; // Nothing to claim\n    }\n\n    // Execute claim using pre-formatted tx_data\n    const hash = await walletClient.sendTransaction({\n      to: dist.distributor,\n      data: dist.tx_data,\n    });\n\n    const receipt = await walletClient.waitForTransactionReceipt({ hash });\n    results.push({ distribution: dist, receipt });\n  }\n\n  return results;\n}\n```\n\n### 4. React Components for Display\n\n**File: `src/components/VaultMetricsPanel.tsx`**\n\n```tsx\nexport function VaultMetricsPanel({ vaultAddress, chainId }) {\n  const { data, loading, error } = useVaultData(vaultAddress, chainId);\n\n  if (loading) return <Skeleton />;\n  if (error) return <ErrorDisplay error={error} />;\n\n  return (\n    <div className=\"vault-metrics\">\n      {/* Vault Header */}\n      <div className=\"header\">\n        <h2>{data.vault.name}</h2>\n        <p>{data.vault.symbol}</p>\n      </div>\n\n      {/* APY Display */}\n      <div className=\"apy-section\">\n        <div className=\"total-apy\">\n          <span className=\"label\">Total APY</span>\n          <span className=\"value\">{data.totalApy.toFixed(2)}%</span>\n        </div>\n\n        <div className=\"breakdown\">\n          <div>Base APY: {data.baseApy.toFixed(2)}%</div>\n          {data.rewardsApr > 0 && (\n            <div className=\"rewards\">\n              Rewards: +{data.rewardsApr.toFixed(2)}%\n            </div>\n          )}\n        </div>\n      </div>\n\n      {/* Rewards List */}\n      {data.rewards.length > 0 && (\n        <VaultRewardsDisplay rewards={data.rewards} />\n      )}\n    </div>\n  );\n}\n```\n\n**File: `src/components/UserRewardsPanel.tsx`**\n\n```tsx\nexport function UserRewardsPanel({ userAddress, chainId }) {\n  const [rewards, setRewards] = useState(null);\n  const [claiming, setClaiming] = useState(false);\n\n  useEffect(() => {\n    getUserRewards(userAddress, chainId).then(setRewards);\n  }, [userAddress, chainId]);\n\n  const handleClaimAll = async () => {\n    setClaiming(true);\n    try {\n      // Claim from both systems\n      await Promise.all([\n        claimMerklRewards(userAddress, chainId, walletClient),\n        claimURDRewards(userAddress, walletClient),\n      ]);\n\n      alert(\"Rewards claimed successfully!\");\n      // Refresh rewards data\n      getUserRewards(userAddress, chainId).then(setRewards);\n    } catch (error) {\n      console.error(\"Claim failed:\", error);\n      alert(\"Claim failed. See console for details.\");\n    } finally {\n      setClaiming(false);\n    }\n  };\n\n  return (\n    <div className=\"user-rewards\">\n      <h3>Your Claimable Rewards</h3>\n\n      {rewards?.combined.map((reward) => (\n        <div key={reward.token} className=\"reward-row\">\n          <span>{reward.token}</span>\n          <span>{formatAmount(reward.amount)} {reward.token}</span>\n        </div>\n      ))}\n\n      <button onClick={handleClaimAll} disabled={claiming}>\n        {claiming ? \"Claiming...\" : \"Claim All Rewards\"}\n      </button>\n\n      {/* Show source breakdown */}\n      <details>\n        <summary>View breakdown</summary>\n        <div>Merkl: {rewards?.merkl.length || 0} rewards</div>\n        <div>URD: {rewards?.urd.length || 0} rewards</div>\n      </details>\n    </div>\n  );\n}\n```\n\n## Running the Demo\n\n### Prerequisites\n\n- Node.js 18+ and yarn\n- A wallet with Morpho positions (for testing user rewards)\n\n### Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/morpho-org/merkl-morpho-recipe.git\ncd merkl-morpho-recipe\n\n# Install dependencies\nyarn install\n\n# Run the development server\nyarn dev\n\n# Open http://localhost:3000\n```\n\n### Explore via Scripts\n\nThe demo includes standalone scripts to understand the data flow:\n\n```bash\n# See vault APY + rewards calculation\nyarn demo:yield\n\n# Check user claimable rewards\nyarn demo:rewards\n\n# Complete integration flow\nyarn demo:full\n```\n\n**Example Output:**\n\n```\n$ yarn demo:yield\n\n=== Vault Metrics ===\nVault: Steakhouse USDC\nBase APY: 8.45%\nRewards APR: 2.13%\nTotal APY: 10.58%\n\nReward Programs:\n  - MORPHO: 1.85% APR\n  - STEAK: 0.28% APR\n```\n\n## Key Takeaways from the Demo\n\n### 1. Error Handling\n\nThe demo implements graceful error handling:\n\n```typescript\ntry {\n  const data = await fetchVaultData(address, chain);\n  return data;\n} catch (error) {\n  console.error(\"Failed to fetch vault data:\", error);\n  return null; // Fallback to null, don't crash the app\n}\n```\n\n### 2. Type Safety\n\nFull TypeScript coverage ensures correctness:\n\n```typescript\nexport interface VaultReward {\n  token: string;\n  apr: number;\n  yearlySupplyTokens: string;\n  tokenAddress: string;\n}\n\nexport interface UserClaimableReward {\n  token: string;\n  amount: bigint;\n  source: \"merkl\" | \"urd\";\n}\n```\n\n### 3. Caching Strategy\n\n```typescript\nconst CACHE_DURATION = 5 * 60 * 1000; // 5 minutes\n\nconst cache = new Map<string, { data: any; timestamp: number }>();\n\nexport function getCached<T>(\n  key: string,\n  fetcher: () => Promise<T>\n): Promise<T> {\n  const cached = cache.get(key);\n\n  if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {\n    return Promise.resolve(cached.data);\n  }\n\n  return fetcher().then((data) => {\n    cache.set(key, { data, timestamp: Date.now() });\n    return data;\n  });\n}\n```\n\n### 4. Simulation Before Execution\n\n```typescript\n// File: src/lib/simulation.ts\nexport async function simulateClaimTransaction(\n  distributorAddress: string,\n  txData: string,\n  userAddress: string\n) {\n  const publicClient = createPublicClient({\n    chain: mainnet,\n    transport: http(),\n  });\n\n  try {\n    await publicClient.call({\n      to: distributorAddress,\n      data: txData,\n      from: userAddress,\n    });\n\n    return { success: true };\n  } catch (error) {\n    return { success: false, error };\n  }\n}\n```\n\n## Adapting the Demo for Production\n\nWhen building on this demo for production, consider:\n\n### Security\n\n- **Never expose private keys**: Use secure wallet connection libraries (RainbowKit, Wagmi, etc.)\n- **Validate all inputs**: Sanitize user addresses, vault addresses, chain IDs\n- **Handle transaction failures**: Implement retry logic with exponential backoff\n- **Rate limiting**: Respect API rate limits and implement client-side throttling\n\n### Performance\n\n- **Lazy load components**: Use React.lazy for routes\n- **Optimize bundle size**: Code split by route and feature\n- **Implement pagination**: For users with many rewards\n- **Use a state management solution**: Redux, Zustand, or React Query for complex state\n\n### User Experience\n\n- **Transaction notifications**: Toast notifications for claim status\n- **Transaction history**: Show past claims\n- **Gas estimation**: Display estimated gas costs before claiming\n\n### Monitoring\n\n- **Error tracking**: Sentry, Bugsnag, or similar\n- **Analytics**: Track claim success rates, popular vaults, etc.\n- **Logging**: Structured logging for debugging\n\n## Next Steps from the Demo\n\nAfter exploring the demo:\n\n1. **Fork and modify**: Adapt it to your use case\n2. **Add wallet connection**: Integrate RainbowKit or ConnectKit\n3. **Customize UI**: Apply your brand's design system\n4. **Deploy**: Vercel, Netlify, or your preferred platform\n\n## Resources\n\n- **Demo Repository**: [github.com/morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe)\n- **Morpho API**: [api.morpho.org/graphql](https://api.morpho.org/graphql)\n- **Merkl Docs**: [docs.merkl.xyz](https://docs.merkl.xyz/)\n- **Rewards API**: [rewards.morpho.org/docs](https://rewards.morpho.org/docs)\n\n**Tutorials**\n\n- [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)\n- [Claim Rewards](/build/rewards/tutorials/claim-rewards)\n- [Integrate Display](/build/rewards/tutorials/integrate-display)"
  },
  "/build/rewards/resources/all/": {
    "title": "Rewards: Developer Resources",
    "url": "https://docs.morpho.org/build/rewards/resources/all/",
    "section": "Build",
    "content": "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.\n\n## APIs\n\n### Morpho API (Recommended for Vault/Market Rewards)\n\nThe Morpho API provides integrated rewards data alongside vault and market information.\n\n-   **GraphQL Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql)\n-   **Documentation**: [Morpho API Docs](/tools/offchain/api/morpho/)\n-   **Rewards Queries**:\n    -   [Morpho Markets Rewards](/tools/offchain/api/rewards/#morpho-markets-rewards)\n    -   [Morpho Vaults Rewards](/tools/offchain/api/rewards/#morpho-vaults-rewards)\n\n**Use Cases:**\n- Fetch vault APY + rewards APR\n- Get market reward rates (supply, borrow, collateral)\n- Combine base yield and rewards in one query\n- Historical data and time-series queries\n\n### Merkl API (Primary for User Rewards)\n\nMerkl's REST API for current reward programs and user claimable amounts.\n\n-   **Base URL**: `https://api.merkl.xyz/v4/`\n-   **Documentation**: [docs.merkl.xyz/integrate-merkl/app](https://docs.merkl.xyz/integrate-merkl/app)\n-   **Key Endpoints**:\n    -   User Rewards: `GET /userRewards?user={address}&chainId={chainId}`\n    -   Claim Data: `GET /claim?user={address}&chainId={chainId}`\n\n**Use Cases:**\n- Fetch user claimable rewards (current programs)\n- Get Merkle proofs for claiming\n- Real-time reward accrual (updates every 8 hours)\n\n### Morpho Rewards API (Legacy URD Programs)\n\nThe Rewards API for historical Morpho URD rewards.\n\n-   **Base URL**: `https://rewards.morpho.org/v1/`\n-   **API Docs**: [rewards.morpho.org/docs](https://rewards.morpho.org/docs)\n-   **Key Endpoints**:\n    -   User Rewards: `GET /users/{address}/rewards`\n    -   User Distributions: `GET /users/{address}/distributions`\n    -   All Programs: `GET /programs`\n    -   Stats: `GET /rewards/stats`\n\n**Use Cases:**\n- Fetch historical/legacy rewards\n- Get URD claim data (Merkle proofs)\n- Query past reward programs\n\n## Smart Contracts\n\n### Merkl Distributor Contracts\n\n**Mainnet (Ethereum):**\n- Address: `0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae`\n\n**Other Chains:**\n- See [Merkl's documentation](https://docs.merkl.xyz/) for all chain deployments\n\n**Key Functions:**\n- `claim(address user, address[] tokens, uint256[] amounts, bytes32[][] proofs)` - Claim rewards\n\n### Morpho URD Contracts\n\n**Mainnet (Ethereum):**\n- URD Address: `0x330eefa8a787552DC5cAd3C3cA644844B1E61Ddb`\n\n**Other Chains:**\n- See [Rewards Addresses](/get-started/resources/addresses/#rewards) for all deployments\n\n**Key Functions:**\n- `claim(address account, address reward, uint256 claimable, bytes32[] proof)` - Claim rewards\n- `claimed(address account, address reward) view returns (uint256)` - Check claimed amount\n\n**Repository:**\n- GitHub: [morpho-org/universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor)\n\n### Contract ABIs\n\n**Merkl Distributor ABI:**\n```json\n[\n  {\n    \"inputs\": [\n      { \"name\": \"user\", \"type\": \"address\" },\n      { \"name\": \"tokens\", \"type\": \"address[]\" },\n      { \"name\": \"amounts\", \"type\": \"uint256[]\" },\n      { \"name\": \"proofs\", \"type\": \"bytes32[][]\" }\n    ],\n    \"name\": \"claim\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  }\n]\n```\n\n**URD ABI (Claim):**\n```json\n[\n  {\n    \"inputs\": [\n      { \"name\": \"account\", \"type\": \"address\" },\n      { \"name\": \"reward\", \"type\": \"address\" },\n      { \"name\": \"claimable\", \"type\": \"uint256\" },\n      { \"name\": \"proof\", \"type\": \"bytes32[]\" }\n    ],\n    \"name\": \"claim\",\n    \"outputs\": [{ \"name\": \"amount\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"name\": \"account\", \"type\": \"address\" },\n      { \"name\": \"reward\", \"type\": \"address\" }\n    ],\n    \"name\": \"claimed\",\n    \"outputs\": [{ \"name\": \"\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  }\n]\n```\n\n## Code Examples & Repositories\n\n### Official Examples\n\n-   **Merkl + Morpho Recipe** (Recommended):\n    -   GitHub: [morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe)\n    -   A complete Next.js demo showing:\n        -   Vault metrics with rewards\n        -   User claimable rewards (Merkl + URD)\n        -   Claim implementations\n        -   TypeScript best practices\n\n### Community Examples\n\n-   **Morpho Lite App**: [morpho-org/morpho-lite-apps](https://github.com/morpho-org/morpho-lite-apps/tree/main/apps/lite)\n-   **Fallback App**: [morpho-org/morpho-blue-offchain-public](https://github.com/morpho-org/morpho-blue-offchain-public/tree/main/apps/fallback)\n\n## SDKs & Tools\n\n### Morpho SDKs\n\nWhile there's no dedicated rewards SDK, you can use Morpho's core SDKs for related functionality:\n\n-   **`@morpho-org/blue-sdk`**: Core SDK for vaults and markets\n-   **`@morpho-org/blue-sdk-viem`**: Viem-based fetchers\n-   **`@morpho-org/simulation-sdk`**: Simulate transactions\n\n**Learn More**: [Morpho SDKs Documentation](/tools/offchain/sdks/get-started/)\n\n### GraphQL Clients\n\nFor querying the Morpho API:\n\n-   **[graphql-request](https://github.com/jasonkuhrt/graphql-request)**: Lightweight GraphQL client\n-   **[Apollo Client](https://www.apollographql.com/docs/react/)**: Full-featured GraphQL client\n-   **[urql](https://formidable.com/open-source/urql/)**: Flexible GraphQL client\n\n### Web3 Libraries\n\nFor claiming rewards onchain:\n\n-   **[viem](https://viem.sh/)**: Modern TypeScript web3 library (recommended)\n-   **[ethers.js](https://docs.ethers.org/)**: Popular web3 library\n-   **[web3.js](https://web3js.readthedocs.io/)**: Classic web3 library\n\n## External Documentation\n\n### Merkl\n\n-   **Official Docs**: [docs.merkl.xyz](https://docs.merkl.xyz/)\n-   **Integration Guide**: [docs.merkl.xyz/integrate-merkl/app](https://docs.merkl.xyz/integrate-merkl/app)\n\n### Morpho\n\n-   **Developer Hub**: [/tools/](/tools/)\n-   **API Documentation**: [/tools/offchain/api/rewards/](/tools/offchain/api/rewards/)\n\n## Onchain Data Sources\n\n-   **Morpho Subgraphs**: [/tools/offchain/subgraphs/](/tools/offchain/subgraphs/)\n-   **Merkl Subgraphs**: See [Merkl docs](https://docs.merkl.xyz/)\n\n## Tutorials & Guides\n\n### Getting Started\n\n-   [Rewards Integration Overview](/build/rewards/get-started)\n-   [Understanding Reward Programs](/build/rewards/concepts/reward-campaigns)\n-   [Distribution Systems (Merkl vs URD)](/build/rewards/concepts/distribution-system)\n\n### Step-by-Step Tutorials\n\n-   [Create a Rewards Program](/build/rewards/tutorials/create-program)\n-   [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data)\n-   [Claim Rewards](/build/rewards/tutorials/claim-rewards)\n-   [Integrate Rewards Display](/build/rewards/tutorials/integrate-display)\n\n### Advanced\n\n-   [Complete Integration Example](/build/rewards/guides/complete-integration)\n-   [URD Technical Details](/get-started/resources/contracts/rewards/)\n\n## Support Channels\n\n### For Integrators\n\n-   **Technical Questions**: [help.morpho.org](https://help.morpho.org)\n\n### For Reward Issuers\n\n-   **Program Creation Help**: [Merkl Docs](https://docs.merkl.xyz/)\n\n## Monitoring & Analytics\n\n### Dashboards\n\n-   **Merkl Dashboard**: [merkl.xyz](https://merkl.xyz/) - View active campaigns\n-   **Morpho App**: [app.morpho.org](https://app.morpho.org) - See rewards on vaults/markets\n\n### Analytics Tools\n\n-   **Dune Analytics**: [Morpho Dashboards](/tools/offchain/dune/)\n-   **DefiLlama**: Track TVL and yields across Morpho\n\n## Governance & Updates\n\n### Morpho Governance\n\n-   **Snapshot**: [snapshot.box/#/s:morpho.eth](https://snapshot.box/#/s:morpho.eth)\n\n### Migration Information\n\n-   **MIP 111**: [Snapshot Proposal](https://snapshot.box/#/s:morpho.eth/proposal/0xadf3862d97cf4e8bb84a4b3d5117abe1a9db774e92ad97c65bde22214c0b76c9) - Migration to Merkl\n\n## Quick Reference\n\n| Resource | Link |\n|----------|------|\n| **Morpho API** | [api.morpho.org/graphql](https://api.morpho.org/graphql) |\n| **Merkl API** | [api.merkl.xyz/v4](https://api.merkl.xyz/v4/) |\n| **Rewards API** | [rewards.morpho.org](https://rewards.morpho.org) |\n| **Example Code** | [github.com/morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe) |\n| **Merkl Docs** | [docs.merkl.xyz](https://docs.merkl.xyz/) |\n| **URD Contracts** | [github.com/morpho-org/universal-rewards-distributor](https://github.com/morpho-org/universal-rewards-distributor) |\n\n## Need Help?\n\nIf you can't find what you're looking for, reach out via:\n\n-   **Chat**: [help.morpho.org](https://help.morpho.org)"
  },
  "/build/rewards/tutorials/claim-rewards/": {
    "title": "Claim Rewards",
    "url": "https://docs.morpho.org/build/rewards/tutorials/claim-rewards/",
    "section": "Build",
    "content": "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.\n\n## Overview\n\nClaiming rewards involves:\n1. Fetching claim data (proof + transaction data) from the appropriate API\n2. Constructing or using pre-formatted transaction calldata\n3. Submitting the claim transaction onchain\n4. Handling the response and updating your UI\n\nThe process is similar for both Merkl and URD, but they use different APIs and smart contracts.\n\n## Prerequisites\n\n- Understanding of [Distribution Systems](/build/rewards/concepts/distribution-system)\n- Familiarity with [Fetching Rewards Data](/build/rewards/tutorials/fetch-rewards-data)\n- A web3 library (viem, ethers, web3.js)\n- User's wallet connected to your app\n\n## Claiming via Merkl\n\nMerkl is the primary distribution system for current reward programs.\n\n### Step 1: Fetch Claim Data\n\n**Endpoint:**\n```\nGET https://api.merkl.xyz/v4/claim?user={address}&chainId={chainId}\n```\n\n**Example:**\n```typescript\nasync function fetchMerklClaimData(\n  userAddress: string,\n  chainId: number\n): Promise<MerklClaimData> {\n  const response = await fetch(\n    `https://api.merkl.xyz/v4/claim?user=${userAddress}&chainId=${chainId}`\n  );\n\n  if (!response.ok) {\n    throw new Error(`Merkl API error: ${response.status}`);\n  }\n\n  return response.json();\n}\n```\n\n**Response Structure:**\n```json\n{\n  \"claim\": {\n    \"user\": \"0x...\",\n    \"tokens\": [\"0xTOKEN1\", \"0xTOKEN2\"],\n    \"amounts\": [\"1000000000000000000\", \"2000000000000000000\"],\n    \"proofs\": [\n      [\"0xproof1a\", \"0xproof1b\"],\n      [\"0xproof2a\", \"0xproof2b\"]\n    ]\n  }\n}\n```\n\n### Step 2: Execute the Claim\n\nUsing **viem**:\n\n```typescript\nimport { createWalletClient, custom } from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\nconst MERKL_DISTRIBUTOR = \"0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae\"; // Mainnet\n\nasync function claimMerklRewards(\n  userAddress: string,\n  chainId: number\n) {\n  // 1. Fetch claim data\n  const claimData = await fetchMerklClaimData(userAddress, chainId);\n\n  // 2. Setup wallet client\n  const walletClient = createWalletClient({\n    account: userAddress,\n    chain: mainnet,\n    transport: custom(window.ethereum),\n  });\n\n  // 3. Send claim transaction\n  const hash = await walletClient.writeContract({\n    address: MERKL_DISTRIBUTOR,\n    abi: MERKL_ABI,\n    functionName: \"claim\",\n    args: [\n      claimData.claim.user,\n      claimData.claim.tokens,\n      claimData.claim.amounts,\n      claimData.claim.proofs,\n    ],\n  });\n\n  // 4. Wait for confirmation\n  const receipt = await walletClient.waitForTransactionReceipt({ hash });\n\n  return receipt;\n}\n\n// Merkl Distributor ABI (claim function)\nconst MERKL_ABI = [\n  {\n    inputs: [\n      { name: \"user\", type: \"address\" },\n      { name: \"tokens\", type: \"address[]\" },\n      { name: \"amounts\", type: \"uint256[]\" },\n      { name: \"proofs\", type: \"bytes32[][]\" },\n    ],\n    name: \"claim\",\n    outputs: [],\n    stateMutability: \"nonpayable\",\n    type: \"function\",\n  },\n] as const;\n```\n\n### Step 3: Handle the Result\n\n```typescript\ntry {\n  const receipt = await claimMerklRewards(userAddress, 1);\n\n  if (receipt.status === \"success\") {\n    console.log(\"✅ Merkl rewards claimed successfully!\");\n    // Update your UI to reflect claimed rewards\n  } else {\n    console.error(\"❌ Claim transaction failed\");\n  }\n} catch (error) {\n  console.error(\"Error claiming Merkl rewards:\", error);\n  // Show error message to user\n}\n```\n\nFor more details on Merkl claiming, see the [official Merkl documentation](https://docs.merkl.xyz/integrate-merkl/app#claiming-user-rewards).\n\n## Claiming via Morpho URD - Legacy distributions\n\nThe URD handles legacy reward programs. While new programs use Merkl, many users still have unclaimed URD rewards.\n\n### Step 1: Fetch Distribution Data\n\n**Endpoint:**\n```\nGET https://rewards.morpho.org/v1/users/{address}/distributions\n```\n\n**Example:**\n```typescript\ninterface URDDistribution {\n  user: string;\n  distributor: string;  // URD contract address\n  chain_id: number;\n  asset: {\n    address: string;\n    symbol: string;\n  };\n  claimable: string;  // Cumulative amount\n  proof: string[];\n  tx_data: string;  // Pre-formatted calldata\n}\n\nasync function fetchURDDistributions(\n  userAddress: string\n): Promise<URDDistribution[]> {\n  const response = await fetch(\n    `https://rewards.morpho.org/v1/users/${userAddress}/distributions`\n  );\n\n  if (!response.ok) {\n    throw new Error(`Rewards API error: ${response.status}`);\n  }\n\n  return response.json();\n}\n```\n\n**Response Structure:**\n```json\n[\n  {\n    \"user\": \"0x...\",\n    \"distributor\": \"0x330eefa8a787552DC5cAd3C3cA644844B1E61Ddb\",\n    \"chain_id\": 1,\n    \"asset\": {\n      \"address\": \"0x58D97B57BB95320F9a05dC918Aef65434969c2B2\",\n      \"symbol\": \"MORPHO\"\n    },\n    \"claimable\": \"115631364898103632676\",\n    \"proof\": [\"0x1a2b...\", \"0x3c4d...\"],\n    \"tx_data\": \"0x4e71d92d...\"\n  }\n]\n```\n\n### Step 2: Check Already-Claimed Amount\n\nBefore claiming, verify how much the user has already claimed to avoid unnecessary transactions:\n\n```typescript\nimport { createPublicClient, http } from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\nconst URD_ABI = [\n  {\n    inputs: [\n      { name: \"account\", type: \"address\" },\n      { name: \"reward\", type: \"address\" },\n    ],\n    name: \"claimed\",\n    outputs: [{ name: \"\", type: \"uint256\" }],\n    stateMutability: \"view\",\n    type: \"function\",\n  },\n] as const;\n\nasync function getClaimedAmount(\n  distributorAddress: string,\n  userAddress: string,\n  rewardTokenAddress: string\n): Promise<bigint> {\n  const publicClient = createPublicClient({\n    chain: mainnet,\n    transport: http(),\n  });\n\n  const claimed = await publicClient.readContract({\n    address: distributorAddress as `0x${string}`,\n    abi: URD_ABI,\n    functionName: \"claimed\",\n    args: [userAddress as `0x${string}`, rewardTokenAddress as `0x${string}`],\n  });\n\n  return claimed;\n}\n```\n\n### Step 3: Execute the Claim\n\nUsing Pre-formatted `tx_data`\n\nThe API provides ready-to-use transaction calldata:\n\n```typescript\nasync function claimURDRewards(distribution: URDDistribution) {\n  // 1. Check if there's anything to claim\n  const alreadyClaimed = await getClaimedAmount(\n    distribution.distributor,\n    distribution.user,\n    distribution.asset.address\n  );\n\n  const claimable = BigInt(distribution.claimable);\n\n  if (alreadyClaimed >= claimable) {\n    console.log(\"Nothing to claim (already claimed)\");\n    return null;\n  }\n\n  // 2. Setup wallet client\n  const walletClient = createWalletClient({\n    account: distribution.user as `0x${string}`,\n    chain: mainnet,\n    transport: custom(window.ethereum),\n  });\n\n  // 3. Send transaction with pre-formatted data\n  const hash = await walletClient.sendTransaction({\n    to: distribution.distributor as `0x${string}`,\n    data: distribution.tx_data as `0x${string}`,\n  });\n\n  // 4. Wait for confirmation\n  const receipt = await walletClient.waitForTransactionReceipt({ hash });\n\n  return receipt;\n}\n```\n\n## Resources\n\n- **Merkl Claim Docs**: [docs.merkl.xyz/integrate-merkl/app#claiming-user-rewards](https://docs.merkl.xyz/integrate-merkl/app#claiming-user-rewards)\n- **Rewards API**: [rewards.morpho.org/docs](https://rewards.morpho.org/docs)\n- **Example Code**: [morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe)"
  },
  "/build/rewards/tutorials/create-program/": {
    "title": "Create a Rewards Program",
    "url": "https://docs.morpho.org/build/rewards/tutorials/create-program/",
    "section": "Build",
    "content": "This tutorial guides you through creating a new rewards program for Morpho Vaults or Markets using **Merkl**, the current standard for reward distribution.\n\n**Target Audience**  \nThis tutorial is for:\n- Protocol teams looking to incentivize specific Morpho Markets or Vaults\n- DAOs planning reward campaigns\n- Token issuers wanting to boost liquidity in Morpho\n- Projects building on top of Morpho\n\n## Prerequisites\n\nBefore creating a rewards program, ensure you have:\n\n- [ ] A clear incentive strategy (what behavior do you want to encourage?)\n- [ ] Reward tokens ready for distribution\n- [ ] Knowledge of target Morpho Markets or Vaults\n- [ ] A wallet with funds to deposit reward tokens\n- [ ] Understanding of [Reward Program Types](/build/rewards/concepts/reward-campaigns)\n\n## Overview: Merkl for Rewards Programs\n\n[Merkl](https://merkl.xyz/) is the standard distribution system for Morpho rewards. It provides:\n\n- **Automated Distribution**: Rewards calculated and distributed every 8 hours\n- **Flexible Configuration**: Target specific markets, vaults, or user groups\n- **Multi-Chain Support**: Works across all chains where Morpho is deployed\n- **Transparent Tracking**: Real-time visibility into reward distribution\n\n## Creating a Program via Merkl\n\nMerkl provides a user-friendly interface for creating reward campaigns. The process differs slightly between Vault and Market programs.\n\n#### Jump on the studio\n\nhttps://studio.merkl.xyz/create-campaign/lend\n\n#### Select `Morpho` as protocol\n\n  \n\n#### Fill the inputs as per Merkl doc \n\n## Next Steps\n\n- **Fetch campaign data**: Follow the [Fetch Rewards Data tutorial](/build/rewards/tutorials/fetch-rewards-data)\n- **Integrate display**: Check out the [Integrate Display tutorial](/build/rewards/tutorials/integrate-display)\n- **Enable claiming**: See the [Claim Rewards tutorial](/build/rewards/tutorials/claim-rewards)"
  },
  "/build/rewards/tutorials/fetch-rewards-data/": {
    "title": "Fetch Rewards Data",
    "url": "https://docs.morpho.org/build/rewards/tutorials/fetch-rewards-data/",
    "section": "Build",
    "content": "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.\n\n## What You'll Learn\n\n- How to fetch vault and market reward rates from Morpho API\n- How to query user-specific rewards from Merkl API\n- How to get historical reward data from Morpho Rewards API (URD)\n- How to combine data from multiple sources for a complete picture\n\n## Prerequisites\n\n- Basic understanding of [Reward Programs](/build/rewards/concepts/reward-campaigns)\n- Familiarity with REST and GraphQL APIs\n- A tool for making API requests (curl, fetch, axios, or GraphQL client)\n\n## API Landscape Overview\n\nThere are **three main APIs** for rewards data:\n\n| API | Use Case | Rewards Type | Data Provided |\n|-----|----------|--------------|---------------|\n| **Morpho API** | Vault/Market reward rates | Both Merkl & Old URD | APRs, reward token info, integrated with vault/market data |\n| **Merkl API** | User claimable rewards | Merkl only | User balances, claim data, real-time rewards |\n| **Rewards API** | Historical rewards | URD only | Legacy programs, distributions, claim data |\n\n**Recommended Strategy:**\n1. Use **Morpho API** for displaying reward APRs on vaults/markets (easiest integration)\n2. Use **Merkl API** for user-specific Merkl rewards\n3. Use **Rewards API** for user-specific URD (legacy) rewards\n\n## Fetching Vault Rewards\n\n### Using Morpho API (Recommended)\n\nVault rewards come from **two sources** that must be queried and aggregated manually:\n1. **Vault-level rewards**: Direct campaigns targeting the vault\n2. **Market-level rewards**: Forwarded from markets where the vault allocates\n\n#### Query Complete Vault Rewards\n\n```graphql\nquery VaultRewards($address: String!, $chainId: Int!) {\n  vaultByAddress(address: $address, chainId: $chainId) {\n    address\n    name\n    symbol\n    state {\n      apy\n      netApy  # Convenience field: complete APY including rewards\n\n      # Vault-level rewards (direct)\n      rewards {\n        supplyApr\n        yearlySupplyTokens\n        asset {\n          address\n          symbol\n          priceUsd\n          chain { id }\n        }\n      }\n\n      # Market-level rewards (forwarded from allocations)\n      allocation {\n        supplyAssetsUsd  # Required for weighted average\n        market {\n          uniqueKey\n          loanAsset { symbol }\n          collateralAsset { symbol }\n          state {\n            rewards {\n              supplyApr\n              asset {\n                address\n                symbol\n                priceUsd\n                chain { id }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n**Variables:**\n```json\n{\n  \"address\": \"0x9aB2d181E4b87ba57D5eD564D3eF652C4E710707\",\n  \"chainId\": 8453\n}\n```\n\n#### Calculate Total Rewards APR\n\nVault rewards require **manual aggregation** with weighted averaging:\n\n```typescript\nconst vault = response.data.vaultByAddress;\n\n// 1. Sum vault-level rewards\nconst vaultRewardsApr = vault.state.rewards.reduce(\n  (sum, r) => sum + parseFloat(r.supplyApr),\n  0\n);\n\n// 2. Calculate weighted average of market-level rewards\nconst totalAllocatedUsd = vault.state.allocation.reduce(\n  (sum, alloc) => sum + parseFloat(alloc.supplyAssetsUsd),\n  0\n);\n\nconst marketRewardsApr = vault.state.allocation.reduce((sum, alloc) => {\n  const marketRewards = alloc.market.state.rewards.reduce(\n    (marketSum, r) => marketSum + parseFloat(r.supplyApr),\n    0\n  );\n  const weight = parseFloat(alloc.supplyAssetsUsd) / totalAllocatedUsd;\n  return sum + (marketRewards * weight);\n}, 0);\n\n// 3. Total rewards APR\nconst totalRewardsApr = vaultRewardsApr + marketRewardsApr;\n\nconsole.log(`Base APY: ${vault.state.apy}%`);\nconsole.log(`Vault Rewards APR: ${vaultRewardsApr}%`);\nconsole.log(`Market Rewards APR: ${marketRewardsApr}%`);\nconsole.log(`Total APY: ${parseFloat(vault.state.apy) + totalRewardsApr}%`);\n```\n\n#### Alternative: Use Convenience Fields\n\nFor simple total APY display without breakdown:\n\n```typescript\nconst vault = response.data.vaultByAddress;\nconst netApy = parseFloat(vault.state.netApy);  // Pre-calculated complete APY\n\nconsole.log(`Total APY: ${netApy}%`);\n```\n\n**Important Notes:**\n- Vault rewards are in **two separate API locations**: `state.rewards` and `state.allocation[].market.state.rewards`\n- Manual weighted average calculation is required for market rewards\n- Use `supplyAssetsUsd` from allocations to calculate weights\n- Convenience field `netApy` includes all components but doesn't provide breakdown\n\n## Fetching Market Rewards\n\nMarkets can have rewards for **supply** and **borrow**.\n\n### Using Morpho API\n\n```graphql\nquery MarketRewards($uniqueKey: String!) {\n  markets(where: { uniqueKey: $uniqueKey }) {\n    items {\n      uniqueKey\n      loanAsset {\n        symbol\n      }\n      collateralAsset {\n        symbol\n      }\n      state {\n        borrowApy\n        supplyApy\n        rewards {\n          supplyApr\n          borrowApr\n          asset {\n            address\n            symbol\n            priceUsd\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n**Key Fields:**\n- `supplyApr`: Reward APR for suppliers\n- `borrowApr`: Reward APR for borrowers (often negative, meaning borrowers earn rewards)\n\n## Fetching User-Specific Rewards\n\n### Merkl API (Current Programs)\n\nTo get a user's claimable Merkl rewards:\n\n**Endpoint:**\n```\nGET https://api.merkl.xyz/v4/userRewards?user={address}\n```\n\n**Example:**\n```bash\ncurl \"https://api.merkl.xyz/v4/userRewards?user=0x1234...5678\"\n```\n\n**Response Structure:**\n```json\n{\n  \"1\": {  // Chain ID\n    \"0xVAULT_OR_MARKET_ADDRESS\": {\n      \"claimable\": {\n        \"0xREWARD_TOKEN_ADDRESS\": {\n          \"accumulated\": \"1234567890\",\n          \"unclaimed\": \"1234567890\",\n          \"symbol\": \"MORPHO\",\n          \"decimals\": 18\n        }\n      }\n    }\n  }\n}\n```\n\n**TypeScript Example:**\n```typescript\nasync function fetchMerklRewards(userAddress: string) {\n  const response = await fetch(\n    `https://api.merkl.xyz/v4/userRewards?user=${userAddress}`\n  );\n  const data = await response.json();\n\n  // Parse rewards by chain\n  const chainId = 1; // Ethereum mainnet\n  const rewards = data[chainId] || {};\n\n  // Aggregate all claimable rewards\n  const claimableByToken: Record<string, bigint> = {};\n\n  for (const [campaignAddress, campaignData] of Object.entries(rewards)) {\n    for (const [tokenAddress, tokenData] of Object.entries(\n      campaignData.claimable || {}\n    )) {\n      const unclaimed = BigInt(tokenData.unclaimed || \"0\");\n      claimableByToken[tokenAddress] =\n        (claimableByToken[tokenAddress] || 0n) + unclaimed;\n    }\n  }\n\n  return claimableByToken;\n}\n```\n\n### Morpho Rewards API (Legacy URD Programs)\n\nTo get a user's URD rewards:\n\n**Endpoint:**\n```\nGET https://rewards.morpho.org/v1/users/{address}/rewards\n```\n\n**Example:**\n```bash\ncurl \"https://rewards.morpho.org/v1/users/0x0ec553110e53122d1226646670a8475D4C8E6F04/rewards\"\n```\n\n**Response Structure:**\n```json\n[\n  {\n    \"user\": \"0x0ec553110e53122d1226646670a8475D4C8E6F04\",\n    \"type\": \"uniform-reward\",\n    \"asset\": {\n      \"id\": \"0x58D97B57BB95320F9a05dC918Aef65434969c2B2-1\",\n      \"address\": \"0x58D97B57BB95320F9a05dC918Aef65434969c2B2\",\n      \"chain_id\": 1\n    },\n    \"program_id\": \"0x5068...\",\n    \"amount\": {\n      \"total\": \"115631364898103632676\",\n      \"claimable_now\": \"22676259927164556632\",\n      \"claimable_next\": \"1688912463745536463\",\n      \"claimed\": \"91266192507193539581\"\n    }\n  }\n]\n```\n\n**Key Fields:**\n- `claimable_now`: Available to claim right now\n- `claimable_next`: Will become claimable in next epoch\n- `claimed`: Already claimed by user\n- `total`: Sum of all the above\n\n**TypeScript Example:**\n```typescript\nasync function fetchURDRewards(userAddress: string) {\n  const response = await fetch(\n    `https://rewards.morpho.org/v1/users/${userAddress}/rewards`\n  );\n  const rewards = await response.json();\n\n  // Aggregate claimable by token\n  const claimableByToken: Record<string, bigint> = {};\n\n  for (const reward of rewards) {\n    const tokenAddress = reward.asset.address;\n    const claimable = BigInt(reward.amount.claimable_now);\n\n    claimableByToken[tokenAddress] =\n      (claimableByToken[tokenAddress] || 0n) + claimable;\n  }\n\n  return claimableByToken;\n}\n```\n\n## Combining Data from Multiple Sources\n\nTo show a complete rewards picture, you'll need to combine data from Merkl and URD:\n\n```typescript\nasync function fetchAllUserRewards(userAddress: string) {\n  // Fetch from both sources in parallel\n  const [merklRewards, urdRewards] = await Promise.all([\n    fetchMerklRewards(userAddress),\n    fetchURDRewards(userAddress),\n  ]);\n\n  // Combine by token address\n  const allRewards: Record<string, {\n    merkl: bigint;\n    urd: bigint;\n    total: bigint;\n  }> = {};\n\n  // Add Merkl rewards\n  for (const [token, amount] of Object.entries(merklRewards)) {\n    allRewards[token] = allRewards[token] || { merkl: 0n, urd: 0n, total: 0n };\n    allRewards[token].merkl = amount;\n    allRewards[token].total += amount;\n  }\n\n  // Add URD rewards\n  for (const [token, amount] of Object.entries(urdRewards)) {\n    allRewards[token] = allRewards[token] || { merkl: 0n, urd: 0n, total: 0n };\n    allRewards[token].urd = amount;\n    allRewards[token].total += amount;\n  }\n\n  return allRewards;\n}\n```\n\n## Performance Considerations\n\n### Caching\n\n**Vault/Market Rewards (Morpho API):**\n- Cache for 5-15 minutes\n- Rewards rates change infrequently\n\n**User Merkl Rewards:**\n- Cache for 5-10 minutes\n- Updates every 8 hours, but users expect fresh data\n\n### Parallel Fetching\n\nAlways fetch from multiple APIs in parallel:\n\n```typescript\nconst [vaultData, merklRewards, urdRewards] = await Promise.all([\n  fetchVaultFromMorphoAPI(vaultAddress),\n  fetchMerklRewards(userAddress),\n  fetchURDRewards(userAddress),\n]);\n```\n\n### Error Handling\n\n```typescript\nasync function fetchRewardsSafely(userAddress: string) {\n  try {\n    const merkl = await fetchMerklRewards(userAddress);\n  } catch (error) {\n    console.error(\"Merkl API error:\", error);\n    merkl = {}; // Fallback to empty\n  }\n\n  try {\n    const urd = await fetchURDRewards(userAddress);\n  } catch (error) {\n    console.error(\"URD API error:\", error);\n    urd = {}; // Fallback to empty\n  }\n\n  return { merkl, urd };\n}\n```\n\n## API Rate Limits\n\nBe mindful of rate limits:\n\n| API | Rate Limit | Notes |\n|-----|------------|-------|\n| Morpho API | 2k / 5 min | Use responsibly |\n| Merkl API | Unknown, likely generous | Cache responses |\n| Rewards API | 850 / min | Avoid excessive polling |\n\n**Best Practice:** Cache aggressively and fetch only when needed.\n\n## Next Steps\n\n- **Display rewards**: Follow the [Integrate Display tutorial](/build/rewards/tutorials/integrate-display)\n- **Enable claiming**: See the [Claim Rewards tutorial](/build/rewards/tutorials/claim-rewards)\n- **Full example**: Check out the [Complete Integration Guide](/build/rewards/guides/complete-integration)\n\n## Resources\n\n- **Morpho API Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql)\n- **Merkl Docs**: [docs.merkl.xyz/integrate-merkl/app](https://docs.merkl.xyz/integrate-merkl/app)\n- **Rewards API Docs**: [rewards.morpho.org/docs](https://rewards.morpho.org/docs)\n- **Example Code**: [morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe)"
  },
  "/build/rewards/tutorials/integrate-display/": {
    "title": "Integrate Rewards Display",
    "url": "https://docs.morpho.org/build/rewards/tutorials/integrate-display/",
    "section": "Build",
    "content": "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.\n\n## What to Display\n\nA complete rewards integration should show:\n\n1. **Vault/Market Level Rewards** - The APR users can earn\n2. **User Claimable Rewards** - How much users have earned and can claim\n3. **Combined APY/APR** - Total yield including base + rewards\n4. **Reward Token Information** - What tokens are being distributed\n5. **Claim Status** - What's claimable now vs. pending\n\n## Displaying Vault Rewards\n\n### Fetching and Calculating Total APY\n\n```typescript\nimport { GraphQLClient, gql } from \"graphql-request\";\n\nconst client = new GraphQLClient(\"https://api.morpho.org/graphql\");\n\nasync function getVaultWithRewards(vaultAddress: string, chainId: number) {\n  const query = gql`\n    query VaultRewards($address: String!, $chainId: Int!) {\n      vaults(where: { address: $address, chainId: $chainId }) {\n        items {\n          address\n          name\n          symbol\n          asset {\n            symbol\n          }\n          state {\n            apy\n            totalAssets\n            rewards {\n              yearlySupplyTokens\n              supplyApr\n              asset {\n                address\n                symbol\n                priceUsd\n              }\n            }\n          }\n        }\n      }\n    }\n  `;\n\n  const response = await client.request(query, {\n    address: vaultAddress,\n    chainId,\n  });\n\n  const vault = response.vaults.items[0];\n\n  return {\n    vault: vault.name,\n    symbol: vault.symbol,\n    asset: vault.asset.symbol,\n    baseApy: parseFloat(vault.state.apy),\n    rewardsApr: vault.state.rewards.reduce(\n      (sum, r) => sum + parseFloat(r.supplyApr),\n      0\n    ),\n    totalApy:\n      parseFloat(vault.state.apy) +\n      vault.state.rewards.reduce((sum, r) => sum + parseFloat(r.supplyApr), 0),\n    rewards: vault.state.rewards.map((r) => ({\n      token: r.asset.symbol,\n      apr: parseFloat(r.supplyApr),\n      tokenAddress: r.asset.address,\n    })),\n  };\n}\n```\n\n### React Component Example\n\n```tsx\nimport React, { useEffect, useState } from \"react\";\n\ninterface VaultRewardsDisplayProps {\n  vaultAddress: string;\n  chainId: number;\n}\n\nfunction VaultRewardsDisplay({ vaultAddress, chainId }: VaultRewardsDisplayProps) {\n  const [data, setData] = useState<any>(null);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    getVaultWithRewards(vaultAddress, chainId)\n      .then(setData)\n      .finally(() => setLoading(false));\n  }, [vaultAddress, chainId]);\n\n  if (loading) return <div>Loading...</div>;\n  if (!data) return <div>No data</div>;\n\n  return (\n    <div className=\"vault-rewards\">\n      <h2>{data.vault}</h2>\n      <p className=\"asset\">Deposit {data.asset}</p>\n\n      {/* Total APY */}\n      <div className=\"apy-display\">\n        <h3>Total APY: {data.totalApy.toFixed(2)}%</h3>\n        <div className=\"breakdown\">\n          <div>Base APY: {data.baseApy.toFixed(2)}%</div>\n          <div>Rewards APR: +{data.rewardsApr.toFixed(2)}%</div>\n        </div>\n      </div>\n\n      {/* Rewards Breakdown */}\n      {data.rewards.length > 0 && (\n        <div className=\"rewards-breakdown\">\n          <h4>Reward Programs:</h4>\n          {data.rewards.map((reward) => (\n            <div key={reward.tokenAddress} className=\"reward-item\">\n              <span>{reward.token}</span>\n              <span>{reward.apr.toFixed(2)}% APR</span>\n            </div>\n          ))}\n        </div>\n      )}\n    </div>\n  );\n}\n```\n\n### Visual Design Tips\n\n**Highlight Total Yield:**\n```tsx\n<div className=\"total-apy\">\n  <span className=\"label\">Total APY</span>\n  <span className=\"value\">{totalApy.toFixed(2)}%</span>\n</div>\n```\n\n**Show Breakdown on Hover/Click:**\n```tsx\n<Tooltip content={\n  <div>\n    <div>Base APY: {baseApy}%</div>\n    <div>MORPHO Rewards: +{morphoApr}%</div>\n    <div>Partner Rewards: +{partnerApr}%</div>\n  </div>\n}>\n  <span className=\"apy\">{totalApy}%</span>\n</Tooltip>\n```\n\n**Use Badges for Rewards:**\n```tsx\n{rewards.length > 0 && (\n  <span className=\"rewards-badge\">\n    +{rewardsApr.toFixed(1)}% Rewards\n  </span>\n)}\n```\n\n## Displaying User Claimable Rewards\n\n### Fetching User Rewards from Both Systems\n\n```typescript\nasync function getUserAllClaimableRewards(userAddress: string, chainId: number) {\n  const [merklRewards, urdRewards] = await Promise.all([\n    fetchMerklClaimable(userAddress, chainId),\n    fetchURDClaimable(userAddress),\n  ]);\n\n  return {\n    merkl: merklRewards,\n    urd: urdRewards,\n    total: combineRewards(merklRewards, urdRewards),\n  };\n}\n\nasync function fetchMerklClaimable(userAddress: string, chainId: number) {\n  const response = await fetch(\n    `https://api.merkl.xyz/v4/userRewards?user=${userAddress}&chainId=${chainId}`\n  );\n  const data = await response.json();\n\n  const claimable: Array<{ token: string; amount: bigint; symbol: string }> = [];\n\n  for (const [campaignAddr, campaignData] of Object.entries(data[chainId] || {})) {\n    for (const [tokenAddr, tokenData] of Object.entries(\n      campaignData.claimable || {}\n    )) {\n      claimable.push({\n        token: tokenAddr,\n        amount: BigInt(tokenData.unclaimed || \"0\"),\n        symbol: tokenData.symbol,\n      });\n    }\n  }\n\n  return claimable;\n}\n\nasync function fetchURDClaimable(userAddress: string) {\n  const response = await fetch(\n    `https://rewards.morpho.org/v1/users/${userAddress}/rewards`\n  );\n  const rewards = await response.json();\n\n  return rewards.map((r) => ({\n    token: r.asset.address,\n    amount: BigInt(r.amount.claimable_now),\n    symbol: r.asset.symbol || \"Unknown\",\n  }));\n}\n\nfunction combineRewards(merkl: any[], urd: any[]) {\n  const combined: Record<string, { token: string; amount: bigint; symbol: string }> = {};\n\n  [...merkl, ...urd].forEach((reward) => {\n    if (!combined[reward.token]) {\n      combined[reward.token] = { ...reward };\n    } else {\n      combined[reward.token].amount += reward.amount;\n    }\n  });\n\n  return Object.values(combined);\n}\n```\n\n### React Component for User Rewards\n\n```tsx\nimport { formatUnits } from \"viem\";\n\nfunction UserRewardsDisplay({ userAddress, chainId }: {\n  userAddress: string;\n  chainId: number;\n}) {\n  const [rewards, setRewards] = useState<any>(null);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    getUserAllClaimableRewards(userAddress, chainId)\n      .then(setRewards)\n      .finally(() => setLoading(false));\n  }, [userAddress, chainId]);\n\n  if (loading) return <div>Loading rewards...</div>;\n  if (!rewards || rewards.total.length === 0) {\n    return <div>No claimable rewards</div>;\n  }\n\n  return (\n    <div className=\"user-rewards\">\n      <h3>Your Claimable Rewards</h3>\n\n      {rewards.total.map((reward) => (\n        <div key={reward.token} className=\"reward-row\">\n          <span className=\"token\">{reward.symbol}</span>\n          <span className=\"amount\">\n            {formatUnits(reward.amount, 18)} {reward.symbol}\n          </span>\n        </div>\n      ))}\n\n      {/* Show separate counts for transparency */}\n      <div className=\"source-breakdown\">\n        <small>\n          Merkl: {rewards.merkl.length} rewards • URD: {rewards.urd.length} rewards\n        </small>\n      </div>\n\n      {/* Claim button */}\n      <button onClick={() => handleClaimAll(userAddress, chainId)}>\n        Claim All Rewards\n      </button>\n    </div>\n  );\n}\n```\n\n## Displaying Rewards in Tables\n\nFor portfolio or dashboard views:\n\n```tsx\nfunction VaultPortfolio({ userAddress, chainId }: {\n  userAddress: string;\n  chainId: number;\n}) {\n  const [vaults, setVaults] = useState<any[]>([]);\n\n  return (\n    <table>\n      <thead>\n        <tr>\n          <th>Vault</th>\n          <th>Your Deposit</th>\n          <th>Base APY</th>\n          <th>Rewards APR</th>\n          <th>Total APY</th>\n          <th>Claimable</th>\n        </tr>\n      </thead>\n      <tbody>\n        {vaults.map((vault) => (\n          <tr key={vault.address}>\n            <td>{vault.name}</td>\n            <td>\n              {vault.userDeposit} {vault.asset.symbol}\n            </td>\n            <td>{vault.baseApy.toFixed(2)}%</td>\n            <td className=\"rewards-apr\">\n              +{vault.rewardsApr.toFixed(2)}%\n            </td>\n            <td className=\"total-apy\">\n              <strong>{vault.totalApy.toFixed(2)}%</strong>\n            </td>\n            <td>\n              {vault.claimable > 0 ? (\n                <button>Claim</button>\n              ) : (\n                <span>—</span>\n              )}\n            </td>\n          </tr>\n        ))}\n      </tbody>\n    </table>\n  );\n}\n```\n\n## Showing Reward Program Details\n\nProvide transparency about active programs:\n\n```tsx\nfunction RewardProgramsCard({ vaultAddress, chainId }) {\n  const [programs, setPrograms] = useState<any[]>([]);\n\n  // Fetch active programs for this vault\n  useEffect(() => {\n    fetchActivePrograms(vaultAddress, chainId).then(setPrograms);\n  }, [vaultAddress, chainId]);\n\n  return (\n    <div className=\"reward-programs\">\n      <h4>Active Reward Programs</h4>\n\n      {programs.map((program) => (\n        <div key={program.id} className=\"program-card\">\n          <div className=\"header\">\n            <img src={program.tokenIcon} alt={program.token} />\n            <span>{program.token} Rewards</span>\n          </div>\n\n          <div className=\"details\">\n            <div>APR: {program.apr.toFixed(2)}%</div>\n            <div>Ends: {formatDate(program.endDate)}</div>\n            <div>Source: {program.isMerkl ? \"Merkl\" : \"Morpho URD\"}</div>\n          </div>\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\n## Real-Time Updates\n\n### Polling for Updates\n\n```typescript\nfunction useRewardsPolling(userAddress: string, chainId: number) {\n  const [rewards, setRewards] = useState<any>(null);\n\n  useEffect(() => {\n    const fetchRewards = () => {\n      getUserAllClaimableRewards(userAddress, chainId).then(setRewards);\n    };\n\n    // Initial fetch\n    fetchRewards();\n\n    // Poll every 5 minutes for Merkl updates\n    const interval = setInterval(fetchRewards, 5 * 60 * 1000);\n\n    return () => clearInterval(interval);\n  }, [userAddress, chainId]);\n\n  return rewards;\n}\n```\n\n### Showing Accruing Rewards\n\nFor a more dynamic experience:\n\n```tsx\nfunction AccruingRewardsDisplay({ baseAmount, ratePerSecond }) {\n  const [accrued, setAccrued] = useState(baseAmount);\n\n  useEffect(() => {\n    const interval = setInterval(() => {\n      setAccrued((prev) => prev + ratePerSecond);\n    }, 1000);\n\n    return () => clearInterval(interval);\n  }, [ratePerSecond]);\n\n  return (\n    <div className=\"accruing-rewards\">\n      <span>Accruing: </span>\n      <span className=\"animated-number\">\n        {accrued.toFixed(6)} MORPHO\n      </span>\n    </div>\n  );\n}\n```\n\n## Handling Edge Cases\n\n### No Rewards Available\n\n```tsx\n{rewards.length === 0 ? (\n  <div className=\"no-rewards\">\n    <p>No active reward programs for this vault</p>\n    <p>Check back later or explore other vaults</p>\n  </div>\n) : (\n  <RewardsList rewards={rewards} />\n)}\n```\n\n### Failed to Fetch Rewards\n\n```tsx\n{error ? (\n  <div className=\"error-state\">\n    <p>Unable to load rewards data</p>\n    <button onClick={retry}>Retry</button>\n  </div>\n) : (\n  <RewardsDisplay />\n)}\n```\n\n### Dust Amounts\n\nDon't show tiny amounts that aren't worth claiming:\n\n```typescript\nconst DUST_THRESHOLD = 0.01; // $0.01 USD\n\nfunction filterDust(rewards: any[], tokenPrices: Record<string, number>) {\n  return rewards.filter((reward) => {\n    const usdValue =\n      parseFloat(formatUnits(reward.amount, 18)) * tokenPrices[reward.token];\n    return usdValue > DUST_THRESHOLD;\n  });\n}\n```\n\n## Accessibility Considerations\n\n- **Use semantic HTML**: `<table>` for tabular data, `<button>` for actions\n- **Provide labels**: Screen readers should understand what APY/APR values mean\n- **Keyboard navigation**: Ensure all interactive elements are keyboard-accessible\n- **Loading states**: Clear indication when data is loading\n\n```tsx\n<div role=\"status\" aria-live=\"polite\">\n  {loading ? \"Loading rewards...\" : `${rewards.length} rewards available`}\n</div>\n```\n\n## Resources\n\n- **Example App**: [morpho-org/merkl-morpho-recipe](https://github.com/morpho-org/merkl-morpho-recipe)\n- **Morpho API Playground**: [api.morpho.org/graphql](https://api.morpho.org/graphql)\n- **Design Inspiration**: [app.morpho.org](https://app.morpho.org)\n\n## Next Steps\n\n- **Implement claiming**: [Claim Rewards tutorial](/build/rewards/tutorials/claim-rewards)\n- **See complete example**: [Complete Integration Guide](/build/rewards/guides/complete-integration)"
  },
  "/curate/": {
    "title": "Morpho Curation",
    "url": "https://docs.morpho.org/curate/",
    "section": "Curate",
    "content": "This section serves as the definitive resource for Morpho Vault curators. It provides essential information to create, manage, and optimize vaults within the Morpho ecosystem.\n\n## Introduction to Curation\n\nCurators are essential in balancing stakeholder needs and maintaining vault performance. This guide highlights the core aspects of effective vault curation.\n\n## Curator Responsibilities\n\n### Borrower Needs\n\n- **Competitive Rates:** Access to markets offering attractive and competitive rates\n- **Liquidity Assurance:** Reliable liquidity during market stress to prevent rate spikes\n- **Capital Allocation:** Adequate capital support as positions grow\n- **Responsive Curation:** Quick adaptations to changing market conditions\n\n### Depositor Needs\n\n- **Risk Mitigation:** Zero tolerance for bad debt events\n- **Competitive Yields:** APYs that align with risk profiles\n- **Security & Monitoring:** Robust security measures and continuous collateral liquidity oversight\n- **Transparency:** Clear and ongoing risk assessments\n\n## Operational Requirements\n\n### Admin Tasks\n\n- **Role & Security Configuration:** Establish and maintain secure role assignments\n- **Market Listings:** Create and manage market listings effectively\n- **Fee & Cap Adjustments:** Update vault fee parameters and adjust allocation caps\n- **Public Settings:** Configure public allocation parameters\n\n### Market Curation\n\n- **Liquidity Reallocation:** Automate transfers between markets to optimize capital efficiency\n- **Performance Monitoring:** Track vault APYs against benchmarks\n- **Risk Assessment:** Evaluate liquidity risks, oracle reliability, collateral fundamentals, chain-specific factors, and multisig security\n- **Health Tracking:** Continuously monitor borrower conditions and optionaly execute liquidation processes for at-risk positions\n\n## Reward Mechanisms\n\n- **MORPHO Rewards:** Distributed to whitelisted markets and, in part, passed directly to vault depositors\n- **Oracle Integration:** Utilizes onchain price feeds from providers such as Chainlink, Api3, Redstone, Pendle, Hashnote, Chronicle, and Pyth\n- **Blockchain-Specific Deployment:** Rewards distribution varies by blockchain, with official deployments receiving priority\n- **Additional Configurations:** Extra market-level or vault-level rewards can be set up following the [reward programs guide](https://github.com/morpho-org/morpho-blue-reward-programs?tab=readme-ov-file#create-a-market-program)\n\n## Public Allocator Integration\n\nThe [Public Allocator (PA)](/learn/concepts/public-allocator/) significantly enhances vault performance:\n\n- Enable the PA on all vaults to maximize capital efficiency while maintaining risk parameters\n- Set flow configurations strategically:\n  - Open flows between markets sharing identical risk profiles\n  - Configure idle market flows to manipulate rates while preserving borrower access\n  - Set idle market `flow in` to zero unless bot reallocation is desired\n- Leverage third-party integrations like Contango and DefiSaver to drive additional volume\n\n## Key Advantages for Curators\n\n- **Optimized Capital Efficiency:** Benefit from advanced market-matching algorithms\n- **Granular Risk Control:** Configure precise market exposure parameters\n- **Non-Custodial Security:** Ensure transparent, immutable vault operations\n- **Dynamic Reallocation:** Maintain competitive rates with automated reallocation tools\n- **Flexible Customization:** Tailor vault parameters to meet diverse market needs\n\n## Get Started\n\nNew curators should begin with this overview to build a solid foundation, while experienced curators may reference specific sections for targeted guidance. This concise document is designed to enhance vault performance, manage risk effectively, and optimize returns for all vault users.\n\nRefer to [this section](/get-started/resources/contracts/) to dig into the specs of all smart contracts involved."
  },
  "/curate/concepts/adapter-registry/": {
    "title": "Adapter Registry",
    "url": "https://docs.morpho.org/curate/concepts/adapter-registry/",
    "section": "Curate",
    "content": "Vault V2 introduces the concept of an **Adapter Registry** — a [smart contract](/get-started/resources/addresses/#morpho-v2-contracts) that defines which adapters a vault can use to allocate assets.\n\n## Why Registries Matter\n\n[Vault V2](https://github.com/morpho-org/vault-v2) is future-proof: any curator can add adapters to deposit assets into external protocols.\nThis flexibility is powerful but also introduces risk: a vault could attract liquidity using the Morpho ecosystem and later redirect funds to other protocols that may be less secure or less aligned with Morpho’s safety and quality standards.\n\nAdapter Registries solve this by giving curators (and end users) a way to lock the vault’s allocation perimeter.\n- Without a registry → any adapter can be added.\n- With a registry → only adapters explicitly approved by that registry can be used.\n- The curator can abdicate the `setAdapterRegistry` function (by timelocking it forever) to make this restriction permanent and noncustodial.\n\nFor implementation details, see the [vault-V2-adapter-registries repository](https://github.com/morpho-org/vault-v2-adapter-registries).\n\n## The Morpho Registry\n\nThe **Morpho Registry** is an official registry maintained by the Morpho governance.\nIt lists adapters approved by the Morpho governance — including Morpho Markets (V1, V2) and Morpho Vaults V1 — and allows new ones to be added over time.\n\nVaults that:\n1. Set their adapter registry to the Morpho Registry, and\n2. Abdicate the ability to change it\n\nare considered Morpho Vaults V2.\n\nThese Morpho Vaults V2 gain access to Morpho ecosystem benefits, such as:\n- Eligibility for display and distribution in the Morpho App.\n- Access to Morpho’s support, incentive programs and Prime apps suite.\n- Confidence for depositors that the vault will remain within the Morpho-approved adapter perimeter.\n\nDevelopers can explore the Morpho Registry contract and other registry implementations in the [vault-V2-adapter-registries GitHub repo](https://github.com/morpho-org/vault-v2-adapter-registries).\n\n## Key Properties\n\n**Future proof**: vaults can add a new adapter, benefiting from it while preserving the liquidity the vault has built.\n\n**Add-only**: Once an adapter is approved, it stays; adapters can’t be removed to avoid breaking existing vaults.\n\n**Non-custodial guarantees**: Users can always exit before any configuration change (thanks to timelocks and in-kind redemptions).\n\n**Composable**: Builders can create their own registries if they want different adapter rules."
  },
  "/curate/concepts/fee/": {
    "title": "Fees",
    "url": "https://docs.morpho.org/curate/concepts/fee/",
    "section": "Curate",
    "content": "Morpho Vaults include fee mechanisms that allow vault managers to generate revenue from the yield they produce. The implementation and capabilities of these fees have evolved significantly from Vaults V1 to Vaults V2, offering curators more flexibility in designing their business models.\n\n## Fee Structure in Morpho Vaults V2\n\nVaults V2 introduce a sophisticated, dual-fee structure, giving curators precise control over revenue streams. All fee-related changes are managed by the `Curator` and are subject to a **timelock**, ensuring transparency and giving users time to react to proposed changes.\n\n### 1. Performance Fee\n\nThe performance fee is a percentage of the yield generated by the vault, aligning the curator's revenue with the vault's success.\n\n-   **Fee Basis**: Charged as a percentage of the interest generated by the vault's investments. This is automatically calculated based on the real asset values reported by adapters.\n-   **Maximum Rate**: Capped at **50%** of the generated interest.\n-   **Control**: The `Curator` sets the fee rate and the recipient address.\n\n### 2. Management Fee\n\nThe management fee is a continuous fee charged on the vault's total assets under management (AUM), providing a steady revenue stream for the vault's managers.\n\n-   **Fee Basis**: Calculated as an annualized percentage of the vault's `totalAssets`. A small portion of this fee is collected each time interest is accrued.\n-   **Maximum Rate**: Capped at **5% per year**.\n-   **Control**: The `Curator` sets the fee rate and the recipient address.\n\n### Fee Collection Mechanism in V2\n\nFees in Vaults V2 are collected seamlessly without affecting depositors' principal.\n\n1.  An interaction (like a deposit, withdrawal, or a direct `accrueInterest` call) triggers interest and fee calculations.\n2.  The vault aggregates asset values from all adapters to determine the total interest generated.\n3.  The performance and management fees are calculated based on this interest and the total assets.\n4.  New vault shares corresponding to the fee amounts are minted directly to the `performanceFeeRecipient` and `managementFeeRecipient` addresses.\n5.  The vault's `totalAssets` are updated to reflect the new state after interest distribution.\n\nThis share-minting mechanism ensures that fees are taken from the profits, while the principal of all depositors remains fully intact.\n\n## Fee Structure in Morpho Vaults V1\n\nThe fee system in Vaults V1 is simpler, consisting of a single performance-based fee controlled by the `Owner`.\n\n-   **Fee Type**: A single **performance fee**. There is no management fee.\n-   **Fee Basis**: The fee is a percentage of the **actual interest** accrued onchain from the underlying Morpho Market V1 positions.\n-   **Control**: The `Owner` of the vault sets the fee rate and the recipient.\n-   **Security**: Fee parameter changes are **immediate** and do not have a timelock.\n-   **Maximum Rate**: Capped at **50%** of the generated interest.\n-   **Collection**: Like in V2, fees are collected by minting new vault shares to the `feeRecipient`.\n\n## Comparison: Vaults V2 vs. Vaults V1\n\n| Feature                     | Morpho Vaults V2                                          | Morpho Vaults V1 (MetaMorpho)                               |\n| --------------------------- | --------------------------------------------------------- | ----------------------------------------------------------- |\n| **Fee Types**               | **Performance Fee** + **Management Fee**                  | Performance Fee Only                                        |\n| **Performance Fee Basis**   | Interest automatically calculated from adapter asset values | **Actual onchain interest** from Morpho Market V1 positions  |\n| **Management Fee Basis**    | Percentage of **Total Assets** (AUM)                      | N/A                                                         |"
  },
  "/curate/concepts/gates/": {
    "title": "Gates in Morpho Vaults",
    "url": "https://docs.morpho.org/curate/concepts/gates/",
    "section": "Curate",
    "content": "Morpho Vaults (V1 and V2) support different mechanisms to restrict access to deposits, withdrawals, and transfers. Vault V2 introduces **first-class gates** as external contracts with timelock and abdication guarantees, while Vault V1.1 achieves gating operationally by manipulating the `supplyQueue` and market caps.\n\n## High-Level Comparison\n\n| Aspect                          | Vault V1.1                               | Vault V2                                        |\n|---------------------------------|-------------------------------------------|------------------------------------------------|\n| **Native Gates**                | ❌ None (must use supplyQueue + caps)      | ✅ Four explicit gates (receive/send shares, receive/send assets) |\n| **Granularity**                 | Coarse: deposits only (via `supplyQueue`) | Fine: deposits, withdrawals, transfers, fee accrual |\n| **Timelock**                    | Caps increases are timelocked (24h–2w)    | All gate changes timelocked (configurable, e.g. up to 3 weeks) |\n| **Abdication**                  | ❌ Not supported                          | ✅ Supported (permanent permissionless or permanently gated) |\n| **Atomic batching**             | ✅ `multicall` allows open–deposit–close  | ✅ `multicall` supported but rarely needed for gates |\n| **Intended use cases**          | Simple whitelisting of suppliers          | Compliance, allowlists, permissioned transfers |\n\n## Gates in Vault V2\n\n### Executive Summary\n\nGates in Vault V2 are external smart contracts that provide **access control and compliance mechanisms** for vault operations. They enable selective permissions for share transfers, asset deposits, and asset withdrawals while making it possible to maintain the vault's noncustodial guarantees. Gates are **optional** (if not set, operations are unrestricted) and can be **timelocked** for security.\n\n### Core Architecture\n\n#### Four Gate Types\n\n  \n\nVault V2 implements a **four-gate system** addressing different operational vectors:\n\n#### 1. **Receive Shares Gate** (`receiveSharesGate`)\n\n- **Interface**: `IReceiveSharesGate` with `canReceiveShares(address)`\n- **Controls**: Who can receive vault shares\n- **Operations**:\n    - `deposit()`, `mint()` → checks `canReceiveShares(onBehalf)`\n    - `transfer()`, `transferFrom()` → checks `canReceiveShares(to)`\n    - Performance/management fee accrual → checks `canReceiveShares(feeRecipient)`\n- **⚠️ Critical Risk**: Can prevent depositors from getting back shares deposited on other contracts. Note that if the gate **reverts** instead of returning `false`, it can cause a **denial of service (DoS)** across core vault operations.\n\n#### 2. **Send Shares Gate** (`sendSharesGate`)\n\n- **Interface**: `ISendSharesGate` with `canSendShares(address)`\n- **Controls**: Who can send vault shares\n- **Operations**:\n    - `withdraw()`, `redeem()` → checks `canSendShares(onBehalf)`\n    - `transfer()`, `transferFrom()` → checks `canSendShares(from)`\n- **⚠️ Critical Risk**: Can lock users out of exiting the vault or prevent depositors from getting back shares deposited on other contracts\n\n#### 3. **Receive Assets Gate** (`receiveAssetsGate`)\n\n- **Interface**: `IReceiveAssetsGate` with `canReceiveAssets(address)`\n- **Controls**: Who can receive underlying assets from the vault\n- **Operations**:\n    - `withdraw()`, `redeem()` → checks `canReceiveAssets(receiver)`\n- **Special Rule**: Vault itself (`address(this)`) always bypasses this gate\n- **⚠️ Critical Risk**: Can prevent people from receiving their assets upon withdrawals\n\n#### 4. **Send Assets Gate** (`sendAssetsGate`)\n\n- **Interface**: `ISendAssetsGate` with `canSendAssets(address)`\n- **Controls**: Who can deposit underlying assets into the vault\n- **Operations**:\n    - `deposit()`, `mint()` → checks `canSendAssets(msg.sender)`\n- **Non-critical**: Cannot block users' funds, while still being able to gate supplies\n\n### Technical Implementation Deep Dive\n\nPermissioned token functions (gates) can be found in the Vault V2 repository [here](https://github.com/morpho-org/vault-v2/blob/0888120e4c041690a040635dc4d448b7cb597965/src/VaultV2.sol#L910-L926) and IGate interfaces [here](https://github.com/morpho-org/vault-v2/blob/main/src/interfaces/IGate.sol).\n\n#### Gate Checking Logic\n\n```solidity\n// From VaultV2.sol - Gate validation functions\nfunction canReceiveShares(address account) public view returns (bool) {\n    return receiveSharesGate == address(0) ||\n           IReceiveSharesGate(receiveSharesGate).canReceiveShares(account);\n}\n\nfunction canSendShares(address account) public view returns (bool) {\n    return sendSharesGate == address(0) ||\n           ISendSharesGate(sendSharesGate).canSendShares(account);\n}\n\nfunction canReceiveAssets(address account) public view returns (bool) {\n    return account == address(this) ||\n           receiveAssetsGate == address(0) ||\n           IReceiveAssetsGate(receiveAssetsGate).canReceiveAssets(account);\n}\n\nfunction canSendAssets(address account) public view returns (bool) {\n    return sendAssetsGate == address(0) ||\n           ISendAssetsGate(sendAssetsGate).canSendAssets(account);\n}\n\n```\n\n#### Critical Implementation Requirements\n\nGates MUST be designed knowing it should never revert, returning always boolean values. Also gates should not use a malicious amount of gas (like something close to the block size).\n\n### Governance and Security Model\n\n#### Timelock Protection\n\nGates follow the vault's timelock system:\n\n```solidity\n// Curator functions for gate management (timelockable)\nfunction setReceiveSharesGate(address newReceiveSharesGate) external {\n    timelocked();\n    receiveSharesGate = newReceiveSharesGate;\n    emit EventsLib.SetReceiveSharesGate(newReceiveSharesGate);\n}\n\nfunction setSendSharesGate(address newSendSharesGate) external {\n    timelocked();\n    sendSharesGate = newSendSharesGate;\n    emit EventsLib.SetSendSharesGate(newSendSharesGate);\n}\n\nfunction setReceiveAssetsGate(address newReceiveAssetsGate) external {\n    timelocked();\n    receiveAssetsGate = newReceiveAssetsGate;\n    emit EventsLib.SetReceiveAssetsGate(newReceiveAssetsGate);\n}\n\nfunction setSendAssetsGate(address newSendAssetsGate) external {\n    timelocked();\n    sendAssetsGate = newSendAssetsGate;\n    emit EventsLib.SetSendAssetsGate(newSendAssetsGate);\n}\n\n```\n\n#### The Two Types of Permanent Guarantees with Gate Abdication\n\n```solidity\n// Example: Permanently disable receive shares gate changes\nvault.abdicate(IVaultV2.setReceiveSharesGate.selector);\n\n```\n\nThe `abdicate()` function allows a curator to make an irreversible commitment regarding a vault's configuration, providing users with permanent guarantees. When applied to gates, this creates two distinct and powerful outcomes: ensuring a vault is either permanently permissionless or permanently governed by a fixed set of rules:\n\n#### Type 1. The Permanently Ungated Vault (Abdicating to Zero)\n\nThis strategy provides the strongest guarantee of permissionless access.\n\n- **Goal:** To ensure a vault can never have a specific type of gate imposed on it.\n- **How it Works:** The curator first ensures the target gate address is set to address(0) (disabling it). They then call `abdicate` on that gate's setter function (e.g., setReceiveSharesGate). Note that `abdicate` is a timelocked function, so it must be submitted and then executed after the timelock period (or immediately if the timelock is 0).\n- **Result:** This action permanently locks the gate address to address(0). No one can ever set a gate contract for that function in the future. This is a powerful tool for creating truly decentralized vaults where users are assured that access rules will never be introduced.\n\n#### Type 2. The Permanently Gated Vault (Abdicating to a Non-Zero Gate)\n\nThis strategy is designed for vaults that must adhere to a fixed, unchangeable set of compliance rules.\n\n- **Goal:** To lock a vault into a specific, non-modifiable access control policy.\n- **How it Works:** The curator sets the gate to the address of a deployed gate contract and then calls `abdicate` on the setter function.\n- **Result:** The vault becomes permanently bound to that gate contract. The rules defined within that contract can never be altered by changing the gate address.\n\n**Crucial Security Consideration:** This guarantee is only meaningful if the gate contract itself has **immutable behavior**. If the gate contract contains administrative functions that allow an owner to modify its rules (e.g., change a whitelist), then abdicating simply transfers the power to control access from the vault's curator to the gate's administrator. For a true permanent guarantee, the gate contract must be designed without such administrative controls, or its ownership must be renounced.\n\n### Special Cases and Edge Conditions\n\n#### Vault Self-Operations\n\nThe vault itself (`address(this)`) is **always allowed** to receive assets, regardless of the `receiveAssetsGate` configuration. This prevents the vault from blocking its own internal operations:\n\n```solidity\nfunction canReceiveAssets(address account) public view returns (bool) {\n    return account == address(this) || // Vault always bypasses\n           receiveAssetsGate == address(0) ||\n           IReceiveAssetsGate(receiveAssetsGate).canReceiveAssets(account);\n}\n\n```\n\n#### Fee Recipient Gate Checks\n\n**Important**: If a gate is set and reverts for fee recipients when fees are non-zero, interest accrual will revert. This makes proper gate configuration critical for vault operation.\n\n### Impact on Non-Custodial Guarantees\n\n#### Force Deallocate Mechanism\n\n```solidity\nfunction forceDeallocate(address adapter, bytes memory data, uint256 assets, address onBehalf)\n    external returns (uint256)\n\n```\n\nThis function allows users to perform in-kind redemptions by:\n\n1. Flashloaning liquidity\n2. Supplying to an adapter's market\n3. Withdrawing liquidity through `forceDeallocate`\n4. Repaying the flashloan\n\nMore details are provided [here](/learn/concepts/vault-v2/#are-morpho-vaults-v2-non-custodial).\n\n### Testing Considerations\n\nThe codebase includes comprehensive gate testing:\n\n- `GateExampleTest.sol` - Tests the reference implementation (Disclaimer: this should not be used in production as is).\n- `GatingTest.sol` - Tests all gate integration points\n- Tests verify proper error handling for each gate type\n- Tests confirm vault self-operations bypass receive assets gate\n\n## Gates in Vault V1\n\nVault V1.1 does not include first-class gates. Instead, access control can be emulated by **playing with the `supplyQueue` and market caps**, combined with `multicall`. This provides a practical gating mechanism for suppliers.\n\n### Key Mechanics\n\n- **Deposits only work if the `supplyQueue` is non-empty**. If empty, `deposit` reverts and the vault is effectively closed.  \n- **Allocator role** can update the queue at any time (no timelock).  \n- A market must have a **non-zero cap** to appear in the queue.  \n- **Cap increases** are timelocked (24h–2w), but **cap decreases** are instant.  \n- The vault supports **`multicall`**, allowing atomic open–deposit–close flows to prevent front-running.\n\n### Tutorial\n\n#### One-Time Setup\n\n1. **Deploy** the V1.1 vault (`MetaMorphoV1_1`).  \n2. **Assign roles**:  \n   - Owner → multisig  \n   - Curator → multisig (or another trusted address)  \n   - Allocator → hot wallet / automation bot  that will run the batch transaction \n3. **Prepare the market**: ensure cap > 0 (requires timelock if raising).\n\n#### Keep the Vault Closed by Default\n\n```solidity\n// Curator or Allocator\nvault.setSupplyQueue(new MarketParams); // []\n```\n\nNo one can deposit, as the queue is empty.\n\n#### Open Deposit Window (Privileged Supplier)\n\nPerform an **atomic batch** via `multicall`:\n\n1. Open queue (add target market).  \n2. Deposit assets.  \n3. Close queue (reset to empty).  \n\n#### Example in viem\n\n```ts\nimport { createPublicClient, createWalletClient, http } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { mainnet } from \"viem/chains\";\nimport { morphoVaultAbi } from \"./abi\";\n\nconst account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);\n\nconst client = createWalletClient({\n  account,\n  chain: mainnet,\n  transport: http(RPC_URL),\n});\n\nconst VAULT_ADDRESS = \"0x...\"; \nconst TARGET_MARKET = \"0x...\"; // market id\nconst AMOUNT = 1_000n * 10n ** 18n;\n\nconst openQueueCall  = {\n  abi: morphoVaultAbi,\n  functionName: \"setSupplyQueue\",\n  args: [[TARGET_MARKET]],\n};\n\nconst depositCall = {\n  abi: morphoVaultAbi,\n  functionName: \"deposit\",\n  args: [AMOUNT, account.address],\n};\n\nconst closeQueueCall = {\n  abi: morphoVaultAbi,\n  functionName: \"setSupplyQueue\",\n  args: [[]],\n};\n\nawait client.writeContract({\n  address: VAULT_ADDRESS,\n  abi: morphoVaultAbi,\n  functionName: \"multicall\",\n  args: [[\n    client.encodeFunctionData(openQueueCall),\n    client.encodeFunctionData(depositCall),\n    client.encodeFunctionData(closeQueueCall),\n  ]],\n});\n```\n\n#### Operational Caveats\n\n- **Always batch** open–deposit–close; otherwise, others may front-run deposits.  \n- Keep caps at **0 by default** and raise only when scheduling controlled deposits.  \n- This mechanism gates **suppliers only**; withdrawals remain unaffected.  \n\n#### Final notes on Vault V1 Gating operation:\n- The **supplier must sign the batch** and be the allocator itself.\n- If you use a Gnosis Safe, craft a Multisend with those three calls and have the Safe execute it."
  },
  "/curate/concepts/liquidity/": {
    "title": "Liquidity Curation",
    "url": "https://docs.morpho.org/curate/concepts/liquidity/",
    "section": "Curate",
    "content": "Liquidity Curation is the art and science of curating a vault's capital to optimize yield while adhering to a specific risk strategy. It is a dynamic process performed by the vault's `Curator` and `Allocator`, who work together to define risk parameters and deploy assets effectively.\n\nThe methodology for curation differs significantly between Morpho's vault versions:\n-   **Vaults V2** use a powerful, future-proof framework based on **Adapters** and a granular **ID & Cap System**.\n-   **Vaults V1** use a more direct model focused on allocating to **Morpho Market V1** instances via **Supply and Withdraw Queues**.\n\n## Curation in Morpho Vaults V2\n\nCuration in Vaults V2 is a two-tiered process that separates high-level strategy from tactical execution. The `Curator` sets the rules of the game, and the `Allocator` plays within them.\n\n### The Core Components of V2 Curation\n\nA V2 Curator has three primary tools to build the vault's risk framework:\n\n#### 1. Adapters: The Gateway to Protocols\n\nAn **Adapter** is a smart contract that allows the vault to interact with an external protocol. The Curator's first job is to decide which protocols the vault can trust by enabling their respective adapters. This makes the vault a universal gateway, capable of allocating to:\n- Morpho Market V1 (via `MorphoMarketV1AdapterV2`)\n- Morpho Vault V1 (via `MorphoVaultV1Adapter`)\n- Future Morpho versions and any other yield-bearing protocol with an adapter.\n\n#### 2. The ID & Cap System: Granular Risk Control\n\nThis is the heart of V2 risk curation. Instead of setting a simple cap on a single market, the Curator can manage exposure across abstract **risk factors**, each identified by a unique `id`.\n\nAn `id` can represent anything an adapter can define, such as:\n- A specific collateral asset (e.g., `stETH`)\n- A specific oracle (e.g., `Chainlink`)\n- An entire protocol (e.g., all of Morpho Market V1)\n- A highly specific market configuration\n\nThe Curator can apply two types of caps to any `id`:\n- **Absolute Cap**: A fixed maximum amount of assets (e.g., \"no more than 20M USDC allocated to markets with `wBTC` as collateral\").\n- **Relative Cap**: A maximum percentage of the vault's total assets (e.g., \"no more than 30% of the vault may be exposed to Protocol X\").\n\nThis system allows for sophisticated, multi-dimensional risk policies that were impossible in V1.\n\n#### 3. The Liquidity Adapter: Managing Active Liquidity\n\nThe `Allocator` can designate one enabled adapter as the vault's **`liquidityAdapter`**. This adapter serves two critical functions:\n1.  **Receiving Deposits**: All new user deposits are automatically routed to this adapter, ensuring capital is immediately put to work.\n\nIf a cap (absolute or relative) associated with the ids returned by the liquidity adapter on the liquidity data is reached, deposit/mint will revert.\nThere is no fallback to idle. When caps are hit, someone with allocator/curator permissions needs to either:\n- Increase the caps, or\n- Reallocate funds to other markets, or\n- Remove/change the liquidity adapter\n\n2.  **Fulfilling Withdrawals**: If the vault's idle assets are insufficient to cover a user's withdrawal, funds are automatically pulled from this adapter.\n\nIf there is no idle asset and no liquidity available on the liquidity adapter, the Morpho Vault V2 becomes illiquid. Someone with allocator/curator permissions needs to either:\n- Reallocate funds from other markets to the liquidity adapter, or\n- Change the liquidity adapter to a market with available liquidity\n\nThe liquidity adapter is typically set to a highly liquid and safe yield source to ensure smooth vault operations.\n\n### The Curation Workflow in Practice\n\n1.  **Strategic Curation (The `Curator`)**:\n    - **Enables Adapters**: Decides which protocols are in-scope for the vault's strategy.\n    - **Defines the Risk Framework**: Sets absolute and relative caps on various `ids` to control exposure.\n    - **Appoints Allocators**: Delegates the active portfolio management to trusted entities or smart contracts.\n    *(All these actions are timelocked for security).*\n\n2.  **Tactical Allocation (The `Allocator`)**:\n    - **Operates Within Boundaries**: The Allocator uses `allocate` and `deallocate` to move funds between the vault's idle pool and the various enabled adapters.\n    - **Optimizes Yield**: They can shift capital to adapters offering the best risk-adjusted returns, as long as no caps are breached.\n    - **Curates Liquidity**: They set the `liquidityAdapter` to ensure there are sufficient funds for user deposits and withdrawals.\n\n| Feature                | **In Morpho Vault V2**                                                     |\n| :--------------------- | :------------------------------------------------------------------------- |\n| **Allocation Target**  | Any protocol with an enabled **Adapter**.                                  |\n| **Risk Control**       | Granular **ID & Cap System** (absolute and relative caps on risk factors). |\n| **Liquidity Curation** | A dedicated **`liquidityAdapter`** for deposits and withdrawals.           |\n\n## Curation in Morpho Vaults V1\n\nCuration in Vaults V1 is focused exclusively on allocating capital across **Morpho Market V1** instances. The system is more direct, relying on queues and per-market caps.\n\n### Strategic Market Curation\n\nThe `Curator`'s primary role is to select a basket of Morpho Market V1 instances that align with the vault's strategy and set a hard **supply cap** on each one. This provides a simple but effective way to limit exposure to any single market.\n\n### The Queue System: How Capital Moves\n\nThe `Allocator` is responsible for managing two critical queues that dictate how capital flows in and out of the vault:\n\n#### Supply and Withdraw Queues\n\nThe supply queue determines the order in which markets receive new deposits. When a user deposits assets, the vault attempts to supply liquidity to each market in sequence until the deposit is fully allocated or all market caps are reached.\n\nThe withdraw queue determines the order in which markets are tapped to fulfill user withdrawals. This queue contains all markets where the vault has a non-zero supply or a non-zero cap.\n\n### Recommended Queue Setup\n\n**Supply Queue:** `[Idle]`\n\n**Withdraw Queue:** `[Idle, Market 1, Market 2, …]`\n\nThis configuration is recommended for all Morpho Vaults V1 and V1.1 as it completely prevents any misallocation of funds through normal operations or malicious intent. This setup:\n\n- **Keeps the strategy intact**: Deposits land in idle first and withdrawals exit idle first, so routine user activity can't move funds out of your yield strategy.\n- **Protects APY and risk settings**: Idle acts as a neutral buffer; reallocations happen only when you decide, preventing erosion of returns or allocations to assets beyond your current selection.\n- **Stops accidental drift**: Even well-meaning users can shuffle money between markets if queues start with different pools. Using \"Idle first\" on both sides blocks that.\n- **Thwarts quick \"hit-and-run\" attacks**: Flash-loan or high-balance tricks lose their leverage because idle simply drains and refills itself, leaving active markets unchanged.\n\n## Practical Implementation\n\nThe market management system requires continuous monitoring and adjustment:\n\n- **Data-Driven Decisions**: Base cap adjustments and queue positioning on utilization metrics, yield comparisons, and risk assessments\n- **Capital Flow Analysis**: Monitor deposit and withdrawal patterns to optimize queue configurations\n- **Risk Mitigation**: Implement gradual transitions to prevent rate spikes that could drive borrowers to competitors\n- **Stress Testing**: Regularly simulate extreme market conditions to ensure queue systems remain robust"
  },
  "/curate/concepts/roles/": {
    "title": "Roles & Capabilities",
    "url": "https://docs.morpho.org/curate/concepts/roles/",
    "section": "Curate",
    "content": "The roles and capabilities for managing Morpho Vaults differ significantly between the future-proof Vaults V2 and the original Morpho Market V1-centric Vaults V1. This document outlines the responsibilities and permissions for each version.\n\n## Morpho Vaults V2 Roles\n\nThe Vault V2 architecture introduces a refined role system with a clear separation of concerns, designed for enhanced security and operational flexibility.\n\n**Separation of Concerns is Key in V2**\n\nUnlike V1, the `Owner` in V2 does not inherit the powers of other roles. Each role is distinct, ensuring that administrative control is separate from strategic risk curation and daily portfolio operations.\n\n### Owner\n\nThe **Owner** holds the highest-level administrative power, responsible for appointing and managing the key roles that govern the vault.\n\n- **Recommended Approach:** A secure multisig (e.g., 4-of-6) or an equivalent institutional-grade MPC wallet. A single EOA is highly discouraged for production vaults.\n- **Impact of Compromise:** Full administrative control loss. The Owner can replace the Curator, who controls the vault's strategy.\n\n#### Capabilities\n\n- Only one address can have this role.\n- Transfer ownership of the vault (`setOwner`).\n- Appoint or change the `Curator` (`setCurator`).\n- Add or remove `Sentinels` (`setIsSentinel`).\n- Set the vault's ERC-20 `name` and `symbol`.\n\n### Curator\n\nThe **Curator** is the vault's chief risk officer and strategist. They define the investment thesis, set risk parameters, and enable the tools for the Allocator.\n\n- **Recommended Approach:** A multisig (e.g., 2-of-4 or 3-of-5) or an MPC wallet.\n- **Impact of Compromise:** Can propose and, after a timelock, execute changes that alter the vault's risk profile. The `Sentinel` and depositors have the timelock duration to react.\n\n#### Capabilities\n\n- Only one address can have this role.\n- **Protocol Management**:\n   - `[Timelocked]` Enable or disable yield sources via Adapters (`addAdapter`, `removeAdapter`).\n- **Risk Curation**:\n   - `[Timelocked]` Increase absolute or relative caps for any risk `id` (`increaseAbsoluteCap`, `increaseRelativeCap`).\n   - Instantly decrease absolute or relative caps (`decreaseAbsoluteCap`, `decreaseRelativeCap`).\n- **Yield & Fee Management**:\n   - `[Timelocked]` Set the `performanceFee` and `managementFee`.\n   - `[Timelocked]` Set the `performanceFeeRecipient` and `managementFeeRecipient`.\n- **Operational Management**:\n   - `[Timelocked]` Add or remove `Allocators` (`setIsAllocator`).\n   - `[Timelocked]` Set `Gate` contracts for onchain compliance (`setSharesGate`, `setReceiveAssetsGate`, `setSendAssetsGate`).\n   - `[Timelocked]` Set the penalty for `forceDeallocate` (`setForceDeallocatePenalty`).\n\nA `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.\n\n- **Timelock Management**:\n   - `[Timelocked]` Increase the duration of any timelock (`increaseTimelock`). The timelock for this action equals its own current timelock duration (if set to 0, it can be executed immediately).\n   - `[Timelocked]` Decrease the duration of any timelock (`decreaseTimelock`). The timelock for this action equals the current timelock of the function being decreased.\n   - `[Timelocked]` Irreversibly disable a timelocked action (`abdicate`).\n\n### Allocator\n\nThe **Allocator** is the active portfolio manager, responsible for executing the vault's strategy within the boundaries set by the Curator.\n\n- **Recommended Approach:** A hot-key EOA operated by a bot, or a fast-response multisig.\n- **Impact of Compromise:** Can misallocate funds between *already approved* adapters, potentially leading to suboptimal yield or temporary liquidity imbalances. Cannot introduce new, unapproved risks.\n\n#### Capabilities\n\n- Multiple addresses can have this role.\n- Allocate capital from the vault's idle assets to enabled Adapters (`allocate`).\n- Deallocate capital from Adapters back to the vault's idle assets (`deallocate`).\n- Set and manage the `liquidityAdapter` to handle user deposits and withdrawals.\n- Set the maximum rate at which assets can grow (`setMaxRate`).\n\n### Sentinel\n\nThe **Sentinel** is a safety-oriented role designed for reactive risk mitigation. It acts as a check on the Curator and can intervene in emergencies.\n\n- **Recommended Approach:** Can be a hot key, a DAO governance contract (e.g., Snapshot), or a trusted third party.\n- **Impact of Compromise:** Minimal. A compromised Sentinel can only take actions that reduce risk (e.g., deallocate funds) or halt pending changes. It cannot introduce new risk.\n\n#### Capabilities\n\n- Multiple addresses can have this role.\n- Deallocate funds from any enabled Adapter back to the vault's idle assets (`deallocate`).\n- Instantly decrease absolute or relative caps for any risk `id`.\n- Revoke any pending timelocked action submitted by the Curator (`revoke`).\n\n### Any Address\n\n#### Capabilities\n\n- Execute any action submitted by the Curator once its timelock has expired.\n- Trigger a `forceDeallocate` to provide in-kind redemption liquidity (subject to a penalty).\n\n## Morpho Vaults V1 Roles\n\nFor reference, here are the roles and capabilities for the Morpho Vaults V1 architecture.\n\nIt is intended that Owner, Curator, and Guardian should be different addresses.\n\n### Owner\n\n#### Roles\n\n- **Highly Recommended Approaches:**\n  - Deploy a multisig with minimum 4/6 signers, OR\n  - Use an enterprise MPC wallet with equivalent security controls\n  - Implement strict operational security protocols\n  - Distribute signing authority across trusted entities\n  - Never use single-key EOA (Externally Owned Account) control\n- **Impact of Compromise:** Complete vault control loss without recovery options\n\n#### Capabilities\n\n- Only a single address can have this role.\n- Change owner (2 steps: the new owner has to accept ownership).\n- Renounce ownership.\n- Set the curator.\n- Add/remove addresses with the allocator role (including the Public Allocator).\n- [Time-locked] Set the guardian.\n- Increase the timelock duration for every time-locked function.\n- [Time-locked if already set] Decrease the timelock duration for every time-locked function.\n- Set the performance fee.\n- Set the fee recipient.\n- Set the rewards distributor address.\n- All the capabilities of the Curator, the Allocator and the Guardian.\n\n### Curator\n\n#### Roles\n\n- **Recommended Approaches:**\n  - Deploy a multisig with minimum 2/4 or 3/5 signers, OR\n  - Use an enterprise MPC wallet with multi-party authorization policies\n  - Implement robust operational security protocols\n  - Distribute signing authority with geographical redundancy\n- **Impact of Compromise:** Elevated risk exposure, recoverable by owner intervention\n\n#### Capabilities\n\n- Only a single address can have this role.\n- Decrease a supply cap on a Morpho market.\n- [Time-locked] Increase a supply cap on a Morpho market, which includes enabling a new market (by setting a non-zero cap on a not yet enabled market).\n- [Time-locked] Submit the forced removal of a market.\n- Revoke the pending supply cap on a Morpho market.\n- Revoke the pending removal of a Morpho market.\n- All the capabilities of the Allocator.\n\nNote: the Curator can't pause the withdrawal of funds.\n\n### Allocator\n\n#### Roles\n\n- **Recommended Options:**\n  - EOA operated by monitoring bot\n  - Multisig with fast response capabilities (1/3 or 2/4), OR\n  - Enterprise MPC wallet with appropriate authorization controls\n- **Mitigation Strategy:** Set restrictive market caps to limit potential damage\n\n#### Capabilities\n\n- Multiple addresses can have this role.\n- Can modify the allocation between markets and the idle supply in the vault within the bounds set by the Curator.\n- Set the supply queue to some arbitrary queue of markets.\n- Re-order the withdraw queue by applying a permutation to it. Can omit markets on which the vault has 0 supply and 0 cap to remove it form the withdraw queue.\n\n### Guardian\n\n#### Roles\n\n- **Implementation Options:**\n  - Snapshot-based governance system\n  - Aragon DAO integration\n  - Multisig managed by community representatives\n- **Security Benefit:** Provides emergency intervention capability for users\n\n#### Capabilities\n\n- Only a single address can have this role.\n- Can revoke a pending timelock decrease until the previous timelock ends and the new timelock is accepted (by the Owner).\n- Can revoke a pending guardian until the timelock ends and the new guardian is accepted (by the Owner).\n- Can revoke each pending market cap increase until the timelock ends and the new market cap is accepted (by the Owner or the Curator).\n- In particular, it cannot revoke a pending fee (submitted by the Owner).\n\n### Any address\n\n#### Capabilities\n\n- Can accept the new cap after timelock.\n- Can accept the new fee after timelock.\n- Can accept the new guardian after timelock.\n- Can accept the new Timelock value after the current timelock duration."
  },
  "/curate/concepts/security-considerations/": {
    "title": "Security Considerations for Vault Curators",
    "url": "https://docs.morpho.org/curate/concepts/security-considerations/",
    "section": "Curate",
    "content": "This document outlines important security considerations and best practices for Morpho Vault curators. It covers vault-specific security topics that are most relevant to curators and advanced users.\n\n## Faulty Oracles\n\nSupplying liquidity in a market with a faulty oracle (overestimating the collateral’s price) will obviously lead to a loss of funds, because the health computation and the liquidation wouldn’t work properly.\n\nOn top of that, Morpho Vaults V1 (versions 1.0 and 1.1) have an additional edge-case: if they list a market whose oracle reports a price significantly above the market price — specifically, when the market price goes below `oraclePrice * LLTV` — the number of market shares of the vault can be increased via a donation and, as a result, the vaults can incur some losses.\n\nMore precisely, they can lose as much as the amount that can be borrowed against collateral that can be bought below `LLTV * oraclePrice * σ` where `σ` represents the adversary's share of the vault’s supply.\n\n**Important:** Supply caps at zero will not prevent losses. A vault with a faulty oracle market in the `WithdrawalQueue` and cap at zero can still have its shares in the market increased.\n\n### Recommendations\n\n**To reduce the chances of faulty oracles** (Always important, independent of the edge case)**:**\n\n- Curators should choose oracles to minimize the risk of price divergence.\n- Disable markets that the vault does not actively use (remove from withdraw queue), even if the caps are zero.\n\n**If a faulty oracle situation occurs:**\n\n- Immediately pause deposits by emptying the supply queue. This prevents anyone getting new shares and increasing their `σ`. One can automate this : have an allocator that automatically removes the supply queue when on any market of the vault the market price diverges significantly from the oracle price.\n- Remove the affected market from the queue as quickly as possible:\n    - If the vault holds zero shares in the market, remove it instantly.\n    - If the market is liquid, withdraw all shares and then remove it instantly.\n    - If the market is illiquid, initiate forced removal and execute it once the timelock expires.\n\nNote that Vaults V2 are not affected by this edge-case when supplying directly to Markets V1. If a Vault V2 supplies Vault V1, they can be affected up to its allocation to the Vault V1.\n\nCredit to [Madiha](https://x.com/madiha_right) for helping the Morpho team identify and provide these security guidelines to vault curators.\n\n## Reverting Oracle\n\nWhen an oracle reverts (e.g., due to underlying feed deprecation by the provider), the market enters a degraded state. Some operations stop working, but users are not permanently stuck.\n\n#### What Still Works\n\n| Function             | Works? | Notes                                        |\n| -------------------- | ------ | -------------------------------------------- |\n| `supply`             | ✅     | No price check needed                        |\n| `withdraw`           | ✅     | No price check needed                        |\n| `repay`              | ✅     | No price check needed                        |\n| `supplyCollateral`   | ✅     | No price check needed                        |\n| `borrow`             | ❌     | Requires price → reverts                     |\n| `withdrawCollateral` | ⚠️     | Only if borrower has exactly 0 borrow shares |\n| `liquidate`          | ❌     | Requires price → reverts                     |\n\n#### How Users Can Exit\n\n**Lenders:** Withdraw normally, no issue (provided borrowers repayements grant enough available liquidity)\n\n**Borrowers:** \n1. Repay the full debt (must reach exactly 0 borrow shares)\n2. Then withdraw collateral\n\nIf even 1 borrow share remains, `withdrawCollateral` will revert because it triggers a health check.\n\n**Liquidators:** Cannot liquidate, the function requires the oracle.\n\n#### What Curators can do\n\n1. Set supply cap to 0 to prevent new allocations\n2. Contact the feed provider: request they restore the feed temporarily or provide stale prices so users can exit\n3. Notify affected borrowers to repay and exit\n4. If unrecoverable, use the \"Market Reverts\" emergency flow for Morpho Vaults V1 in the Curator App (see [Emergency Procedures](/curate/tutorials-v1/emergency/#market-reverts-forced-removal))\n\n#### Prevention\n\nWhen selecting oracles and feeds, prefer providers with clear deprecation policies. Ideally, deprecated feeds should return stale prices rather than revert, this allows orderly market wind-down instead of an emergency situation.\n\n## Vault as asset\n\nIn this section, we outline security considerations and recommendations for listing 4626 vaults as an asset, collateral, or loan asset.\n\n### Vault as collateral\n\n#### Liquid & flashloanable 4626 assets with share price decrease\n\nERC4626 vaults with the following properties can incur a loss of funds.\n\n- Most of the shares of the vault can be flash loaned.\n- Most of the vault is liquid.\n- The vault's share price can decrease notably and instantly.\n\nThis is not specific to Morpho but a general statement for all ERC4626 vaults. Since assets deposited on Morpho can always be flash loaned, it is important to keep in mind.\n\nThe loss is bounded by:\n\n```math\ntotalLoss \\le \\delta\\frac{1}{1-\\min(\\frac{A_W}{A}, \\frac{S_L}{S})}\n```\n\nwhere:\n\n- The loss on the vault (that creates the share price decrease):\n```math\n\\delta\n```\n- The liquid portion of the vault:\n```math\n\\frac{A_W}{A}\n````\n\n- The loanable portion of the vault:\n```math\n\\frac{S_L}{S}\n```\n\n#### Recommendations for Morpho Vaults used as collateral\n\nFor Morpho Vaults **with bad debt realization** (created with [the MetaMorpho Factory V1.0](https://github.com/morpho-org/metamorpho)), the share price can decrease in the event of a bad debt realization in one of the listed markets. If the vault is highly liquid, the supply queue has a specific order, and most of the shares can be flashloaned, then the liquidator of the market could amplify bad debt realized by the vault. Since using vaults as collateral increases the proportion of the vault that can be flashloaned, it could favor this amplification. Although very unlikely, it is thus not recommended using those vaults as collateral.\n\nFor Morpho vaults **without bad debt realization** (created with [the MetaMorpho Factory V1.1](https://github.com/morpho-org/metamorpho-v1.1)), the share price of the vault can't decrease, and the above-described scenario can't happen. That said, the vault users won't have bad debt realized in their vault.\n\nCredit to [100proof](https://x.com/1_00_proof) on helping the Morpho team providing those security guidelines to vault curators.\n\n### Vault as loan asset\n\n#### Pricing method\n\nOne of the main considerations when onboarding an asset is what price it should have. A natural way to price vault shares is by using the exchange rate (supported by the [Morpho Oracle V2](https://github.com/morpho-org/morpho-blue-oracles)). We summarise here the risks associated with using this pricing method and recommendations when doing so.\n\n#### Manipulations & share price changes\n\nGeneral manipulations of an ERC4626 are detailed in an [Euler article](https://www.euler.finance/blog/exchange-rate-manipulation-in-erc4626-vaults). Additionally, we should take into account the other possible ways that the share price of a vault can change.\n\nWe have in the general case:\n\n1. **donations** in general to ERC4626 vaults can cause a sudden price increase. Vaults can have mitigations to this, but most are vulnerable. Morpho Vaults can be affected because of supply on behalf.\n\n2. **rounding errors** (including stealth donations) can change the share price. They are not expected to be significant, including for Morpho Vaults when the vault has a large enough total assets.\n\nAnd the ones specific to each vaults. For example in Morpho vaults:\n\n3. **“economic”**, known scenarios could decrease the share price on Morpho Vaults. They should be accepted by the user for what they are, so they are not considered as blocking. It includes bad debt realization for Morpho Vaults V1.0 (note that public reallocation can be an aggravating factor in this scenario) and forced market removal.\n\nThe price change by donation causes a price increase, so it naturally is an issue for listing a vault as a loan asset. In particular, it leads to:\n\n- the possibility of a future attack like the Cream hack, as soon as the position of those shares is priced\n- liquidations having an extra incentive that is extremely difficult to mitigate, resulting in borrowers taking unpredictable risks (or not joining at all).\n\n**Because of those risks, it is not recommended to list any ERC4626 vault as a loan asset in a Morpho market at the moment.**\n\n## Inflation Front-Running Attack Protection\n\nMorpho Vaults V1, like all ERC4626-compliant vaults, have a potential vulnerability to what is known as an \"inflation front-running attack,\" particularly when the vault is newly created and empty. This vulnerability is explicitly mentioned in the Morpho Vault contract:\n\n```solidity\n/// @inheritdoc IERC4626\n/// @notice For tokens with 18 decimals, the protection against the inflation front-running attack is low. To\n/// protect against this attack, vault deployers should make an initial deposit of a non-trivial amount in the vault\n/// or depositors should check that the share price does not exceed a certain limit.\n\n```\n\n### What is an Inflation Front-Running Attack?\n\nThis attack works as follows:\n\n1. An attacker sees a pending transaction where a user intends to deposit into an empty (or nearly empty) vault\n2. The attacker front-runs the transaction with a minimal deposit followed by a large donation directly to the vault\n3. This artificially inflates the share price of the vault\n4. When a user’s deposit execute and is small enough, they receive significantly fewer shares than expected\n5. The attacker, as the majority shareholder, can benefit from this manipulation if more than one user deposit receives fewer shares than expected\n\nThis vulnerability is most pronounced for tokens with 18 or more decimals, where the `DECIMALS_OFFSET` in the Morpho Vault V1 contract is zero.\n\n### Best Practices for Morpho Vault Curators\n\n1. **Initial Protection**: Always make an initial deposit of at least 1e9 shares (or 1e12 shares for assets with less than 9 decimals) immediately after vault and market creation on behalf of the address `0x000000000000000000000000000000000000dEaD`. Ensure that all of the markets that the vault allocates to have this deposit as well.\n2. **Timelock**: Implement a 3-day timelock to give enough time to review any new markets before adding them to the vault's allocation.\n3. **Monitoring**: Monitor the vault's share price relative to the underlying asset price to detect potential manipulation\n\n### Technical Details\n\nThe vulnerability exists because in ERC4626 vaults, the relationship between shares and assets determines the exchange rate. In an empty vault with no protection mechanisms:\n\n1. The attacker deposits a minimal amount (e.g., 1 wei of the token) and receives 1 share\n2. The attacker then transfers a large amount directly to the vault (e.g., 100M tokens)\n3. This creates an exchange rate where 1 share ≈ 100M tokens\n4. A user depositing 1 token would receive 0 shares due to the inflated exchange rate\n\nThe protection mechanisms recommended above prevent this by ensuring the vault has enough tokens to dilute to make the share price increase by donation prohibitively expensive or by adding checks that would reject transactions with suspicious exchange rates.\n\n### Additional Resources\n\nFor more information on ERC4626 and the inflation attack vulnerability:\n\n- [OpenZeppelin ERC4626 Documentation](https://docs.openzeppelin.com/contracts/5.x/erc4626)\n- [EIP-4626: Tokenized Vault Standard](https://eips.ethereum.org/EIPS/eip-4626)\n- [YieldBox Approach to ERC4626 Security](https://github.com/boringcrypto/YieldBox)"
  },
  "/curate/concepts/timelock/": {
    "title": "Timelock",
    "url": "https://docs.morpho.org/curate/concepts/timelock/",
    "section": "Curate",
    "content": "The timelock is a cornerstone of security in Morpho Vaults. It is a mandatory waiting period for sensitive administrative actions, designed to protect depositors by ensuring transparency and providing a window to react to proposed changes. This mechanism is fundamental to the noncustodial nature of the vaults.\n\n### The Timelock Process\n\nA timelock enforces a simple but powerful workflow for critical changes:\n\n1.  **Submit**: An administrator (the `Curator` in V2 and `Owner` in V1) proposes a change by submitting it to the vault contract.\n2.  **Wait**: The proposal becomes pending and enters a waiting period. The duration of this period is defined by the timelock. During this time, the change cannot be executed, and anyone can review it onchain.\n3.  **Execute**: Once the timelock duration has passed, anyone can call the function to execute the proposed change, making it final.\n\nThis delay is crucial, as it prevents malicious or erroneous changes from taking effect instantly, giving users and safety roles (`Sentinel`/`Guardian`) time to intervene or withdraw their funds.\n\n## Timelocks in Morpho Vaults V2: Granular and Flexible Security\n\nVaults V2 upgrade the timelock concept significantly by introducing **per-function timelocks**. This allows for a more nuanced and sophisticated approach to security.\n\n### How It Works: Timelocks per Selector\n\nInstead of a single, global timelock for the entire vault, a V2 `Curator` can assign a different timelock duration to each sensitive action, identified by its function `selector`.\n\nThis flexibility allows for risk-based security policies. For example, a Curator might configure their vault with:\n-   A **7-day timelock** for high-risk actions like enabling a new, untested adapter.\n-   A **1-day timelock** for routine, lower-risk actions like appointing a new `Allocator`.\n-   A **0-second timelock** for actions they deem completely safe (though this is less common for production vaults).\n\n### Timelock Management in V2\n\nThe `Curator` has a specific set of tools to manage these timelocks, each with its own security logic:\n\n-   **Increasing Timelocks (`increaseTimelock`)**: A Curator can increase the duration of any timelock. This action is itself **timelocked**, meaning it must go through the standard submit-and-execute process. However, if the current timelock for `increaseTimelock` is set to 0, it can be executed immediately.\n\n-   **Decreasing Timelocks (`decreaseTimelock`)**: This action is highly sensitive. The timelock for `decreaseTimelock` **equals the current timelock of the function being decreased**. This prevents a malicious actor from instantly reducing all safety delays to zero, as they must wait through the same delay period as the function they're trying to reduce.\n\n-   **Abdicating Actions (`abdicate`)**: A Curator can choose to **permanently and irreversibly** disable their ability to submit a certain type of change by setting its timelock to infinity. This is a powerful \"trust-hardening\" feature. For example, a vault could abdicate the ability to ever set a `Gate`, guaranteeing to its users that it will remain permissionless forever.\n\n## Timelocks in Morpho Vaults V1\n\nIn contrast, Morpho Vaults V1 use a **global timelock** system. A single timelock duration applies to all protected actions within the vault, such as increasing a market's supply cap or setting the `Guardian`.\n\n### Key Characteristics of V1 Timelocks\n\n-   **Flexible Initial Setup**: The timelock can be set to zero at deployment. This is a major convenience that allows vault administrators to perform the initial configuration and market setup instantly without waiting periods.\n-   **Post-Setup Security**: After the initial setup, any change to the timelock must set its duration to be between **1 day and 2 weeks**.\n-   **Asymmetric Updates**:\n    -   **Increasing** the timelock takes effect immediately.\n    -   **Decreasing** the timelock is itself a timelocked action, requiring a wait equal to the *current* (longer) timelock duration.\n\nThis V1 model provides robust security while allowing for practical initial vault deployment.\n\n### Viewing Timelock Settings\n\nYou can check the current timelock value(s) for any Morpho Vault by visiting the \"Read Contract\" section on a blockchain explorer and querying the `timelock` function.\n- In **V2**, this function takes a function `selector` as an argument.\n- In **V1**, it returns the single, global timelock duration in seconds.\n\n## Comparison: Vaults V2 vs. Vaults V1\n\n| Feature                     | Morpho Vaults V2                                          | Morpho Vaults V1 (MetaMorpho)                               |\n| --------------------------- | --------------------------------------------------------- | ----------------------------------------------------------- |\n| **Timelock Structure**      | **Per-function timelocks** (granular control)             | **Global timelock** (single duration for all actions)       |\n| **Timelock Assignment**     | Different durations per function selector                  | One duration applies to all protected actions               |\n| **Increasing Timelocks**    | **Timelocked** (subject to its own timelock duration)     | **Instant** (takes effect immediately)                      |\n| **Decreasing Timelocks**    | **Equals the timelock of the function being decreased**   | Subject to **current timelock** duration                    |\n| **Initial Setup**           | **Can be set to zero** at deployment (default is 0)        | **Can be set to zero** at deployment                        |\n| **Permitted Range**         | Flexible (can be set to infinity via abdication)          | **1 day to 2 weeks** (after initial setup)                 |\n| **Abdication Feature**      | **Yes** (can permanently disable actions)                 | **No**                                                       |"
  },
  "/curate/concepts/yield/": {
    "title": "Yield Generation",
    "url": "https://docs.morpho.org/curate/concepts/yield/",
    "section": "Curate",
    "content": "Understanding how yield is generated, accounted for, and distributed is fundamental to curating a successful Morpho Vault. The mechanism for handling yield has evolved from a fully automated onchain system in Vaults V1 to an even more streamlined, adapter-based model in Vaults V2.\n\n  \n\n## Yield in Morpho Vaults V1\n\nIn Vaults V1, yield generation is a direct and automatic process tied exclusively to **Morpho Market V1**.\n\n### The V1 Yield Flow\n\n1.  **Allocation**: The vault allocates capital to one or more Morpho Market V1 instances, as directed by the `Allocator`.\n2.  **Interest Paid by Borrowers**: Borrowers in those markets pay interest on their loans according to the market's specific Interest Rate Model (IRM).\n3.  **Onchain Accrual**: This interest automatically accrues to all lenders in the market, including the Morpho Vault.\n4.  **Automatic `totalAssets` Update**: When any user interacts with the vault (e.g., deposits or withdraws), the vault contract automatically calculates its total assets by summing up its underlying positions on Morpho Market V1. This process is fully onchain and reflects the real, up-to-the-second value of its holdings.\n5.  **Share Price Growth**: As `totalAssets` increases from the accrued interest, the value of each vault share appreciates, delivering yield to depositors.\n\nThe key takeaway for V1 is that yield is **passively received and automatically accounted for**. The Curator's job is to select the right markets, not to manage the yield calculation itself.\n\n## Yield in Morpho Vaults V2\n\nVaults V2 are designed to be future-proof, capable of allocating assets to countless different yield sources. Like V1, the yield calculation remains fully automated through a streamlined adapter-based architecture.\n\n### Automatic Asset Reporting via Adapters\n\nEach **Adapter** in Vaults V2 implements a `realAssets()` function that reports the current value of all investments it manages. This allows the vault to automatically aggregate yield from diverse sources.\n\n-   **Adapter Responsibility**: Each adapter is responsible for accurately reporting the current value of its investments through `realAssets()`.\n-   **Automatic Aggregation**: The vault calculates its total assets by summing the `realAssets()` from all adapters plus any idle assets.\n-   **Protocol Flexibility**: This model allows the vault to account for yield from any source while maintaining automated, onchain accuracy.\n\n### The V2 Yield Flow\n\n1.  **Allocation**: The `Allocator` deploys capital to various protocols through **Adapters** (e.g., to Morpho Market V1, Morpho Vault V1, etc.).\n2.  **Yield Generation**: Each underlying position generates yield according to its own protocol's rules.\n3.  **Real-time Reporting**: Each adapter continuously tracks the current value of its investments and reports this via `realAssets()`.\n4.  **Vault Accrual**: When a user interacts with the vault, the vault automatically queries all adapters' `realAssets()` and updates its `totalAssets` accordingly.\n5.  **Share Price Growth**: As the real asset values increase from yield generation, the vault's share price increases automatically, delivering yield to depositors.\n\n### Adapter Examples\n\nThe initial adapter implementations demonstrate this automatic approach:\n\n-   **`MorphoMarketV1AdapterV2`**: Automatically queries Morpho Market V1 to report the current value of supply positions, including any accrued interest.\n-   **`MorphoVaultV1Adapter`**: Automatically queries the share price of the underlying Morpho Vault V1 to report current asset values.\n\n### Interest Rate Controls\n\nWhile yield tracking is automatic, Curators can set additional controls:\n\n#### maxRate\n\nA curator-controlled parameter that caps how quickly `totalAssets` can grow, useful for implementing fixed-rate distributions or preventing unrealistic yield spikes.\n\nThe `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))\n\nIf `maxRate` is 0, yield does not accrue to vault's suppliers.\n\n### Practical Implications for Curators\n\n-   **V1 Curation**: Focus on **market selection** and **capital allocation**. Yield accounting is handled by the protocol.\n-   **V2 Curation**: Focus on **protocol selection**, **adapter enablement**, and **capital allocation**. Yield accounting remains automated through adapter reporting, with optional rate controls via `maxRate`.\n-   **Simplified Management**: Unlike manual rate-setting systems, the adapter-based approach eliminates the risk of mispricing yield while maintaining the flexibility to integrate with any protocol."
  },
  "/curate/tool-suite/": {
    "title": "Morpho Tool Suite",
    "url": "https://docs.morpho.org/curate/tool-suite/",
    "section": "Curate",
    "content": "This section details the critical applications developed by the Morpho Association for effective vault management and ecosystem participation. Each application serves specific functions in the curation workflow.\n\n## Prime Apps\n\n### Curator App V2 - [curator.morpho.org](https://curator.morpho.org/vaults)\n\n**Purpose:** Delivers specialized tools for Morpho Vault V2 curators to manage vault operations.\n\n**Key Features:**\n\n- Create and deploy new vaults V2\n- Curate adapter listings and parameters\n- Configure vault settings and permissions\n- Set allocation caps, strategies and timelocks\n\n**Version:** Beta deployment with ongoing feature development\n\n**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/).\n\n### Curator App V1 - [curator-v1.morpho.org](https://curator-v1.morpho.org/)\n\n**Purpose:** Delivers specialized tools for Morpho Vault V1 curators to manage vault operations.\n\n**Key Features:**\n\n- Create and deploy new vaults V1\n- Curate market listings and parameters\n- Configure vault settings and permissions\n- Set allocation caps, strategies and timelocks\n\n**Version:** Beta deployment with ongoing feature development\n\n**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/).\n\n## Utility Apps\n\n### Oracle Decoder - [oracles.morpho.dev](https://oracles.morpho.dev/oracle-decoder)\n\n**Purpose:** Aid oracle configurations to ensure price feed accuracy and security.\n\n**Key Features:**\n\n- Decode oracle configurations\n- Verify price accuracy against reference sources\n- Test oracle configurations\n- Identify configuration issues\n\n**Version:** Production\n\n**Implementation Note:** Always verify oracle data configurations before deploying to production environments. Use this tool to:\n\n1. Confirm correct asset pricing\n2. Validate operational parameters\n3. Test edge case scenarios \n\n### Liquidation App - [liquidation.morpho.org](https://liquidation.morpho.org/)\n\n**Purpose:** Provides manual liquidation capabilities for unhealthy positions.\n\n**Key Features:**\n\n- Identify liquidatable positions\n- Execute manual liquidations\n- Calculate liquidation profitability\n- Monitor position health metrics\n\n**Version:** Production and requires supplemental automation\n\n**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.\n\n## Consumer Apps\n\n### Main App - [app.morpho.org](https://app.morpho.org/)\n\n**Purpose:** Interface for both lenders interacting with Morpho vaults and Borrowers interacting with Morpho Markets.\n\n**Key Features:**\n\n- View all Morpho Markets & Morpho Vaults\n- Deposit, manage, and exit positions in Morpho Vaults\n- Enter, manage, and exit from borrow positions\n- Track vault performance metrics\n- Monitor position health and market statistics\n\n**Version: Production**\n\n### Fallback App - [fallback.morpho.org/](https://fallback.morpho.org/)\n\n**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.\n\n**Key Features:**\n\n- View your Morpho Markets & Morpho Vaults positions\n- Exit positions from Morpho Vaults and Morpho Markets\n\n**Version: Production**\n\n### Data Dashboard - [data.morpho.org](https://data.morpho.org/)\n\n**Purpose:** Provides on-chain data and analytics for the Morpho ecosystem.\n\n**Version:** Production\n\n## External Apps - Rewards\n\nRewards on Morpho are distributed via the Merkl stack. One can create rewards programs, monitor rewards programs details at protocol level or for a specific user, and claim rewards via the Merkl app.\n\nThis external application is provided by [Merkl](https://x.com/merkl_xyz). The Morpho Association does not endorse or guarantee its functionality. Use at your own discretion.\n\n- [campaigns.morpho.org](https://campaigns.morpho.org/)\n\n## Bots and automations\n\n### Liquidation bot - [morpho-blue-liquidation-bot](https://github.com/morpho-org/morpho-blue-liquidation-bot)\n\n**Purpose:** A simple, fast, and easily deployable liquidation bot for the Morpho V1 protocol. This bot is entirely based on RPC calls and is designed to be easy to configure, customizable, and ready to deploy on any EVM-compatible chain.\n\n**Key Features:**\n\n- Automatically detects liquidatable positions and executes the liquidations.\n- Also supports Morpho Blue pre liquidations.\n- Multi-chain compatible.\n- Configurable liquidity venues.\n- Profit evaluation thanks to configurable pricers.\n- Minimal setup and dependencies (RPC-only, no extra infra required).\n\n### Vault V2 Reallocation bot - [vault-v2-reallocation-bot](https://github.com/morpho-org/vault-v2-reallocation-bot)\n\n**Purpose:** A simple, fast, and easily deployable reallocation bot for the Morpho Vaults V2. This bot is entirely based on RPC calls and the Morpho API and is designed to automate Morpho Vaults V2 reallocations according customable strategies.\n\n**Key Features:**\n\n- Automatically rebalances assets within Morpho Vaults V2 to maintain capital efficiency\n- Equalizes utilization rates across markets\n- Multi-chain compatible (Ethereum, Base, and more)\n- Configurable minimum threshold for utilization changes (2.5% by default)\n\nThis bots are provided as-is, without any warranty. The Morpho Association is not responsible for any potential loss of funds resulting from the use of this bot, including (but not limited to) gas fees, failed transactions, liquidations or reallocations on malicious or misconfigured markets."
  },
  "/curate/tutorials-market-v1/creating-market/": {
    "title": "Create a Market",
    "url": "https://docs.morpho.org/curate/tutorials-market-v1/creating-market/",
    "section": "Curate",
    "content": "This tutorial guides you through the process of creating and configuring a market in your Morpho vault.\n\nYou have to carefully validate the `oracle` configuration you expect to use for the market you intend to deploy. Refer to the [previous section](/curate/tutorials-market-v1/deploying-oracle/) to check how to validate an oracle configuration.\n\nMake sure to implement protection against inflation front-running attacks. These attacks can allow malicious users to extract value from the market. For detailed explanation and protection measures, refer to the [inflation front-running attack protection section](/learn/resources/risks/#inflation-front-running-attack-protection).\n\nFor permanent protection, it consists in supplying at least 1e9 shares (or 1e12 shares for assets with less than 9 decimals) in the market on behalf of the address `0x000000000000000000000000000000000000dEaD`\n\n## Deploying a Market via Etherscan\n\n### Jump on the Morpho contract\n\n    See the [address section](/get-started/resources/addresses/).\n\n    E.g: Ethereum mainnet address is [0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb](https://etherscan.io/address/0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb#writeContract)\n\n### Fill all attributes\n\nJump on the `createMarket` function\n\n    - `loanToken`: paste the address of the loan token,\n    - `collateralToken`: paste the address of the collateral token,\n    - `oracle`: paste the oracle address,\n    - `irm`: paste the Interest Rate Model address,\n    - `lltv`: the LLTV is defined with 18 decimals. 1e18 represents an LLTV of 100% (which is not enabled) and 945000000000000000 thus represents 94.5%.\n\nBelow is a short list of things to have in mind when creating a new market:\n\nThe LLTV a market creator is expecting to use has to be enabled. At first, the following LLTVs have been governance-approved:\n\n| LLTV (%) | Solidity Values (scaled by 1e18) |\n| -------- | -------------------------------- |\n| 0        | 0                                |\n| 38.5     | 385000000000000000               |\n| 62.5     | 625000000000000000               |\n| 77.0     | 770000000000000000               |\n| 86.0     | 860000000000000000               |\n| 91.5     | 915000000000000000               |\n| 94.5     | 945000000000000000               |\n| 96.5     | 965000000000000000               |\n| 98.0     | 980000000000000000               |\n\nIf you consider using a vault as loan or collateral token, please read the section below about [Vault as Asset](/curate/concepts/security-considerations/)\n\n- **Issue**: At deployment, a market starts with 0% utilization, which causes interest rates to quickly decay to extremely low levels, creating a poor user experience.\n- **Solution**: Add $1 of supply and borrow $0.90 immediately after market creation to establish 90% utilization (matching the Adaptive Curve IRM target). This prevents rate decay and ensures market stability from the start.\n- **Best practice**: Batch the market creation with supply and borrow transactions to achieve your desired utilization target. While 90% is recommended for the default IRM, other targets may be appropriate depending on your specific rate goals.\n- **Warning**: Without this intervention, markets intended for future use may already have extremely low rates by the time users start interacting with them, requiring significant time to return to reasonable levels.\n\n### Sign the transaction\n\nYou are done.\n\n## Idle markets\n\nIdle markets on Morpho are markets where funds can not be borrowed. This liquidity earns no yield from borrowers but can be used as an immediately available buffer for withdrawals. Idle markets are used by curators in [liquidity curation](/curate/concepts/liquidity#curation-in-morpho-vaults-v1) for Morpho Vaults V1.\n\nTo create an idle market, one has to reproduce the same steps than for an any market, except that the only variable field is the `loanToken` one, all other fields are using the 0 address or 0.\n\nHere is an example from the USDC idle market on Ethereum (0x54efdee08e272e929034a8f26f7ca34b1ebe364b275391169b28c6d7db24dbc8):\n    - `loanToken`: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\n    - `collateralToken`: 0x0000000000000000000000000000000000000000\n    - `oracle`: 0x0000000000000000000000000000000000000000\n    - `irm`: 0x0000000000000000000000000000000000000000\n    - `lltv`: 0\n\nBefore creating an idle market for a specific asset on a specific chain, make sure the market does not exist already (see [Market ID Generator below](/curate/tutorials-market-v1/creating-market/#resource-market-id-generator)).\n\n## Important Note\n\n### Market Id Retrieval\n\nWhen creating a market, a `CreateMarket` event is emitted with the market `id`:\n\n  \n\nTo retrieve the market parameters from this `id`:\n\n#### Navigate to the Morpho contract on Etherscan\n\n#### Go to the \"Read Contract\" tab\n\n#### Find the `idToMarketParams` function\n\n#### Paste the `id` into the input field and execute\n\nExample: Using the `id`: `0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc`\n\n## Resource: Market ID Generator\n\nUse this tool to generate the unique market ID from your market parameters:"
  },
  "/curate/tutorials-market-v1/dead-deposit/": {
    "title": "Market Dead deposit",
    "url": "https://docs.morpho.org/curate/tutorials-market-v1/dead-deposit/",
    "section": "Curate",
    "content": "This tutorial explains how to set up a dead deposit for a Market V1.\n\nA dead deposit is a security measure against ERC-4626 inflation attacks ([read more](/build/earn/concepts/vault-mechanics#inflation-attack-protection)).\n\nSetting up a dead deposit involves supplying 1e9 shares (or 1e12 shares for assets with less than 9 decimals) to the target market, on behalf of address `0x000000000000000000000000000000000000dEaD`, through a simple process on a block explorer like Etherscan:\n\n1. Find the Morpho contract on the target chain in the [Addresses page](/get-started/resources/addresses#morpho-v1-contracts).\n\n2. Approve the Morpho contract to spend the market's loan token on your behalf. You can do this on the loan token's contract. Approve enough assets to cover 1e9 vault shares (or 1e12 shares for assets with less than 9 decimals).\n\n  \n\n3. Use the Morpho contract's `supply` function to supply 1e9 shares (or 1e12 shares for assets with less than 9 decimals) to the market on behalf of address `0x000000000000000000000000000000000000dEaD`.\n\n  \n\nOnce the transaction is confirmed, the market will be secured with a dead deposit."
  },
  "/curate/tutorials-market-v1/deploying-oracle/": {
    "title": "Deploy an Oracle for Morpho Markets",
    "url": "https://docs.morpho.org/curate/tutorials-market-v1/deploying-oracle/",
    "section": "Curate",
    "content": "Oracle deployment is a critical step when creating lending markets in Morpho, as these smart contracts provide essential price information that powers core functionalities like collateral evaluation and liquidation triggers. This guide will walk you through the entire process of configuring, testing, and deploying an oracle using the Morpho ecosystem tools.\n\n## Understanding Oracles in Morpho\n\nBefore jumping into deployment, let's review what oracles do in the Morpho ecosystem:\n\n- **Purpose**: Oracles provide price data that determines what one token is worth relative to another\n- **Implementation**: Morpho takes an oracle-agnostic approach, allowing market creators to choose appropriate price feed mechanisms\n- **Interface**: All oracles implement the `IOracle` interface with a single standardized function: `price()`\n- **Immutability**: Once a market is deployed, its oracle address cannot be modified, making correct setup crucial\n\n## The Oracle Deployment Process\n\nThis guide covers the complete process of deploying a new oracle using:\n\n1. **MorphoChainlinkOracleV2Factory**: The contract used to create new oracles\n2. **Oracle Tester Tool**: A web interface to validate your configuration and prepare deployment\n3. **Oracle Decoder**: A tool to run additional checks on your configuration post-deployment\n\n## Step 1: Understanding the Oracle Parameters\n\nThe `MorphoChainlinkOracleV2Factory` requires several parameters that determine how the oracle will calculate prices. Let's break them down:\n\n### Key Parameters\n\n| Parameter                    | Description                                                                 |\n| ---------------------------- | --------------------------------------------------------------------------- |\n| `baseVault`                  | ERC4626 vault for the collateral token (zero address if not applicable)     |\n| `baseVaultConversionSample`  | Amount of base vault shares for conversion calculation (use 1 if no vault)  |\n| `baseFeed1`                  | First price feed for the collateral token (zero address if not needed)      |\n| `baseFeed2`                  | Second price feed for the collateral token (zero address if not needed)     |\n| `baseTokenDecimals`          | Decimal precision of the base/collateral token                              |\n| `quoteVault`                 | ERC4626 vault for the loan token (zero address if not applicable)           |\n| `quoteVaultConversionSample` | Amount of quote vault shares for conversion calculation (use 1 if no vault) |\n| `quoteFeed1`                 | First price feed for the loan token (zero address if not needed)            |\n| `quoteFeed2`                 | Second price feed for the loan token (zero address if not needed)           |\n| `quoteTokenDecimals`         | Decimal precision of the quote/loan token                                   |\n| `salt`                       | Unique identifier for deterministic address creation (typically \"0x\")       |\n\n### Common Oracle Configurations\n\nDifferent asset pairs require different oracle configurations. Here are some common patterns:\n\n1. **Standard tokens (ETH/USDC)**: Direct price feed with no vaults\n2. **Wrapped tokens (wstETH/ETH)**: Requires special exchange rate adapter\n3. **Yield-bearing tokens (sDAI/USDC)**: Requires vault configuration (sDAI -> DAI -> USD -> USDC or sDAI -> DAI -> USDC)\n\n## Step 2: Using the Oracle Tester Tool\n\nThe Oracle Tester tool helps you validate your configuration before deployment, saving gas and preventing errors. Here's how to use it:\n\n  \n\n### Accessing the Oracle Tester\n\n#### Navigate\n\nJump on the Morpho Oracle Interface at [oracles.morpho.dev](https://oracles.morpho.dev/oracle-tester)\n\n#### Tester section\n\nVerify you are on the \"Tester\" tab in the navigation menu\n\n#### Form section\n\nYou'll see a form for configuring and testing your oracle\n\n### Basic Steps\n\n#### Select Network\n\nChoose the blockchain where you'll deploy your oracle. All blockchains where Morpho contracts were deployed are supported. Verify the addresses [here](/get-started/resources/addresses/#morpho-contracts).\n\n#### Select Assets\n\n- Choose the **Collateral Asset** (the token that will be used as collateral)\n- Choose the **Loan Asset** (the token that will be borrowed)\n- If your token isn't listed, click \"Add New Asset\" to add custom token information\n\n### Advanced Configuration\n\nAfter selecting your assets, you'll need to fill in the detailed oracle parameters:\n\n#### Base (Collateral) Configuration\n\n- **Base Vault**: If your collateral is an ERC4626 token, enter the vault address. Otherwise, use the default zero address (`0x0000000000000000000000000000000000000000`).\n- **Base Vault Conv. Sample**: Default is 1 if using zero address for Base Vault. For ERC4626 tokens, use a value like `1000000000000000000` (1e18) to ensure precision. This value is used to query the `convertToAsset` function on the Base Vault address you put thus needs enough precision.\n\n  ##### Understanding Vault Conversion Samples\n\n  For ERC4626 tokens like sDAI, the Vault Conversion Sample is critical for accurate pricing:\n\n  1. **What it does**: The conversion sample represents the amount of vault shares (e.g., sDAI) that will be passed to the vault's `convertToAssets` function to determine the equivalent amount of underlying tokens (e.g., DAI).\n\n  2. **Why it matters**: The `convertToAssets` function returns how much of the underlying asset (e.g., DAI) you would receive if you redeemed a given amount of vault shares (e.g., sDAI).\n\n  3. **Choosing a value**:\n\n     - For non-vault tokens: Use `1`\n     - For ERC4626 tokens: Use a value with sufficient precision, typically `1000000000000000000` (1e18)\n\n  4. **Example with sDAI**:\n\n     - When we set `baseVault` to the sDAI vault address (0x83F20F44975D03b1b09e64809B757c47f942BEeA)\n     - And `baseVaultConversionSample` to 1e18 (1 full share)\n     - The oracle internally calls `convertToAssets(1e18)` on the sDAI vault\n     - This returns the current amount of DAI that 1e18 sDAI shares are worth\n     - This exchange rate is then used in the price calculation alongside the DAI/USD price feed\n\n  5. **Formula visualization**:\n     For a sDAI/USDC oracle, the pricing path is:\n     ```\n     sDAI → DAI (via vault conversion) → USD (via DAI/USD feed) → USDC (via USDC/USD feed)\n     ```\n     The vault conversion is the first step in establishing the price routing path for ERC4626 tokens, allowing accurate relative valuation between yield-bearing tokens and their non-yield-bearing counterparts.\n\n- **Base Feed 1**: The primary price feed for your collateral asset. This could be a Chainlink, Redstone, Pyth, or Chronicle, ...\n- **Base Feed 2**: If needed, a secondary price feed for route calculation. Often the zero address.\n- **Base Token Decimals**: The decimal precision of your collateral token. In most of the case, it should match the actual collateral token decimals. If a Base Vault is put, use the underlying asset decimals. (Eg: if `sDAI` is put in Base Vault, use `DAI` decimals)\n\n#### Quote (Loan) Configuration\n\n- **Quote Vault**: If your loan token is an ERC4626 token, enter the vault address. Otherwise, use the zero address.\n- **Quote Vault Conv. Sample**: Similar to Base Vault Conversion Sample, default is 1.\n- **Quote Feed 1**: Primary price feed for the loan asset.\n- **Quote Feed 2**: Secondary price feed if needed.\n- **Quote Token Decimals**: The decimal precision of your loan token.\n\n#### Salt Configuration\n\n- **Salt**: This is typically set to `0x` for initial deployments. It's used to create deterministic addresses. This means that changing the salt, with the very same config, will create a different oracle address.\n\nThe `Base` and `Quote` configuration are not 'strictly' only for pricing the collateral or respectively only for the loan. One needs to understand that base feeds can be read in the 'left to right' direction, where quote from 'right to left' direction in the virtual mental route.\n\nLet's take two examples:\n\n**Example A:**\n\n- Base Feed 1: DAI -> USD\n- Quote Feed 1: USDC -> USD\n\nThe virtual route is:\n\n- DAI -> USD + USD -> USDC\n- -> thus DAI -> USDC.\n\nAn oracle having the previous base and quote feed provided will be usable for a DAI as collateral and USDC as loan assets market.\n\n**Example B:**\n\n- Base Vault 1: sDAI (implicitly, this corresponds to creating the sDAI -> DAI onchain feed)\n- Base Feed 1: DAI -> USD\n- Quote Feed 1: USDC -> USD\n\nThe virtual route is:\n\n- sDAI -> DAI + DAI -> USD + USD -> USDC\n- -> thus sDAI -> USDC.\n\nAn oracle having the previous base vault and base and quote feeds provided will be usable for a sDAI as collateral and USDC as loan assets market.\n\n#### Scale Factor\n\nAfter deployment, the oracle deployed will contain a `SCALE_FACTOR` that is calculated to properly normalize price values between different tokens, taking into account:\n\n- Decimal differences between tokens\n- Feed precision values\n- Vault conversion samples (for ERC4626 yield-bearing tokens)\n\n##### Scale Factor Computation\n\nThe `SCALE_FACTOR` in the Morpho Chainlink Oracle V2 is calculated to properly normalize price values between different tokens, taking into account:\n\n- Decimal differences between tokens\n- Feed precision values\n- Vault conversion samples (for ERC4626 yield-bearing tokens)\n\n```math\n\\text{SCALE\\_FACTOR} = 10^{\\text{exponent}} \\times \\frac{\\text{quote\\_vault\\_conversion\\_sample}}{\\text{base\\_vault\\_conversion\\_sample}}\n```\n\n```math\n\\text{exponent} = 36 + \\text{quoteContribution} - \\text{baseContribution}\n```\n\nWhere:\n\n```math\n\\text{quoteContribution} = \\text{quote\\_token\\_decimals} + \\text{quote\\_feed1\\_decimals} + \\text{quote\\_feed2\\_decimals}\n```\n\n```math\n\\text{baseContribution} = \\text{base\\_token\\_decimals} + \\text{base\\_feed1\\_decimals} + \\text{base\\_feed2\\_decimals}\n```\n\nWith the following variables:\n\n- **base_token_decimals** = Number of decimals in the base token\n- **quote_token_decimals** = Number of decimals in the quote token\n- **base_feed1_decimals** = Decimals in the first base price feed\n- **base_feed2_decimals** = Decimals in the second base price feed\n- **quote_feed1_decimals** = Decimals in the first quote price feed\n- **quote_feed2_decimals** = Decimals in the second quote price feed\n- **base_vault_conversion_sample** = Base vault conversion sample size\n- **quote_vault_conversion_sample** = Quote vault conversion sample size\n\n##### Why Scale Factor Could Be Negative or Zero\n\nThe scale factor computation can result in undesired values due to a combination of factors:\n\n1. **Exponent Underflow**: If the sum of negative components significantly exceeds the positive components, the exponent could become negative. In Solidity, this would cause the power calculation to result in 0, as integer powers less than 0 return 0.\n\n2. **Division by Large Vault Sample**: When using ERC4626 vaults, if vault conversion sample is too large compared to the power calculation result, integer division can round down to 0. This is what often happens with yield-bearing tokens like sDAI that require large conversion sample values (1e18).\n\n3. **Precision Loss**: If the calculated value is between 0 and 1 (after division by vault conversion sample), Solidity's integer arithmetic will round it down to 0.\n\nFinding the right balance for vault conversion samples is critical. The samples need to be large enough to provide sufficient precision when converting share values to asset values, but not so large that they cause the scale factor calculation to underflow or become 0 through division.\n\n##### What to do if Scale Factor is Negative or Zero\n\nA **feed wrapper** can correct scale factor misalignment by exposing the same underlying price data but altering the feed’s reported decimals. This ensures the scale factor computed in the oracle stays positive and within the expected precision range without changing vault samples or core oracle logic.\n\n| **Situation**                       | **Feed decimals adjustment** | **Where to adjust**     | **Effect**                                                  |\n|-------------------------------------|------------------------------| ----------------------- | -------------------------------------------------------------|\n| Scale factor = 0 or extremely small | Decrease feed decimals       | Base side feed wrapper  | Raises scale factor above 0 and restores valid price output |\n| Scale factor excessively large      | Increase feed decimals       | Quote side feed wrapper | Brings scale factor back to a stable, precise range         |\n\nA **Dummy feed** providing an hardcoded 1:1 price but with a specific decimal setup can also be used to adjust final Scale factor result.\n[Here](https://etherscan.io/address/0xc3866d726C204C0836E0677A31973c649888973D#code) is a **DummyFeed** created by the community to adjust [this oracle](https://etherscan.io/address/0x95E85FeF34B79F0030f41fb619733BF7e024BD87#code).\n\nAny developer implementing a feed wrapper or a dummy feed is fully responsible for its correctness and security.  \nWrappers and dummy feeds can modify core oracle behavior and **must be independently audited** before use in production or integration with Morpho contracts.\n\n### Running Tests\n\nAfter configuring all parameters, click the \"Check\" button to run a series of tests:\n\n1. **Decimals Check**: Verifies that the token decimals match what's expected\n2. **ERC4626 Check**: Confirms if the loan asset is an ERC4626 token\n3. **Deployment Check**: Checks if an oracle with these parameters already exists [*Only on Ethereum and Base*]\n4. ~~**Feeds Check**: Feel free to ignore this one~~ [*Deprecated*]\n5. **Price Check**: Compares the calculated oracle price with expected market prices from a USD comparison price\n\nEach check will show a status indicator:\n\n- ✅ **Green** = Passed\n- ⚠️ **Yellow** = Warning or needs attention\n- ❌ **Red** = Failed check\n\n### Generating Deployment Payload\n\nIf all checks pass, click the \"Generate Payload\" button to create the transaction data you'll need for deployment. You can:\n\n1. View the payload details directly in the interface\n2. Download the payload as a JSON file\n3. Open a Safe transaction to deploy using the \"Open Safe\" button (for multisig deployments)\n\n## Step 3: Deploying the Oracle\n\nOnce you've validated your configuration, you have two options for deployment:\n\n### Option A: Deploying via Etherscan\n\n#### Find the Factory Contract\n\n- Navigate to the MorphoChainlinkOracleV2Factory address on Etherscan:\n  - Ethereum: [0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766](https://etherscan.io/address/0x3A7bB36Ee3f3eE32A60e9f2b33c1e5f2E83ad766#writeContract)\n  - Base: Check the [Morpho documentation](/get-started/resources/addresses/) for the latest address\n\n#### Connect Your Wallet\n\n- Click \"Connect to Web3\" on Etherscan\n- Connect your wallet (MetaMask, WalletConnect, etc.)\n\n#### Fill in the Parameters\n\n- Navigate to the `createMorphoChainlinkOracleV2` function\n- Input all the parameters you validated with the Oracle Tester\n- Double-check all values against your test results\n\n#### Write Contract\n\n- Click \"Write\" to send the transaction\n- Confirm the transaction in your wallet\n- Wait for the transaction to be confirmed\n\n#### Verify Deployment\n\n- Check for the `CreateMorphoChainlinkOracleV2` event in the transaction logs\n- Note the deployed oracle address for future reference\n\n### Option B: Deploying via Safe (Multisig)\n\n#### Prepare the Safe Transaction\n\n- Click \"Open Safe\" in the Oracle Tester after generating the payload\n- This will open the Safe interface with the transaction data pre-filled\n\n#### Review and Submit\\*\\*:\n\n- Review all parameters in the Safe interface\n- Submit the transaction for signing by your multisig participants\n- Execute the transaction once you have the required signatures\n\n## Step 4: Final Validation\n\nAfter deployment, it's crucial to validate that your oracle is working correctly:\n\n#### Use the Oracle Decoder Tool\n\n- Navigate to [oracles.morpho.dev/oracle-decoder](https://oracles.morpho.dev/oracle-decoder)\n- Enter your oracle address\n- Verify that it returns the expected price for your asset pair\n\n#### Check the Oracle Price\n\n- Call the `price()` function on your deployed oracle\n- Verify that the returned price is within expected ranges\n\n## Example Configurations\n\nHere are detailed examples for common token pairs:\n\n### A. cbBTC/USDC Oracle\n\n```python\nbaseVault: \"0x0000000000000000000000000000000000000000\",  // No Base Vault\nbaseVaultConversionSample: 1,                             // Default to 1 as no Base Vault\nbaseFeed1: \"0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c\",  // BTC/USD Feed\nbaseFeed2: \"0x0000000000000000000000000000000000000000\",  // - Default to Zero Address\nbaseTokenDecimals: 8,                                     // BTC Decimals\nquoteVault: \"0x0000000000000000000000000000000000000000\", // No Quote Vault\nquoteVaultConversionSample: 1,                            // Default to 1 as no Quote Vault\nquoteFeed1: \"0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6\", // USDC/USD Feed\nquoteFeed2: \"0x0000000000000000000000000000000000000000\", // -\nquoteTokenDecimals: 6,                                    // USDC Decimals\nsalt: \"0x0000000000000000000000000000000000000000000000000000000000000000\", // one can put any bytes 32 different than a deployed oracle with the very same configuration\n```\n\n  \n\n  \n\n**Explanation**:\n\n- This configuration uses a direct BTC/USD [price feed](https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&search=0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c) for calculating the cbBTC/USD feed price.\n- It also uses a USDC/USD [quote feed](https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&search=0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6) for calculating the USDC/USD feed price.\n\nAs USDC/USD is used in the quote section, the final route is:\ncbBTC -> USD -> USDC.\n\n### B. DAI/USDC Oracle - USDC Hardcoded\n\nThe particularity in this example is that removing the `QuoteFeed1` as it was in previous example acts as if someone was hardcoding the USDC price to 1 in the oracle of the market, because the virtual path is:\n\n- **Before**: DAI -> USD -> USDC\n- **Now Hardcoded**: DAI -> USD (no USD -> USDC price)\n\n```python\nbaseVault: \"0x0000000000000000000000000000000000000000\",  // -\nbaseVaultConversionSample: 1,                             // - default\nbaseFeed1: \"0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9\",  // DAI/USD Feed\nbaseFeed2: \"0x0000000000000000000000000000000000000000\",  // -\nbaseTokenDecimals: 18,                                    // DAI Decimals (NOT sDAI decimals)\nquoteVault: \"0x0000000000000000000000000000000000000000\", // -\nquoteVaultConversionSample: 1,                            // -\nquoteFeed1: \"0x0000000000000000000000000000000000000000\", // EMPTY Feed\nquoteFeed2: \"0x0000000000000000000000000000000000000000\", // -\nquoteTokenDecimals: 6,                                    // USDC Decimals\nsalt: \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n```\n\n  \n\n  \n\n**Explanation**: This configuration is using the chainlink price feed for the DAI -> USD part, and is not pricing USDC -> USD on purpose to showcase the USDC `hardcoding` method.\n\n### C. sDAI/USDC Oracle\n\n```python\nbaseVault: \"0x83F20F44975D03b1b09e64809B757c47f942BEeA\",  // sDAI Vault\nbaseVaultConversionSample: 1000000000000000000,           // 1e18\nbaseFeed1: \"0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9\",  // DAI/USD Feed\nbaseFeed2: \"0x0000000000000000000000000000000000000000\",  // -\nbaseTokenDecimals: 18,                                    // DAI Decimals (NOT sDAI decimals)\nquoteVault: \"0x0000000000000000000000000000000000000000\", // -\nquoteVaultConversionSample: 1,                            // -\nquoteFeed1: \"0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6\", // USDC/USD Feed\nquoteFeed2: \"0x0000000000000000000000000000000000000000\", // -\nquoteTokenDecimals: 6,                                    // USDC Decimals\nsalt: \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n```\n\n  \n\n  \n\n**Explanation**: This configuration handles a yield-bearing token (sDAI) by specifying its vault address and using a higher conversion sample to account for the share-to-asset conversion. The price feeds are standard Chainlink feeds for the underlying assets.\n\n### D. sDAI/USDC Oracle - USDC Hardcoded\n\n```python\nbaseVault: \"0x83F20F44975D03b1b09e64809B757c47f942BEeA\",  // sDAI Vault\nbaseVaultConversionSample: 10000000000,                   // 1e10 - Explanation below\nbaseFeed1: \"0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9\",  // DAI/USD Feed\nbaseFeed2: \"0x0000000000000000000000000000000000000000\",  // -\nbaseTokenDecimals: 18,                                    // DAI Decimals (NOT sDAI decimals)\nquoteVault: \"0x0000000000000000000000000000000000000000\", // -\nquoteVaultConversionSample: 1,                            // -\nquoteFeed1: \"0x0000000000000000000000000000000000000000\", // USDC/USD Feed\nquoteFeed2: \"0x0000000000000000000000000000000000000000\", // -\nquoteTokenDecimals: 6,                                    // USDC Decimals\nsalt: \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n```\n\n  \n\n  \n\n- **Explanation**: This configuration handles a yield-bearing token (sDAI) by specifying its vault address and using a high conversion sample (1e10) to account for the share-to-asset conversion. The price feed used in Base Feed 1 is a standard Chainlink feed.\n\nWhy `baseVaultConversionSample` is 1e10 this time?\nSometimes a vault conversion sample that is too high will result in a scale factor of 0 (or even cause a revert at deployment). A solution is to find a tradeoff by reducing the vault conversion sample value (base or quote) while keeping it high enough to maintain precision.\n\n### E. wstETH/ETH Oracle\n\n```\nbaseVault: \"0x0000000000000000000000000000000000000000\",\nbaseVaultConversionSample: 1,\nbaseFeed1: \"0x905b7dAbCD3Ce6B792D874e303D336424Cdb1421\", // wstETH/stETH adapter\nbaseFeed2: \"0x86392dC19c0b719886221c78AB11eb8Cf5c52812\", // stETH/ETH price feed\nbaseTokenDecimals: 18,\nquoteVault: \"0x0000000000000000000000000000000000000000\",\nquoteVaultConversionSample: 1,\nquoteFeed1: \"0x0000000000000000000000000000000000000000\",\nquoteFeed2: \"0x0000000000000000000000000000000000000000\",\nquoteTokenDecimals: 18,\nsalt: \"0x\",\n```\n\n**Explanation**: This configuration uses multiple feeds to establish a price path from wstETH to ETH. It requires a special adapter contract (`WstEthStEthExchangeRateChainlinkAdapter`) that handles the wstETH to stETH conversion, followed by a standard feed for stETH to ETH.\n\n## Troubleshooting Common Issues\n\n### Oracle Deployment Errors\n\n| Issue                                          | Solution                                                                      |\n| ---------------------------------------------- | ----------------------------------------------------------------------------- |\n| \"Transaction reverted\"                         | Double-check all addresses and ensure they are valid contract addresses       |\n| \"Gas estimation failed\"                        | Your configuration may be invalid or the contract cannot be executed properly |\n| \"Oracle with same parameters already deployed\" | Use the existing oracle (check the deployment check results)                  |\n\n### Price Verification Issues\n\n| Issue                                      | Solution                                                                               |\n| ------------------------------------------ | -------------------------------------------------------------------------------------- |\n| Price significantly deviates from expected | Check that your feeds are correctly configured and that the decimals are accurate      |\n| Price is zero                              | Ensure that all required feeds are working and that conversion samples are appropriate |\n| Price overflow/underflow                   | Adjust conversion samples to ensure mathematical operations don't exceed limits        |\n\n## Best Practices for Oracle Deployment\n\n1. **Always test before deploying** - Use the Oracle Tester tool to validate your configuration.\n2. **Understand token decimals** - Incorrect decimal configuration is a common source of errors.\n3. **Use reliable price feeds** - Choose established providers like Chainlink, Redstone, Chronicle, API3, Pyth ...\n4. **Check for existing oracles** - Reuse existing oracles when possible to save gas and ensure consistency.\n5. **Document your configuration** - Keep a record of all parameters for future reference.\n6. **Verify after deployment** - Always check that the deployed oracle returns expected prices.\n\n## Security Considerations\n\nSince oracles are immutable once deployed and attached to a market, their security is paramount:\n\n1. **Verify the source code** of any adapter contracts you're using\n2. **Understand the price path** and how multiple feeds work together\n3. **Consider failure modes** in your price feeds and how they could affect the oracle\n4. **Test with extreme market conditions** to ensure robustness\n\n## Community Contributions\n\nThe Morpho community has contributed various oracle adapters that can be useful for specific price feed requirements. These community-developed adapters can be found in the [Oracle Community Section](/tools/community/oracles/).\n\nBefore building your own adapter, check if the community has already developed a solution for your specific token pair or price feed requirement.\n\n## Getting Help\n\nIf you encounter issues during the oracle deployment process:\n\n1. Get in touch via the chatbox on **[help.morpho.org](https://help.morpho.org)**\n2. For complex setups, consider reaching out to the Morpho Association or to a curator directly\n\nBy following this guide, you should be able to configure, test, and deploy oracles for your Morpho markets with confidence. Remember that careful setup is essential as oracles play a critical role in market safety and cannot be changed after market deployment."
  },
  "/curate/tutorials-market-v1/permissioned-assets/": {
    "title": "Handling Permissioned Tokens in the Morpho App",
    "url": "https://docs.morpho.org/curate/tutorials-market-v1/permissioned-assets/",
    "section": "Curate",
    "content": "Some loan assets and collaterals supported by the Morpho protocol are permissioned tokens.\nThese tokens require specific contract whitelisting to function properly in the Morpho app (frontend & SDKs).\n\nIndeed, Morpho’s Bundler3 system uses adapters to handle token operations and the main Morpho app and SDK require the general adapter to simulate and execute transactions involving permissioned tokens.\nIf the general adapter is not whitelisted, the bundler flow breaks and users cannot interact with permissioned tokens through the app.\n\n## Issuer whitelisting requirements\n\nTo enable a permissioned token to work in the Morpho app, the token issuer must whitelist at token level the following contracts:\n- `Morpho` — core lending protocol\n- `GeneralAdapter1` (`EthereumGeneralAdapter1` for Ethereum mainnet)— required for the frontend and SDK to handle permissioned tokens\n\nAll contracts deployments addresses are available in [the addresses page](/get-started/resources/addresses/).\n\nWithout the general adapter whitelisted, the Morpho app cannot simulate or execute user transactions with permissioned tokens.\n\nWhen listing a permissioned token, curators must review and confirm with the asset issuer that the contracts whitelisting is properly implemented."
  },
  "/curate/tutorials-market-v1/setting-rate/": {
    "title": "Set the Rate at Target",
    "url": "https://docs.morpho.org/curate/tutorials-market-v1/setting-rate/",
    "section": "Curate",
    "content": "This tutorial guides you through the process of setting and managing interest rates for your new markets:\n\n  \n\n## Understanding Rate Mechanics\n\nThe Interest Rate Model (IRM) follows specific rules that market creators should understand:\n\n| Category                  | Condition              | Rate Change               |\n| ------------------------- | ---------------------- | ------------------------- |\n| **Instantaneous Changes** | 90% → 0% Utilization   | Rate ÷4                   |\n|                           | 0% → 90% Utilization   | Rate ×4                   |\n|                           | 90% → 100% Utilization | Rate ×4                   |\n|                           | 100% → 90% Utilization | Rate ÷4                   |\n| **Time-Based Changes**    | At 0% Utilization      | Rate halves every 5 days  |\n|                           | At 100% Utilization    | Rate doubles every 5 days |\n|                           | At 90% Utilization     | Rate remains constant     |\n| **Market Creation**       | Initial State          | 4% APR at 90% utilization |\n|                           | Without Activity       | Starts at 0% utilization  |\n\n## Best Practices for Rate Setting\n\n### Initial Market Setup\n\n- The market starts with 0% utilization despite having a target rate of 4% APR at 90% utilization\n- Without activity, rates will continuously decrease (halving every 5 days)\n- To prevent this, seed the market immediately after creation\n\n### Targeting Specific Rates\n\n- To increase rates: Set utilization above 90%\n- To decrease rates: Set utilization below 90%\n- Avoid 100% utilization as rates will double every 5 days\n- Plan rate adjustments in advance due to the time-based mechanics\n\n### Avoiding Liquidity Traps\n\n- Low rates can create liquidity traps where:\n  - Lenders are discouraged from depositing\n  - Borrowers can't access liquidity due to insufficient deposits\n- Maintain healthy rates from market launch to ensure proper market function\n\nConsider using the PublicAllocator (PA) to manage idle liquidity while maintaining desired utilization rates. This allows for rate management while keeping funds available for borrowing across markets.\n\nFor more details:\n\n- IRM Documentation: [Concept IRM Doc](/learn/concepts/irm/)\n- Implementation: [Morpho V1 IRM on GitHub](https://github.com/morpho-org/morpho-blue-irm)"
  },
  "/curate/tutorials-v1/bad-debt/": {
    "title": "Managing Bad Debt: How-to Guide",
    "url": "https://docs.morpho.org/curate/tutorials-v1/bad-debt/",
    "section": "Curate",
    "content": "## Overview\nThis guide is designed for Morpho Vaults curators and aims to provide a methodical approach to identifying, processing, and resolving bad debt within the Morpho ecosystem.\nIt clarifies the concepts of unrealized and realized bad debt and outlines the technical and operational steps required for effective remediation.\n\n### Bad Debt Overview\n\nAs a reminder, the health of a borrower's position can be divided into three main categories, with LTV being Loan-To-Value, LLTV being the Liquidation Loan-To-Value (one of the market parameters) and LIF the Liquidation Incentive Factor:\n1. If LTV < LLTV, the position is healthy, and the borrower cannot be liquidated.\n2. If LLTV < LTV ≤ 1/LIF, a liquidator can repay part or all of the user's debt and seize part of its collateral.\n3. If 1/LIF < LTV, a liquidator can seize all the collateral by repaying only a share of the debt. There is no incentive for the liquidator or borrower to repay the remaining debt. The latter is commonly referred to as bad debt.\n\nUnder situation 3, bad debt can be categorized into two types: \n1. **Unrealized** when the liquidation has not occurred yet,\n2. **Realized** when the liquidation has occurred, and the entire collateral position is seized.\n\n## How Vaults are handling bad debt\n\nIn practice, the remaining debt of the liquidated user, at the market level, affects all existing suppliers of the market. Vault V1.0 and V1.1 are part of them, and handle bad debt in different ways.\n\n### Vault V1.0\n\nMorpho Vault V1.0 automatically realizes the loss on all existing depositors at the moment of the bad-debt liquidation event. The share price of the vault will instantaneously decrease.\n\nVaults are from a Morpho Market point of view simple users. Their supply shares value post liquidation incurring bad debt in a market they allocated liquidity are worth a bit less than before the liquidation. The entire vault and depositors respectively are impacted proportionally to the proportion of the share the vault has in the market.\n\n### Vault V1.1\n\nMorpho Vault V1.1 do not automatically realize the loss on all existing depositors at the moment of the bad-debt liquidation event. The share price will not decrease. The last depositors will face the bad debt unless action is taken.\n\n## How to cover the bad debt\n\nAnyone (e.g., a curator or a lender) can decide to cover those bad debt events that have been realized, and this is feasible in different ways depending on the version of the vault.\n\nOne can call the action to put back some liquidity \"Asset injection\", which involves supplying methodically sufficient loan tokens to cover the loss in order to:\n1. for vault V1.0: restore the vault's share price\n2. for vault V1.1: allow any lenders to never get stuck if there was some liquidity shortage.\n\n### Vault V1.0\n\n#### How to compute the loan token asset lost?\n\nThe `amountLost` is retrievable easily thanks to the liquidation event emitted. \n\nAfter liquidation with bad debt realization, the entire Morpho Market suffered a reduction on `totalSupplyAsset` up to the `badDebtAssets` (in loan token units), retrievable at the `liquidate` event level.\n\n```solidity\nemit EventsLib.Liquidate(\n    id, msg.sender, borrower, repaidAssets, repaidShares, seizedAssets, badDebtAssets, badDebtShares\n);\n```        \n\nThen, one needs to compute in this Morpho Market what was the proportion % (called `proportionPercentage`) of the vault position as the vault is probably not the only supplier into the market. \n\n```math\namountLost = proportionPercentage \\times badDebtAssets\n```\n\n#### Which action to execute?\n\nThe following 3 solutions could be performed:\n\n1. For vault V1.0, one could think about depositing the loan token asset lost (called `AMOUNT_LOST`) by the vault straight into the market, by calling the `supply()` function, and deposit on behalf of the vault address:\n\n        ```solidity\n        // On the Morpho contract\n        function supply(\n            MarketParams,\n            assets=AMOUNT_LOST,\n            shares=0,\n            onBehalf=0x_VAULT_ADDRESS,\n            0x,\n        )\n        ```\n\n        However, if any new depositor comes between the time the vault suffered from bad debt, and the new loan token provider triggers the supply, this would indeed favor the new user(s) while they should not have been benefiting from this.\n\n2. Deposit on behalf of each user, coming with more gas consumption.\n\n3. Create an airdrop solution favoring the impacted users.\n\nDo not deposit on behalf of 0x000...001 on Vault V1.0 where the bad debt has been realized, as those funds will be lost. That solution will only work for Vault V1.1.\n\n### Vault V1.1\n\nFor vault V1.1, and as stated in the contract, as the bad debt is not realized at the vault level, anyone can compute the amount lost by using the value of lostAssets. \n\n#### How to compute the loan token asset lost?\n\nThe added loss is `lostAssets_after` - `lostAssets_before`. These values are taken by retrieving the onchain `lostAssets` value before and after the liquidation event.\n\n#### Which action to execute?\n\nIt is suggested to supply on behalf of address(1) on the vault. The loan token provider will thus lose the asset, but this will cover the bad debt event and no lenders will ultimately be stuck if they were to withdraw their funds.\n\n```solidity\n// Call the deposit function on the Vault contract like this:\nfunction deposit(assets,0x000..0001)\n```    \n\n## Alternative Approach: Third-Party Insurance Solutions\n\nAnother alternative for users is to subscribe to third-party insurance solutions (e.g., Nexus Mutual) that could provide coverage against bad debt events. This approach offers a proactive risk curation strategy rather than reactive remediation after bad debt has occurred.\n\nThis insurance-based approach could potentially replace or complement the manual bad debt coverage methods described above, providing automated protection for vault participants."
  },
  "/curate/tutorials-v1/checklist/": {
    "title": "Checklist to Validate Vault V1 Configuration",
    "url": "https://docs.morpho.org/curate/tutorials-v1/checklist/",
    "section": "Curate",
    "content": "This tutorial provides two comprehensive checklists for validating your vault configuration and integrating them before going live.\n\n## Vault and Market creation checklist\n\nBelow is a Vault and market checklist for you to review after following the previous process.\n\n- [ ] Create a new market.\n- [ ] Verify the market Oracles.\n- [ ] Set the correct rate at target for the new market.\n- [ ] Set the dead deposit for the new market ([tutorial](/curate/tutorials-market-v1/dead-deposit/)).\n- [ ] Create a Morpho Vault V1.1.\n- [ ] Set the dead deposit for the new vault ([tutorial](/curate/tutorials-v1/dead-deposit/)).\n- [ ] Set the correct caps for all listed markets.\n- [ ] Check that all listed markets have a dead deposit.\n- [ ] Set the correct roles and permissions.\n- [ ] Configure the correct timelock after vault creation.\n- [ ] (optional) Submit rewards program and rewards for the new asset.\n- [ ] List and price your vault on Coingecko.\n- [ ] List your tokens on Etherscan.\n- [ ] Price your tokens on [DeFiLlama](https://docs.llama.fi/coin-prices-api).\n- [ ] (optional) Set and configure the Public Allocator.\n- [ ] Configure your reallocation bot for rate targeting and liquidations.\n- [ ] Submit a Forum post.\n\n## Integration checklist\n\nMorpho has multiple integrations will help distribute the vaults and markets you created\n\n- [ ] Integrate your Vaults in Superform, IPOR Fusion, lazy [Summer.fi](http://Summer.fi) , Yearn, Beefy\n- [ ] Integrate your Markets in Defisaver, Contango, Summer.fi"
  },
  "/curate/tutorials-v1/dead-deposit/": {
    "title": "Vault Dead deposit",
    "url": "https://docs.morpho.org/curate/tutorials-v1/dead-deposit/",
    "section": "Curate",
    "content": "This tutorial explains how to set up a dead deposit for a Vault V1.\n\nA dead deposit is a security measure against ERC-4626 inflation attacks ([read more](/build/earn/concepts/vault-mechanics#inflation-attack-protection)).\n\nSetting up a dead deposit involves minting 1e9 shares (or 1e12 shares for assets with less than 9 decimals) from the target vault, on behalf of address `0x000000000000000000000000000000000000dEaD`, through a simple process on a block explorer like Etherscan:\n\n1. Access the vault contract on the explorer using the vault's address.\n\n2. Approve the Morpho Vault V1 contract to spend the vault's deposit token on your behalf. You can do this on the deposit token's contract. Typically a value of $1.00 should suffice.\n\n  \n\n3. Use the vault contract's `mint` function for 1e9 shares (or 1e12 shares for assets with less than 9 decimals), with address `0x000000000000000000000000000000000000dEaD` as the receiver.\n\n  \n\nOnce the transaction is confirmed, the vault will be secured with a dead deposit."
  },
  "/curate/tutorials-v1/emergency/": {
    "title": "Emergency Procedures",
    "url": "https://docs.morpho.org/curate/tutorials-v1/emergency/",
    "section": "Curate",
    "content": "This document outlines procedures for handling emergency situations related to Morpho Vaults, from dealing with unsafe markets to responding to a compromised role. These actions should be executed with extreme care, as they can have significant consequences for the vault and its depositors.\n\nPlease read the [README](https://github.com/morpho-org/metamorpho/blob/main/README.md) section from the Morpho Vaults repository.\n\n## Unsafe Market: Soft Deprecation\n\nThis procedure is used when a market is deemed too risky for continued new allocations, but is still functioning correctly, allowing for a graceful exit.\n\n### The Goal\n\nSafely withdraw all vault funds from the market without incurring losses, and prevent any new capital from being allocated to it.\n\n### Procedure via Direct Contract Calls\n\n1.  **Revoke Pending Caps**: If there is a pending cap increase for the market, the `Guardian`, `Curator`, or `Owner` should call `revokePendingCap` to prevent it from being accepted.\n2.  **Set Cap to Zero**: The `Curator` or `Owner` must immediately call `submitCap` with a `newSupplyCap` of `0`. This is an instant action and prevents new funds from flowing into the market.\n    *   **Pro Tip**: To avoid front-running issues, it's best to batch the `revokePendingCap` and `submitCap` calls in a single transaction using a `multicall` function for instance.\n3.  **Reallocate Liquidity**: The `Allocator` should call `reallocate` to withdraw all available liquidity from the market. If the market is illiquid, this may need to be done in stages as liquidity becomes available.\n4.  **Update Withdraw Queue**: The `Allocator` should move the market to the beginning of the `withdrawQueue` to ensure any newly available liquidity is captured first.\n5.  **Complete Delisting**: Once all funds have been withdrawn, the `Allocator` can remove the market entirely from the `withdrawQueue` by calling `updateWithdrawQueue`.\n\n### Procedure via the Curator App\n\nThe Curator App streamlines this process with a dedicated \"Unsafe Market\" emergency flow.\n\n  \n\nExecuting this flow in a single transaction will:\n1.  Revoke any pending cap changes for the target market.\n2.  Set the market's supply cap to `0`.\n3.  Reallocate all *currently available* liquidity to the vault's designated Idle Market.\n4.  Move the market to the first position in the `withdrawQueue`.\n\nThis flow performs a \"soft deprecation.\" If the market is illiquid, the vault will retain its position, and the Allocator must monitor it to withdraw the remaining funds as they become available.\n\n## Market Reverts: Forced Removal\n\nThis procedure is for critical situations where a market is malfunctioning (e.g., its functions consistently revert), making it impossible to withdraw funds normally. **This action involves accepting the loss of any capital stuck in the market.**\n\n### The Goal\n\nRemove a broken market from the vault's accounting to restore normal vault operations, even if it means losing the funds allocated to it.\n\n### Procedure via Direct Contract Calls\n\n1.  **Set Cap to Zero**: As with a soft deprecation, the `Curator` must first set the market's cap to `0`.\n2.  **Submit for Removal**: The `Curator` or `Owner` must call `submitMarketRemoval`. This action is **timelocked**.\n3.  **Wait for Timelock**: The mandatory waiting period must elapse.\n4.  **Update Withdraw Queue**: After the timelock, the `Allocator` can call `updateWithdrawQueue` to permanently remove the market from the vault's configuration.\n\n**Warning: Potential Loss of Funds**\nExecuting a forced removal will cause the vault to abandon any assets still allocated to the market. This procedure should **only** be used when funds are considered otherwise irrecoverable.\n\n### Procedure via the Curator App\n\nThe \"Market Reverts\" flow in the Curator App is designed for this scenario.\n\n  \n\nIn a single transaction, this flow will:\n1.  Revoke any pending cap changes for the market.\n2.  Set the market's supply cap to `0`.\n3.  Call `submitMarketRemoval` to begin the timelocked process of forced deprecation.\n\nAfter the timelock expires, the `Allocator` must still manually call `updateWithdrawQueue` to complete the removal.\n\n### Impact on Users\n\nOnce the market has been forced removed from the withdraw queue, there will be different consequences based on whether the vault is a Vault V1.0 or V1.1:\n\n#### Vault V1.0\n\nThe lost funds will be socialized among all depositors immediately. Some options for this loss to be covered are listed in the [Curate: Manage Bad Debt section](/curate/tutorials-v1/bad-debt#which-action-to-execute) of the docs.\n\nDo not deposit on behalf of 0x000...001 on Vault V1.0 where the bad debt has been realized, as those funds will be lost. That solution will only work for Vault V1.1.\n\n**Re-adding the market:** If the market starts working again, it can be re-added. The share price will increase back as the assets become accessible again, effectively reversing the loss socialization.\n\n#### Vault V1.1\n\nThe loss of funds is not realized by depositors. However —if the funds are not recovered—, the last depositors to withdraw will suffer the entire loss and won't be able to withdraw their funds.\n\n**Do not re-add a force-removed market on Vault V1.1.** Re-adding would cause the share price to increase (as the assets become visible again), but the internal `lostAssets` accounting remains unchanged. This creates bad debt that cannot be resolved.\n\nOn Vault V1.1, the loss due to a forced market removal can be prevented if the lost assets are covered by making a deposit to the vault for the amount of the lost assets, on behalf of address `0x000...001`:\n\n```solidity\nvault.deposit(amount, 0x000...001);\n```\n\nMake sure to check that the vault is V1.1 before depositing on behalf of `0x0000000000000000000000000000000000000001`, otherwise this deposit will be lost.\n\n## Role Compromise Scenarios\n\n### Curator Takeover\n\nIf a `Curator` begins acting maliciously (e.g., submitting caps for unsafe markets), the `Owner` must intervene.\n\n1.  **Set a New Curator**: The `Owner` should immediately call `setCurator` to transfer control to a new, trusted address.\n2.  **Revoke Pending Actions**: The new `Curator`, `Owner`, or `Guardian` must call `revokePendingCap` on any malicious proposals submitted by the old curator.\n3.  **Remediate Accepted Actions**: If a malicious cap was accepted before it could be revoked, the new `Curator` must follow the \"Unsafe Market\" procedure to safely exit the position.\n\n### Allocator Takeover\n\nIf an `Allocator` acts against the vault's strategy (e.g., by setting improper queues or reallocating funds incoherently), the `Owner` should:\n\n1.  **Revoke Allocator Privileges**: Call `setIsAllocator` with the malicious address and `false`.\n2.  **Correct Queues**: The `Owner` or a trusted `Allocator` must call `setSupplyQueue` and `updateWithdrawQueue` to restore the correct order.\n3.  **Reallocate Funds**: Call `reallocate` to move funds back into alignment with the vault's intended strategy."
  },
  "/curate/tutorials-v1/manage-allocations/": {
    "title": "Curate Allocations (Vaults V1)",
    "url": "https://docs.morpho.org/curate/tutorials-v1/manage-allocations/",
    "section": "Curate",
    "content": "Managing allocations is the core responsibility of the `Allocator` role. It involves strategically moving capital between the vault's enabled markets to optimize for yield, maintain liquidity, and adhere to the risk parameters set by the `Curator`.\n\nThis guide covers how to manage allocations using two methods:\n1.  **The Curator App**: An intuitive interface for rebalancing the vault's portfolio.\n2.  **Direct Contract Calls**: For advanced users and scripted interactions with the powerful `reallocate` function.\n\n## Method 1: Managing Allocations with the Curator App\n\nThe Curator App provides a visual and interactive way to rebalance your vault's assets. Navigate to the **Allocation** tab to get started.\n\n### Viewing and Planning Allocations\n\nThe main table on this page displays the vault's current, live allocation across all its enabled markets, including the Idle Market. You can customize the table with additional columns to see real-time data like supply caps, utilization, and interest rates.\n\n  \n\n### Performing a Reallocation\n\n#### Enter Edit Mode\nClick the **Reallocate** button to make the \"New Allocation\" column editable. This also reveals several helpful tools at the top right of the table:\n- **Reset**: Reverts your pending changes back to the vault's live state.\n- **Simulate**: Analyzes the impact of your proposed reallocation on the vault's overall APY.\n- **Undo/Redo**: Steps back and forth through your recent changes.\n\n  \n\n#### Define the New Allocation\nYou can now input your desired allocation for each market. Use the toggle at the top of the column to switch between entering values as percentages (%) or as absolute asset amounts. As you edit, the \"Delta\" column will show you how much capital will be moved for each market.\n\n  \n\n#### Save and Execute\nOnce you are satisfied with your new allocation strategy, click the **Save** button to initiate the transaction. The app will generate the necessary `reallocate` call for you to confirm in your wallet.\n\nIf your new allocation doesn't account for 100% of the vault's assets, a popup will prompt you to allocate the small remaining amount to a market of your choice (typically the Idle Market) to ensure no funds are left unallocated.\n\n## Method 2: Reallocating via Direct Contract Calls\n\nFor advanced control and scripting, you can call the `reallocate` function directly on the vault contract. This function is extremely powerful, as it can simultaneously withdraw from some markets and supply to others in a single, gas-efficient transaction.\n\n### Understanding the `reallocate` Function\n\nThe function signature is:\n`reallocate(MarketAllocation[] calldata allocations)`\n\nIt takes a single argument: an array of `MarketAllocation` structs. Each struct tells the vault how much of the underlying `asset` it should aim to have in a specific market **after** the reallocation is complete.\n\n```solidity\nstruct MarketAllocation {\n    MarketParams marketParams; // The full parameters of the target market\n    uint256 assets;            // The desired final amount of assets in this market\n}\n```\n\n### How `reallocate` Works\n\n1.  **Calculates Net Flow**: The function first determines the total amount of assets that need to be withdrawn from markets where the target allocation is *less* than the current allocation.\n2.  **Withdraws First**: It performs all necessary withdrawals from the designated markets.\n3.  **Supplies Second**: It then uses the pool of withdrawn assets to supply to markets where the target allocation is *greater* than the current allocation.\n4.  **Balance Check**: The transaction will revert if the total amount supplied does not exactly match the total amount withdrawn.\n\n### Practical Example: Shifting Funds\n\nImagine a vault with 100 WETH, currently allocated as:\n-   Market A: 70 WETH\n-   Idle Market: 30 WETH\n\nThe Allocator wants to move 20 WETH from Market A to a new, higher-yielding Market B.\n\n**The `allocations` array would look like this:**\n\n```json\n[\n  {\n    \"marketParams\": { ...Market A params... },\n    \"assets\": \"50000000000000000000\" // Target: 50 WETH\n  },\n  {\n    \"marketParams\": { ...Market B params... },\n    \"assets\": \"20000000000000000000\" // Target: 20 WETH\n  }\n]\n```\n\n**What happens when this is executed?**\n1.  The vault sees it needs to withdraw `70 - 50 = 20 WETH` from Market A.\n2.  It withdraws 20 WETH from Market A.\n3.  It sees it needs to supply `20 - 0 = 20 WETH` to Market B.\n4.  It supplies the 20 WETH to Market B.\n5.  The total withdrawn (20) equals the total supplied (20), so the transaction succeeds. The Idle Market was not included, so its balance of 30 WETH remains untouched.\n\n### Best Practice: The \"Max\" Catcher\n\nTo ensure that the total supplied always matches the total withdrawn and to avoid failed transactions due to rounding or accrued interest, it is a **critical best practice** to make the last item in your `allocations` array a \"catcher.\"\n\nThis is typically your Idle Market, with its `assets` parameter set to the maximum possible `uint256` value (`115792089237316195423570985008687907853269984665640564039457584007913129639935`).\n\n**Example: Safely shifting 20 WETH from Market A to Market B**\n\n```json\n[\n  {\n    \"marketParams\": { ...Market A params... },\n    \"assets\": \"50000000000000000000\" // Target: 50 WETH\n  },\n  {\n    \"marketParams\": { ...Market B params... },\n    \"assets\": \"20000000000000000000\" // Target: 20 WETH\n  },\n  {\n    \"marketParams\": { ...Idle Market params... },\n    \"assets\": \"115792089237316195423570985008687907853269984665640564039457584007913129639935\" // MAX_UINT256\n  }\n]\n```\n\nIn this case, the Idle Market will automatically absorb any remaining assets from the withdrawn pool, guaranteeing the transaction succeeds. This is especially useful for fully delisting a market by setting its target `assets` to `0`."
  },
  "/curate/tutorials-v1/manage-markets/": {
    "title": "Curate Markets & Liquidity (Vaults V1)",
    "url": "https://docs.morpho.org/curate/tutorials-v1/manage-markets/",
    "section": "Curate",
    "content": "As a curator for a Morpho Vault V1, your primary responsibilities are to manage which markets the vault can supply to, set risk limits via supply caps, and organize the flow of capital using supply and withdraw queues.\n\nThis guide provides a comprehensive overview of how to perform these actions using two methods:\n1.  **The Curator App**: A user-friendly interface for most management tasks.\n2.  **Direct Contract Calls**: For advanced users or scripted interactions via Etherscan.\n\n## Curating Supply Caps\n\nSupply caps are the primary tool for controlling a vault's risk exposure to any single Morpho Market.\n\n### Using the Curator App\n\nNavigate to the **Caps** tab in the Curator App to view and manage all active and pending market caps.\n\n  \n\n#### Modifying or Adding a New Cap\n\n##### Click \"+ New\" Button\nClick the \"+ New\" button in the top right to open the market selection modal.\n\n  \n\n##### Select a Market and Set the Cap\nChoose the market you want to enable or modify. Set the desired **Supply Cap** value and click `Submit New Cap`. Setting a non-zero cap for the first time will enable the market in your vault.\n\n  \n\n##### Wait for the Timelock and Accept\nIncreasing a cap is a timelocked action. After submitting, the proposal will appear in the **Pending** tab. Once the timelock expires (shown under \"Estimated Valid At\"), you must click **Accept** to finalize the change. Decreasing a cap is instant.\n\n### Using Direct Contract Calls\n\n#### 1. Submit the Cap (`submitCap`)\nExecute `submitCap` with the market's parameters and the desired cap amount. The `newSupplyCap` should be in the native decimals of the loan token.\n\n  \n  <figcaption>Submitting a cap via Etherscan.</figcaption>\n\n#### 2. Accept the Cap (`acceptCap`)\nAfter the timelock period expires, anyone can call `acceptCap` with the same market parameters to finalize the change.\n\n**How to get a market's ID?**\nYou can find a market's ID from:\n- The `CreateMarket` event log at market creation.\n- The main `app.morpho.org` interface.\n- Using a script, like [this one](https://gist.github.com/tomrpl/3cfd34e04a01f9cbae2b16887f8026cf).\n\n  <figcaption>Accepting a cap via Etherscan.</figcaption>\n\n## Managing Queues\n\nThe Supply and Withdraw Queues dictate the logic for capital allocation. The `Allocator` role is responsible for their management.\n\n### Using the Curator App\n\nNavigate to the **Queues** section to view and manage your vault's queues.\n\n  \n\n#### Reordering a Queue\n\n1.  Click the **Edit** button for the queue you wish to modify.\n2.  **Drag and drop** the market cards into your desired order.\n3.  Click **Save** and confirm the transaction.\n\n  \n\n### Using Direct Contract Calls\n\n#### Setting the Supply Queue (`setSupplyQueue`)\n\nTo set the supply queue, call `setSupplyQueue` with an array of market `Id`s in the desired order.\n\n```bash\n# Example input for setSupplyQueue\n[0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41, 0x_MARKET_ID_2, ...]\n```\n\n#### Updating the Withdraw Queue (`updateWithdrawQueue`)\n\nTo reorder the withdraw queue, call `updateWithdrawQueue` with an array of numbers representing the **original indexes** of the markets in their **new desired order**.\n\nFor example, if the original queue was `[MarketA, MarketB, MarketC]` (indexes `[0, 1, 2]`) and you want the new order to be `[MarketC, MarketA, MarketB]`, you would call `updateWithdrawQueue([2, 0, 1])`.\n\n**Idle Market Best Practices**\n-   **Idle Market** should be first in the `supplyQueue` and in the `withdrawQueue`.\n\n## Delisting a Market\n\nDelisting a market is a multi-step process to ensure funds are safely migrated.\n\n### Standard Delisting Process\n\nThis process safely removes a market without losing funds.\n\n#### 1. Set Market Cap to Zero\nInstantly set the market's supply cap to `0` using `submitCap`. This prevents new allocations to the market.\n\n#### 2. Reallocate All Liquidity\nUse `reallocate` to move all of the vault's assets out of the target market and into other active markets. Ensure the market to be delisted is **not** included in the `reallocate` call.\n\n#### 3. Update the Withdraw Queue\nOnce the market's cap and the vault's allocation are both zero, call `updateWithdrawQueue` with a new index array that omits the delisted market.\n\nBefore removing a market from the withdraw queue, ensure:\n1.  The market cap is `0`.\n2.  There are no pending cap changes for that market.\n3.  The vault's allocation in that market is `0`.\nFailure to meet these conditions will cause the transaction to revert.\n\n### Dust Shares Removal\n\nThere is an edge case to consider when removing a market. A small amount of dust supply shares could accumulate through usual allocation processes. Reallocating out of these markets via reallocate is not possible because the reallocation is denominated in assets, while the removal of a market from the withdraw queue requires supply shares to be zero.\nWhen you have some dust shares on a market that you are trying to remove, **you are forced to supply one unit of an asset on behalf of your vault** to then be able to reallocate and withdraw. For example for USDC it would be 0.000001$ (6 decimals).\n\n**Warning**: You must not force remove a market if this edge case occurs:\n    - in V1.0 force-removing it makes share price goes down instantly and will go up instantly if you re-enable the market.\n    - in V1.1, force-removing it creates a bad debt in the vault instantly and will not go away if you re-enable it (instead, the share price will go up, but the same hole will be present).\n\n#### Remove dust shares via the Curator App V1 (Ethereum mainnet and Base only)\n\n#### 1. Head to the Emergency page\nClick on the \"Dust Shares Removal\" `start` button.\n\n  \n\n#### 2. Choose the targeted market\n\n  \n\n#### 3. Follow the app\nThe flow will require to:\n- Approve the Bundler V2\n\nThe Curator app V1 uses the Bundler V2 for this flow - never give approval to the Bundler3 manually.  \n\n- Donate 1 unit of the asset on behalf of the vault\n- Remove dust by reallocating\n\n#### Remove dust shares using direct contract calls\nFor other chains than Ethereum and Base, you will have to follow the same steps as described above but interactign at contract directly (via script or explorer).\n\n#### 1. Approve the [Morpho contract](/get-started/resources/addresses#morpho-v1-contracts) and supply 1 unit of asset in the market on behalf of the vault.\nSee contract spec of the `supply` function [here](/get-started/resources/contracts/morpho/#supply).\n  \n#### 2. You can then `reallocate` liquidity out of the market\nSee how to interact at contract level [here](/curate/tutorials-v1/manage-allocations/#method-2-reallocating-via-direct-contract-calls)\n\n### Emergency Market Removal\n\nThis process should only be used if a market is malfunctioning and funds cannot be safely reallocated.\n\n#### 1. Submit Market for Removal\nAs the `Curator`, call `submitMarketRemoval` with the parameters of the market to be force-removed.\n\n#### 2. Wait for the Timelock\nA timelock period begins, allowing users to react.\n\n#### 3. Update the Withdraw Queue\nAfter the timelock expires, the `Allocator` can call `updateWithdrawQueue` to remove the market, even if it still contains vault assets.\n\n**Risk of Fund Loss**\nUsing `submitMarketRemoval` may result in the permanent loss of any assets remaining in the malfunctioning market. This is an emergency action and should be used with extreme caution.\n\n### Delisting Process Summary\n\nFor safe market delisting:\n\n1. Remove the market from the supply queue\n2. Reduce the market cap to zero\n3. Reallocate all funds from the market to other markets\n4. Remove the market from the withdraw queue\n\nFor emergency situations:\n\n1. Submit market removal\n2. Wait for timelock to elapse\n3. Update the withdraw queue\n\nAlways prioritize the safety of depositor funds and provide clear communication throughout the delisting process."
  },
  "/curate/tutorials-v1/public-allocator/": {
    "title": "Set Up Public Allocator",
    "url": "https://docs.morpho.org/curate/tutorials-v1/public-allocator/",
    "section": "Curate",
    "content": "## Overview\n\nAs the vault curator of a Morpho Vault, you can designate the `PublicAllocator` address as an allocator of the vault.\nThis will allow borrowers or Morpho's interface to trigger reallocations, amplifying the available liquidity for end users while limiting the flow of tokens that can be supplied or withdrawn from a market listed in the vault.\n\nThis provides power for the curator to:\n\n- Enable interface/advanced borrowers to trigger reallocations\n- Amplifies available liquidity\n- Controls token flow limits\n\n## Prerequisites\n\n- You must be a curator of a Morpho Vault\n- Access to the Morpho Vault contract\n\n## Setup Steps\n\n### Enable the Public Allocator\n\nAs a `curator` of your own vault, provide the [`allocator`](/curate/concepts/roles/) role to the `PublicAllocator` [contract address](/get-started/resources/addresses/) as described in [this section](/curate/tutorials-v2/roles/), via the `setIsAllocator` function (0xNewAllocator, true).\n\n  \n  <figcaption>\n    Providing the `allocator` role to the `PublicAllocator` contract on the\n    Morpho Vault contract\n  </figcaption>\n\nNow you can jump on the [`PublicAllocator`](/get-started/resources/addresses/) contract to set it up.\n\n### Configure Basic Settings\n\n#### A. Set Admin (Optional)\n\nBy default, only the owner of the vault can configure the `PublicAllocator` for a given vault. However, the owner can appoint an additional admin by triggering the `setAdmin` function.\n\n#### B. Set Fee (Optional)\n\nThe `PublicAllocator` can set a fee to charge on every reallocation. The fee is paid in ETH and can be changed at any time by the owner of the vault or the admin by triggering the `setFee` function.\n\nThis fee prevents griefing attacks and helps the vault curators to cover the gas costs reallocations in the case the reallocation through the `PublicAllocator` has created an imbalance.\n\n### Configure Flow Caps\n\nFlow caps determine the maximum amount of tokens that can be supplied or withdrawn from a market listed in the vault. The flow caps can be set by the owner of the vault or the admin for a specific market by triggering the `setFlowCap` function.\n\nA flow cap is composed of the `maxIn` and `maxOut` in this order. The `maxIn` is the maximum amount of tokens that can be supplied to a market and the `maxOut` is the maximum amount of tokens that can be withdrawn from a market.\n\nFor example, if amount `x` is withdrawn from a market during reallocation, the market's `maxIn` increases by `x`, while `maxOut` decreases by `x`. Conversely, if `x` is supplied to the market, `maxIn` decreases by `x` and `maxOut` increases by `x`.\n\nThis mechanism helps maintain balance and limits excessive token flows in and out of the market.\n\n## Example Configuration\n\nAssume that the vault has the following markets:\n\n- 0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41\n- 0x58e212060645d18eab6d9b2af3d56fbc906a92ff5667385f616f662c70372284\n- 0x3c83f77bde9541f8d3d82533b19bbc1f97eb2f1098bb991728acbfbede09cc5d\n\n#### Consider the following input for the `setFlowCap` function as an example:\n\n```json\n[\n  {\n    \"id\": \"0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41\", // wstETH/WETH (94.5%)\n    \"caps\": {\n      \"maxIn\": \"199000000000000000000\", // 199 WETH\n      \"maxOut\": \"199000000000000000000\" // 199 WETH\n    }\n  },\n  {\n    \"id\": \"0x58e212060645d18eab6d9b2af3d56fbc906a92ff5667385f616f662c70372284\", // wstETH/WETH (96.5%)\n    \"caps\": {\n      \"maxIn\": \"0\", // 0 WETH\n      \"maxOut\": \"459000000000000000000\" // 459 WETH\n    }\n  },\n  {\n    \"id\": \"0x3c83f77bde9541f8d3d82533b19bbc1f97eb2f1098bb991728acbfbede09cc5d\", // rETH/WETH (94.5%)\n    \"caps\": {\n      \"maxIn\": \"500000000000000000000\", // 500 WETH\n      \"maxOut\": \"150000000000000000000\" // 15 WETH\n    }\n  }\n]\n```\n\n#### Corresponding [Etherscan](https://etherscan.io/) input below:\n\n```\n[[\"0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41\", [\"199000000000000000000\", \"199000000000000000000\"]], [\"0x58e212060645d18eab6d9b2af3d56fbc906a92ff5667385f616f662c70372284\", [\"0\", \"459000000000000000000\"]], [\"0x3c83f77bde9541f8d3d82533b19bbc1f97eb2f1098bb991728acbfbede09cc5d\", [\"500000000000000000000\", \"150000000000000000000\"]]]\n```\n\n## Security Considerations\n\n- Flow cap limits protect against excessive token movements\n- Fees prevent griefing attacks\n- Admin controls provide flexibility while maintaining security\n\n## Next Steps\n\n- Monitor your flow caps\n- Adjust settings as needed\n- Consider market conditions when setting limits"
  },
  "/curate/tutorials-v1/roles/": {
    "title": "Manage Vault Roles",
    "url": "https://docs.morpho.org/curate/tutorials-v1/roles/",
    "section": "Curate",
    "content": "This tutorial guides you through the process of setting up and managing roles for your Morpho vault. Proper role assignment is crucial for vault operations, governance, and security.\n\nEach role has specific permissions and responsibilities. The Owner has the highest level of control and can assign or revoke other roles. Refer to the [roles concept section](/curate/concepts/roles/) for detailed explanations of each role's capabilities.\n\nBe careful when assigning roles, especially the Guardian role, as they have significant control over vault operations. Always verify addresses before executing transactions.\n\n## Using the Curator App\n\nTo manage your vault's roles, navigate using the left-hand side menu to the Roles section.\n\n  \n\n### Owner Transfer\n\nThe vault owner can transfer ownership to a new address. Click the Transfer button next to the current owner address. The new owner must accept the transfer to complete the process.\n\nOwner transfer is permanent once accepted. Ensure the new owner address is correct and trusted.\n\n### Setting Up Core Roles\n\nThe following roles can be configured through the interface or directly via contract calls.\n\n## Using Contract Calls\n\n### Set Curator\n\nThe curator manages market configurations and can submit caps and market removals.\n\nExecute `setCurator(0xNewCurator)`\n\n- **Parameters:** \n  - `newCurator`: Address of the new curator\n- **Permissions:** Only owner can execute\n- **Effect:** Immediate - no timelock required\n\n### Add Allocators\n\nAllocators can reallocate liquidity between markets and manage supply/withdraw queues.\n\nExecute `setIsAllocator(0xNewAllocator, true)`\n\n- **Parameters:**\n  - `newAllocator`: Address to grant allocator permissions\n  - `isAllocator`: `true` to grant, `false` to revoke\n- **Permissions:** Only owner can execute\n- **Effect:** Immediate - can have multiple allocators\n\n### Set Guardian\n\nThe guardian can revoke pending operations and provides additional security oversight.\n\nExecute `submitGuardian(0xNewGuardian)`\n\n- **Parameters:**\n  - `newGuardian`: Address of the new guardian\n- **Permissions:** Only owner can execute\n- **Timelock:** If no guardian exists, sets immediately. Otherwise, requires timelock period\n- **Acceptance:** New guardian must call `acceptGuardian()` after timelock expires\n\n### Configure Fee Structure\n\nPerformance fees are collected when vault performance exceeds benchmarks.\n\n**Step 1: Set Fee Recipient**\nExecute `setFeeRecipient(0xFeeRecipient)`\n\n**Step 2: Set Fee Rate**\nExecute `setFee(10000000000000000)` // 1% fee (18 decimal precision)\n\n- **Parameters:**\n  - `feeRecipient`: Address to receive performance fees\n  - `fee`: Fee rate in 18-decimal format (1% = 10^16)\n- **Limits:** Maximum fee is 50% (0.5e18)\n- **Requirements:** Fee recipient must be set before setting non-zero fee\n\n### Set Skim Recipient\n\nThe skim recipient receives rewards and excess tokens allocated to the vault.\n\nExecute `setSkimRecipient(0xSkimRecipient)`\n\n- **Parameters:**\n  - `skimRecipient`: Address to receive skimmed tokens\n- **Purpose:** Collects rewards from market participation\n- **Usage:** Call `skim(tokenAddress)` to transfer accumulated tokens\n\n## Role Management via Curator App\n\n  \n\n### Guardian Changes\n\nGuardian changes require timelock approval for security:\n\n1. Click **Change** next to the current guardian\n2. Enter the new guardian address\n3. Submit the transaction - this starts the timelock period\n4. Wait for the timelock to expire\n5. New guardian must click **Accept** to complete the change\n\n### Curator Management\n\nCurator changes are immediate and don't require timelock:\n\n1. Click **Change** next to the current curator\n2. Enter the new curator address\n3. Submit the transaction - change takes effect immediately\n\n### Allocator Management\n\n**Adding Allocators:**\n- Click **Add Allocator** in the top right\n- Enter the allocator address in the popup\n- Submit the transaction\n\n**Adding Public Allocator:**\n- Click **Add Public Allocator** for one-click integration\n- This adds the Morpho Public Allocator to your vault\n\n**Removing Allocators:**\n- Click **Remove** on the relevant allocator row\n- Confirm the transaction\n\nMultiple allocators can be active simultaneously. Both the owner and curator can add or remove allocators.\n\n## Best Practices\n\n- **Owner:** Use a secure multisig wallet for the owner role\n- **Curator:** Choose experienced DeFi professionals familiar with Morpho markets\n- **Guardian:** Select a trusted party different from the curator for oversight\n- **Fee Recipient:** Can be the same as owner or a separate treasury address\n- **Allocators:** Add the Public Allocator for automated optimizations, plus any custom allocators\n\nAlways double-check addresses before submitting role assignment transactions. Incorrect addresses cannot be easily reverted and may compromise vault security."
  },
  "/curate/tutorials-v1/vault-creation/": {
    "title": "Create a Vault",
    "url": "https://docs.morpho.org/curate/tutorials-v1/vault-creation/",
    "section": "Curate",
    "content": "This tutorial guides you through the process of creating and configuring a new vault in the Morpho ecosystem. Morpho Vaults can be created directly via etherscan (or any other explorer) or using scripts or using apps.\n\nMorpho Vaults curator is supposed to be a knowledgeable DeFi user, as monitoring liquidity on Morpho requires skills, and has some risks. Refer to the [risk section](/learn/resources/risks/).\n\nBefore operating a vault, make sure to implement protection against inflation front-running attacks. These attacks can allow malicious users to extract value from your vault. For detailed explanation and protection measures, refer to the [inflation front-running attack protection section](/learn/resources/risks/#inflation-front-running-attack-protection).\n\nFor permanent protection, it consists in depositing at least 1e9 shares (or 1e12 shares for assets with less than 9 decimals) in the vault on behalf of the address `0x000000000000000000000000000000000000dEaD`\n\n## Using the Curator App\n\nTo create a new Vault navigate using the left-hand side menu to the Create Vault section.\n\n  \n\nBy default, the owner of the Vault will be the address connected and submitting the transaction. You can create the Vault with any address and set the ownership to another, overriding the default by simply entering a different address.\n\nBy default, the Timelock value is set to 1 Day, however Curators can set it to 0 to facilitate the initial setup (ie. adding markets to the vault without waiting for the Timelock.)\n\nThe Timelock can be increased after the creation of the vault, but it cannot be set to 0 again after creation.\n\nThe rest of the fields are:\n\n- **Asset:** The address of the Vault’s deposit asset - cannot be modified after creation\n- **Name:** The display name of the Vault, which can be modified after creation\n- **Symbol:** The ticker of the vault’s receipt token - cannot be modified after creation\n- **Salt** (optional): A unique value to deterministically generate the Vault’s address (in conjunction with the other parameters)\n\nOnce the vault is configured with the desired parameters, click on Create Vault to submit the transaction.\n\n## Using Etherscan\n\n### Factory Address\n\nJump into the factory contract. You can find factory addresses on [the Addresses section here](/get-started/resources/addresses/).\n\nAlways double check the address you are clicking on.\n\n### Fill attributes\n\nOne will have to fill the following attributes:\n\n- `initialOwner`: The initial owner of the vault.  \n  This address will have the authority to manage the vault's settings and parameters after creation.\n- `initialTimelock`: The initial duration, in seconds, during which any critical operations (e.g. changing the curator or guardian roles, updating market parameters) are delayed for security reasons.\n  Starting from V1.1, the initial timelock can be set to 0 during vault creation to facilitate the initial configuration. After setup, the timelock must be set within bounds (minimum = 1 day = 86,400 seconds and maximum = 2 weeks = 1,209,600 seconds).\n\n   Timelock value: \n  It can be convenient to set the timelock to 0 during the initial configuration\n  phase to complete it faster. Once configuration is complete, any owner can increase\n  the timelock value to the required minimum of 86,400 seconds (1 day) or higher.\n\n- `asset`: The address of the underlying asset (ERC20 token) for which the vault is being created.\n  The vault will manage deposits and withdrawals of this asset.\n- `name`: The human-readable name of the vault.  \n  It is used primarily for display and identification purposes.\n- `symbol`: The abbreviation or ticker symbol of the vault.  \n  This symbol is a shorter way to represent the vault, typically used in interfaces and listings.\n- `salt`: A unique value used in conjunction with the vault's other parameters to deterministically generate its address through the CREATE2 opcode.\n  This ensures the uniqueness of the vault's address even if other parameters are identical. \n  <figcaption>Vault Creation</figcaption>\n\n### Approve\n\nApprove the transaction, and retrieve the address of your vault."
  },
  "/curate/tutorials-v2/abdicate-gates/": {
    "title": "Abdicate Gates",
    "url": "https://docs.morpho.org/curate/tutorials-v2/abdicate-gates/",
    "section": "Curate",
    "content": "This guide explains why and how curators can abdicate the **three critical gates** to guarantee users always have access to their funds, preserving the vault's non-custodial properties.\n\n## Why Abdicate Gates?\n\nMorpho Vault V2 implements four gates that control access to vault operations. Three of these gates are **critical** because they can potentially block users from accessing their funds:\n\n| Gate | Risk | Why It's Critical |\n|------|------|-------------------|\n| **Receive Shares Gate** | Can prevent users from receiving shares during deposits | Users could deposit assets but not receive shares |\n| **Send Shares Gate** | Can lock users out of withdrawals and transfers | Users cannot exit the vault |\n| **Receive Assets Gate** | Can prevent users from receiving assets on withdrawal | Users can burn shares but not receive their assets |\n\nThe fourth gate (**Send Assets Gate**) is non-critical because it only restricts who can deposit—it cannot block existing users from withdrawing.\n\n### Non-Custodial Guarantee\n\nBy abdicating the three critical gates to `address(0)`, a curator permanently guarantees that:\n- No access restrictions can ever be imposed on withdrawals\n- Users can always exit the vault and receive their assets\n- The vault remains truly non-custodial\n\nThis is an **irreversible** action that provides depositors with the strongest possible assurance.\n\n## Prerequisites\n\nBefore abdicating, ensure:\n1. All three critical gates are set to `address(0)` (no gate configured)\n2. You are connected with the **Curator** wallet\n3. You understand this action is **permanent and irreversible**\n\n## Tutorial: Abdicate Gates on the Curator App V2\n\n### Head to the [Curator App V2](https://curator.morpho.org/vaults)\n\nOn your Morpho Vault V2 page, head to the **Timelocks** tab and click on the **Abdicate** button.\n\n  \n\nYou can select the gate you want to abdicate and submit the abdication.\n\n  \n\nOnce the abdication is submitted, it will appear in the **Pending Timelocks**, click there and accept the abdication once the timelock has passed.\n\n  \n\n  \n\nYou can then check the gate function has been abdicated in the **Gates** table of the Timelocks page.\n\n  \n\n## Tutorial: Abdicate Gates via Etherscan\n\nAbdication follows a **two-step timelocked process**: first submit, wait for the timelock, then execute.\n\n### Step 1: Verify Current Gate Settings\n\n1. Go to your vault's contract on Etherscan\n2. Navigate to **Read Contract**\n3. Check the following functions return `0x0000000000000000000000000000000000000000`:\n   - `receiveSharesGate()`\n   - `sendSharesGate()`\n   - `receiveAssetsGate()`\n\nIf any gate is not `address(0)`, you must first set it to zero using the corresponding setter function (also timelocked).\n\n### Step 2: Submit Abdication\n\nNavigate to **Write Contract** and connect your Curator wallet.\n\nFor each gate you want to abdicate, call the `submit` function with the encoded `abdicate` call data:\n\n| Gate to Abdicate | Data to Submit |\n|------------------|----------------|\n| Receive Shares Gate | `0xb2e328482cb19f9800000000000000000000000000000000000000000000000000000000` |\n| Send Shares Gate | `0xb2e32848c21ad02800000000000000000000000000000000000000000000000000000000` |\n| Receive Assets Gate | `0xb2e3284804dbf0ce00000000000000000000000000000000000000000000000000000000` |\n\n1. Find the `submit` function\n2. Enter the data from the table above\n3. Click **Write** and confirm the transaction\n4. Repeat for each gate\n\n### Step 3: Wait for Timelock\n\nAfter submitting, you must wait for the vault's timelock period to elapse before executing.\n\nTo check the timelock duration, call `timelock(bytes4 selector)` with the `abdicate` selector: `0xb2e32848`.\n\n### Step 4: Execute Abdication\n\nOnce the timelock has passed, execute each abdication:\n\n1. Find the `abdicate` function\n2. Enter the gate setter selector:\n   - Receive Shares Gate: `0x2cb19f98`\n   - Send Shares Gate: `0xc21ad028`\n   - Receive Assets Gate: `0x04dbf0ce`\n3. Click **Write** and confirm the transaction\n\n### Function Selector Reference\n\n| Gate Setter Function | Selector |\n|---------------------|----------|\n| `setReceiveSharesGate(address)` | `0x2cb19f98` |\n| `setSendSharesGate(address)` | `0xc21ad028` |\n| `setReceiveAssetsGate(address)` | `0x04dbf0ce` |\n| `setSendAssetsGate(address)` | `0x871c979c` |\n\n### Step 5: Verify Abdication\n\nAfter all transactions confirm, verify the abdication was successful:\n\n1. Go to **Read Contract**\n2. Call `abdicated(bytes4 selector)` with each gate setter selector\n3. Confirm all three return `true`\n\n## Using Solidity\n\n### Step 1: Submit Abdications\n\n```solidity\nimport {IVaultV2} from \"@morpho-org/vault-v2/interfaces/IVaultV2.sol\";\n\n// Submit abdication for all three critical gates\nvault.submit(abi.encodeCall(IVaultV2.abdicate, (IVaultV2.setReceiveSharesGate.selector)));\nvault.submit(abi.encodeCall(IVaultV2.abdicate, (IVaultV2.setSendSharesGate.selector)));\nvault.submit(abi.encodeCall(IVaultV2.abdicate, (IVaultV2.setReceiveAssetsGate.selector)));\n```\n\n### Step 2: Execute After Timelock\n\n```solidity\n// After timelock has passed, execute each abdication\nvault.abdicate(IVaultV2.setReceiveSharesGate.selector);\nvault.abdicate(IVaultV2.setSendSharesGate.selector);\nvault.abdicate(IVaultV2.setReceiveAssetsGate.selector);\n```\n\nAbdication is **irreversible**. Once abdicated, the gate setter function can never be called again, permanently locking the gate to its current value (`address(0)`)."
  },
  "/curate/tutorials-v2/bad-debt/": {
    "title": "Managing Bad Debt: Morpho Vault V2",
    "url": "https://docs.morpho.org/curate/tutorials-v2/bad-debt/",
    "section": "Curate",
    "content": "## Overview\n\nThis guide is designed for Morpho Vault V2 curators and explains how bad debt is handled through the vault's loss socialization mechanism.\n\n### Bad Debt Recap\n\nAs a reminder, the health of a borrower's position can be divided into three main categories, with LTV being Loan-To-Value, LLTV being the Liquidation Loan-To-Value (one of the market parameters) and LIF the Liquidation Incentive Factor:\n1. If LTV < LLTV, the position is healthy, and the borrower cannot be liquidated.\n2. If LLTV < LTV ≤ 1/LIF, a liquidator can repay part or all of the user's debt and seize part or all of its collateral.\n3. If 1/LIF < LTV, a liquidator can seize all the collateral by repaying only a share of the debt. There is no incentive for the liquidator or borrower to repay the remaining debt. The latter is commonly referred to as bad debt.\n\nUnder situation 3, bad debt can be categorized into two types:\n- **Unrealized** when the liquidation has not occurred yet.\n- **Realized** when the liquidation has occurred, and the entire collateral position is seized. \n\n## How Morpho Vault V2 Handles Bad Debt\n\nMorpho Vault V2 implements an automatic loss socialization mechanism. When bad debt occurs in an underlying market or adapter, the loss is detected and reflected in the vault's share price. \n\n### Loss Detection\n\nEach adapter reports the actual current value of its investments via a `realAssets()` function. When bad debt occurs in an underlying market, the value reported by the adapter automatically decreases.\n\n### Loss Realization\n\nDuring interest accrual, the vault compares the reported real asset value to its internally tracked total:\n\n- If `realAssets` has dropped below the previously recorded `totalAssets`, the vault updates its accounting downward.\n- Interest calculation uses `zeroFloorSub()`, which floors at zero, meaning no negative interest is generated.\n- The vault's `totalAssets` is updated to `min(realAssets, maxTotalAssets)`.\n\n### Automatic Socialization\n\nLosses are socialized proportionally because share value is determined via convertToAssets(), which computes shares × (totalAssets + 1) / (totalSupply + virtualShares). When totalAssets decreases, so does the value returned by this function. When `totalAssets` decreases:\n\n- Each share is worth less.\n- No shares are burned — all shareholders absorb the loss equally.\n- Depositors who entered before the loss event bear the loss proportionally to their share of the vault.\n\n## Important Considerations for Curators\n\n### Management Fees During Loss Periods\n\nManagement fees continue to accrue even during periods where losses are realized. Curators should be aware that fees are computed before loss realization in the interest accrual flow.\n\n### Morpho Vault V1.1 Adapter Caveat\n\nMorpho Vaults V1.1 do not realize bad debt internally. If a Morpho Vault V2 supplies to a Morpho Vault V1.1 via a `MorphoVaultV1Adapter`, the corresponding losses from that allocation will **not** be reflected in the Morpho Vault V2's share price. Curators should account for this when allocating to Morpho Vaults V1.1.\n\n### Flash Loan Protection\n\nThe vault includes safeguards against share price manipulation around loss realization events. Losses are only accounted for once per transaction, preventing attackers from shorting shares around a known loss event."
  },
  "/curate/tutorials-v2/checklist/": {
    "title": "Checklist to Validate Vault V2 Configuration",
    "url": "https://docs.morpho.org/curate/tutorials-v2/checklist/",
    "section": "Curate",
    "content": "This checklist covers the setup of a Morpho Vault V2 using a single `MorphoMarketV1AdapterV2` to curate one or several Morpho Markets V1.\n\n## Vault V2 Setup Checklist\n\n*   [ ] **Create a new Morpho Vault V2** using the `VaultV2Factory`.\n*   [ ] **Set the core roles**: As `Owner`, assign the `Curator` and `Sentinel(s)`.\n*   [ ] **Set the Morpho Adapter Registry**: As `Curator`, submit and execute the timelocked proposal to set the `adapterRegistry` to the official Morpho registry.\n*   [ ] **Abdicate `setAdapterRegistry`**: As `Curator`, renounce the ability to change the adapter registry to lock in the official registry permanently.\n*   [ ] **Abdicate Gates**: As `Curator`, if needed, abdicate the three critical gates to remove the ability to restrict deposits and withdrawals ([More on Gate Abdication here](/curate/tutorials-v2/abdicate-gates/)).\n*   [ ] **Deploy the `MorphoMarketV1AdapterV2`**.\n*   [ ] **Enable the adapter**: As `Curator`, submit and execute the timelocked proposals to link the adapter to your vault.\n*   [ ] **Appoint the `Allocator(s)`**: As `Curator`, grant the `Allocator` role to your management contract or multisig via a timelocked proposal.\n*   [ ] **Set the risk caps**: As `Curator`, submit and execute the timelocked proposals to set `absoluteCap` and `relativeCap` on the vault for each Morpho Market V1 you want to include.\n*   [ ] **Set the `liquidityAdapter`**: As `Allocator`, designate the underlying Morpho Market V1 (within the `MorphoMarketV1AdapterV2`) as the default market for handling deposits and withdrawals (usually, a highly liquid market).\n*   [ ] **Set the dead deposit** for the vault itself ([tutorial](/curate/tutorials-v2/dead-deposit/)).\n*   [ ] **Set the dead deposit** for each listed market ([tutorial](/curate/tutorials-market-v1/dead-deposit/)).\n*   [ ] **Harden the vault's timelocks**: After the initial setup is complete, increase the timelocks for sensitive functions to a production-safe value.\n*   [ ] **Configure your reallocation, monitoring and liquidation bots**: Ensure your `Allocator` logic is in place to manage the vault's capital.\n\n## Integration Checklist\n\nMorpho has multiple integrations that will help distribute the vaults you create.\n\n*   [ ] Integrate your Morpho Vault V2 in Superform, IPOR Fusion, Summer.fi, Yearn, Beefy.\n*   [ ] Integrate your underlying Markets in Defisaver, Contango, Summer.fi.\n*   [ ] List and price your new vault token on platforms like Coingecko and Etherscan."
  },
  "/curate/tutorials-v2/dead-deposit/": {
    "title": "Morpho Vault V2 Dead Deposit",
    "url": "https://docs.morpho.org/curate/tutorials-v2/dead-deposit/",
    "section": "Curate",
    "content": "A dead deposit is a security measure against ERC-4626 inflation attacks ([read more](/build/earn/concepts/vault-mechanics#inflation-attack-protection)).\n\nOn an **empty** vault, execute:\n\n```solidity\nvault.mint(TARGET_SHARES, 0x000000000000000000000000000000000000dEaD);\n```\n\nThe dead deposit must be the **very first transaction** on an empty vault. If any user deposit occurs first, the inflation attack may already have been executed.\n\n## How Many Shares to Mint\n\nThe number of shares to mint depends on the vault's underlying asset decimals. Use the table below for common tokens:\n\n| Token  | Decimals | Shares to Mint         | Assets You'll Spend | USD Cost                      |\n|--------|----------|------------------------|---------------------|-------------------------------|\n| WETH   | 18       | 1,000,000,000          | ~0 ETH              | < $0.1                        |\n| wstETH | 18       | 1,000,000,000          | ~0 wstETH           | < $0.1                        |\n| sUSDS  | 18       | 1,000,000,000          | ~0 sUSDS            | < $0.1                        |\n| sUSDe  | 18       | 1,000,000,000          | ~0 sUSDe            | < $0.1                        |\n| siUSD  | 18       | 1,000,000,000          | ~0 siUSD            | < $0.1                        |\n| cbBTC  | 8        | 10,000,000,000,000,000 | 0.01 BTC            | ~$630 (at current BTC price)  |\n| WBTC   | 8        | 10,000,000,000,000,000 | 0.01 BTC            | ~$630 (at current BTC price)  |\n| USDC   | 6        | 1,000,000,000,000,000,000 | 1 USDC           | ~$1                           |\n| PYUSD  | 6        | 1,000,000,000,000,000,000 | 1 PYUSD          | ~$1                           |\n| USDT   | 6        | 1,000,000,000,000,000,000 | 1 USDT           | ~$1                           |\n\n**New or unlisted asset?** Use the formula:\n\n```\ntargetShares = max(1e9, 10^(6 + max(0, 18 - decimals)))\n```\n\n## How to Execute via Explorer\n\n#### 1. Verify the vault is empty\n\nNavigate to the Morpho Vault V2 contract on explorer → **Read Contract** → check that `totalSupply()` returns `0`.\n\n#### 2. Approve the vault to spend your tokens\n\nGo to the underlying token's explorer page → **Write Contract** → call `approve(vaultAddress, assetsAmount)`.\n\nUse the approval amounts below:\n\n| Decimals | Approval amount |\n|----------|-----------------|\n| 18       | 1000000000      |\n| 8        | 1000000         |\n| 6        | 1000000         |\n\n  \n\n#### 3. Mint shares to `0xdead`\n\nGo to the vault contract on Etherscan → **Write Contract** → call `mint(TARGET_SHARES, 0x000000000000000000000000000000000000dEaD)`.\n\nUse the **Shares to Mint** value from the table above for your token.\n\n  \n\n#### 4. Verify the dead deposit\n\nOn the vault contract → **Read Contract** → call `convertToAssets(1000000000000000000)`. The result should be approximately `10^decimals` (i.e. 1.0 token per share).\n\n## Additional Requirements\n\nBeyond the vault-level dead deposit, the following must also be satisfied:\n\n- `0xdead` must have **1e9 supplyShares** in each Morpho market V1 with a non-zero cap on the vault.\n- `0xdead` must have **1e9 shares** in each Morpho Vault V1 with a non-zero cap on the vault, as well as in each market in their withdraw queue.\n\n## Why These Numbers\n\nThe required shares satisfy two constraints simultaneously:\n\n1. **Inflation attack prevention**: at least 1e6 assets must be in the vault, limiting any single manipulation to a relative change of at most 1/1,000,000. This requires `shares >= 1e6 × virtualShares`.\n2. **Share price rounding protection**: prevents the share price from crashing to near-zero when an adapter rounds tiny balances to 0. This requires `shares / (shares + virtualShares) >= 0.999`.\n\nThe inflation attack constraint dominates (by a factor of 1,000), so the formula `max(1e9, 1e6 × virtualShares)` satisfies both. The 1e9 floor applies the existing per-market/per-vault minimum for 18-decimal assets where `virtualShares = 1`.\n\n`virtualShares = 10^max(0, 18 - decimals)` is a constant defined in the VaultV2 constructor."
  },
  "/curate/tutorials-v2/emergency/": {
    "title": "Emergency Procedures (Vaults V2)",
    "url": "https://docs.morpho.org/curate/tutorials-v2/emergency/",
    "section": "Curate",
    "content": "This document outlines procedures for handling emergency situations in Morpho Vaults V2. These actions should be executed with extreme care, as they can have significant consequences for the vault and its depositors.\n\nBefore proceeding, ensure you are familiar with [Roles & Capabilities](/curate/concepts/roles/), [Timelocks](/curate/concepts/timelock/), and [Adapters](/curate/tutorials-v2/listing-adapters/).\n\n## Quick Reference\n\n**Key V2 design principle:** Emergency functions that *reduce* risk (revoking, decreasing caps, deallocating) are never timelocked. Only functions that could *increase* risk are timelocked.\n\n| Action | Timelocked? | Who Can Execute |\n|---|---|---|\n| Revoke any pending timelocked action | No | Curator, Sentinel |\n| Decrease absolute/relative caps to 0 | No | Curator, Sentinel |\n| Deallocate funds to idle | No | Allocator, Sentinel |\n| Force deallocate (in-kind redemption) | No | Anyone (permissionless, subject to penalty) |\n| Remove allocator role (`setIsAllocator`) | Yes (configurable) | Curator via `submit` |\n| Remove adapter (`removeAdapter`) | Yes | Curator via `submit` |\n| Burn shares (adapter-level, MarketV1AdapterV2) | Yes (adapter timelock) | Curator via adapter `submit` |\n\n## Unsafe Adapter: Soft Deprecation\n\nUse this procedure when an adapter is deemed too risky for continued allocation, but all contracts are still functioning correctly and funds can be withdrawn normally.\n\nIf the adapter is working properly and the markets are deemed risky for allocation, the removal should happen [at the market level](/curate/tutorials-v2/emergency/#unsafe-market-soft-deprecation), not at the adapter level.\n\n### Procedure\n\n**Step 1 — Revoke Pending Cap Increases**\n\nIf there are any pending cap increases for ids associated with the adapter, the **Sentinel** or **Curator** should call `revoke(bytes)` on the vault to cancel them.\n\n```solidity\n// Revoke a pending absolute cap increase\nbytes memory pendingData = abi.encodeCall(IVaultV2.increaseAbsoluteCap, (idData, newCap));\nvault.revoke(pendingData);\n```\n\n**Step 2 — Set Caps to Zero**\n\nThe **Curator** or **Sentinel** calls `decreaseAbsoluteCap` and `decreaseRelativeCap` for all ids associated with the adapter, setting them to `0`. This prevents any new allocations to the adapter.\n\n```solidity\nvault.decreaseAbsoluteCap(idData, 0);\nvault.decreaseRelativeCap(idData, 0);\n```\n\n**Step 3 — Deallocate Liquidity to Idle**\n\nThe **Allocator** or **Sentinel** calls `deallocate` on the vault to withdraw all available assets from the adapter back to idle. If the underlying market is illiquid, this may need to be done in stages as liquidity becomes available.\n\n```solidity\nvault.deallocate(adapter, data, assets);\n```\n\nThe `assets` parameter requires an exact amount — neither the vault nor the `MorphoMarketV1AdapterV2` adapter interprets `type(uint256).max` as \"withdraw all.\" You must query the current allocation and pass the precise value.\n\n**Step 4 — Remove the Adapter**\n\nOnce the adapter's allocation reaches zero, the **Curator** calls `submit` to propose `removeAdapter`. This action is **timelocked**. After the timelock expires, anyone can execute the removal.\n\n```solidity\n// Submit removal (timelocked)\nvault.submit(abi.encodeCall(IVaultV2.removeAdapter, (adapterAddress)));\n\n// After timelock expires, execute\nvault.removeAdapter(adapterAddress);\n```\n\nIf the adapter is currently set as the `liquidityAdapter`, it should be unset first by the Allocator, otherwise further deposits into the vault would revert.\n\n**Loss of Funds:** If you remove an adapter that still has liquidity in it, this action will realize a loss.\n\n---\n\n## Market Reverts: Hard Deprecation\n\nUse this procedure when an underlying market is malfunctioning (e.g., its functions consistently revert), making it impossible to withdraw funds normally. **This action involves accepting the loss of any capital stuck in the market.**\n\n### MorphoMarketV1AdapterV2 — Burn Shares\n\nThe `MorphoMarketV1AdapterV2` has its own independent timelock system. Forced market removal happens at the **adapter level** via `burnShares`, which zeroes out the adapter's internal share accounting for a specific market.\n\n**Step 1 — Set Caps to Zero**\n\nAs with soft deprecation, the **Curator** or **Sentinel** should immediately decrease all caps to zero for ids associated with the market.\n\n**Step 2 — Submit `burnShares` (Timelocked at Adapter Level)**\n\nThe **Curator** calls `submit` on the adapter itself (not the vault) to propose burning the shares for the broken market.\n\n```solidity\n// Submit to the adapter (not the vault)\nadapter.submit(abi.encodeCall(IMorphoMarketV1AdapterV2.burnShares, (marketId)));\n```\n\nThe mandatory waiting period must elapse. During this time, the **Sentinel** or **Curator** can revoke via the adapter's `revoke` function if needed.\n\n**Step 3 — Execute `burnShares`**\n\nAfter the adapter timelock expires, anyone can execute the burn.\n\n```solidity\nadapter.burnShares(marketId);\n```\n\n**Step 4 — Sync Vault Accounting**\n\nDeallocate `0` from the vault to update its internal allocation tracking.\n\n```solidity\nvault.deallocate(adapter, data, 0);\n```\n\n**Warning: Loss of Funds.** Burnt shares are lost forever. This procedure should only be used when the market consistently reverts and funds are considered irrecoverable.\n\n### MorphoVaultV1Adapter\n\nFor the `MorphoVaultV1Adapter`, forced removal happens at the **vault level** since this adapter wraps an entire Vault V1 position rather than individual markets. In this scenario, follow the procedure in [V1 Emergency Actions](/curate/tutorials-v1/emergency/).\n\n### Impact on Depositors\n\nMorpho Vault V2 implements **automatic loss socialization**: when the adapter's `realAssets()` reports a value lower than previously recorded `totalAssets`, the vault updates its accounting downward, and the loss is reflected proportionally in the share price for all depositors. For a detailed breakdown of how this accounting update is computed, see [Managing Bad Debt](/curate/tutorials-v2/bad-debt/).\n\nIf the underlying adapter wraps a Vault V1.1, note that V1.1 does *not* realize bad debt internally — so the Morpho Vault V2 will also not reflect those specific losses.\n\n---\n\n## Allocator Compromise\n\nIf an **Allocator** is compromised or acting maliciously, the Curator should act to remove the role and correct any misallocations. The Allocator can only operate within the bounds set by the Curator (enabled adapters and caps), so the blast radius is limited to misallocation within the allowed set.\n\n### Procedure\n\n**Step 1 — Remove the Allocator Role**\n\nThe **Curator** calls `submit` to propose `setIsAllocator(compromisedAddress, false)`.\n\n```solidity\nvault.submit(abi.encodeCall(IVaultV2.setIsAllocator, (compromisedAddress, false)));\n\n// If timelock is 0, execute immediately\nvault.setIsAllocator(compromisedAddress, false);\n```\n\nIf the `setIsAllocator` timelock is non-zero, proceed to Step 2 while waiting.\n\n**Step 2 — Set Caps to Zero**\n\nThe **Sentinel** (or **Curator**) should immediately decrease all caps to zero. This is **instant** (cap decreases are exempt from timelocks) and neutralizes the allocator regardless of whether the role removal is timelocked.\n\n```solidity\nvault.decreaseAbsoluteCap(idData, 0);\nvault.decreaseRelativeCap(idData, 0);\n```\n\n**Step 3 — Correct Misallocations**\n\nA trusted Allocator or the Curator should deallocate from any wrongly allocated positions and reallocate according to the vault's intended strategy.\n\n```solidity\nvault.deallocate(adapter, data, assets);\n```\n\nOnce the compromised allocator is removed, the Curator re-establishes caps and assigns a new allocator.\n\n---\n\n## Curator Compromise\n\nIf the **Curator** begins acting maliciously (submitting caps for unsafe adapters or markets, adding untrusted markets or caps, changing fees or gates), the Owner and Sentinel must coordinate a response.\n\n### Procedure\n\n**Step 1 — Owner Replaces the Curator** (Instant)\n\nThe **Owner** immediately calls `setCurator` to transfer control to a new, trusted address. This is **not timelocked** — the Owner can execute this instantly.\n\n```solidity\nvault.setCurator(newTrustedCurator);\n```\n\nThis instantly strips the compromised address of all Curator capabilities.\n\n**Step 2 — Sentinel Revokes All Pending Actions** (Instant)\n\nThe **Sentinel** must call `revoke` on every pending timelocked action submitted by the compromised curator. In V2, `revoke(bytes)` can cancel **any** pending timelocked action — adapter additions, cap increases, fee changes, gate changes, allocator changes, timelock decreases, etc.\n\n```solidity\nvault.revoke(pendingMaliciousData);\n```\n\n**Step 3 — Assess Accepted Malicious Actions**\n\nIf any malicious changes were executed before they could be revoked:\n\n- **Malicious adapter was added:** The new Curator follows the [Soft Deprecation procedure](/curate/tutorials-v2/emergency#unsafe-adapter-soft-deprecation) to safely exit. Set caps to zero, deallocate all funds, then submit `removeAdapter`.\n- **Caps were increased on unsafe ids:** The new Curator or Sentinel instantly decreases caps to zero.\n- **Fees were changed:** The new Curator submits corrected fee values (timelocked).\n- **Gates were changed:** The new Curator submits corrected gate values (timelocked).\n\n**Key protection:** Depositors are protected by the timelock window. Even if the Curator is compromised, all risk-increasing actions (adding adapters, increasing caps, changing gates) must go through the timelock, giving the Sentinel and depositors time to react.\n\n### Adapter-Level Remediation (MorphoMarketV1AdapterV2)\n\nIf the vault uses `MorphoMarketV1AdapterV2`, the adapter has its own timelock system and checks `IVaultV2(parentVault).curator()` for authorization. Replacing the curator at the vault level automatically revokes the compromised address's access to adapter-level `submit` calls.\n\nHowever, any actions the compromised curator already submitted to the adapter remain pending. The new curator (or Sentinel) should revoke those at the adapter level as well:\n\n```solidity\nadapter.revoke(pendingAdapterData);\n```\n\n---\n\n## Owner Compromise\n\nOwner compromise is the most severe scenario. In Morpho Vault V2, the Owner's powers are intentionally limited — they can **only** set the Curator and Sentinels. They cannot directly modify caps, adapters, fees, or allocations. However, a compromised Owner can appoint a malicious Curator, which cascades into a Curator compromise scenario.\n\nDepositors must exit the vault before malicious configuration changes take effect. The vault should be considered **permanently compromised.**\n\n### Procedure\n\n**Step 1 — Sentinel Blocks Immediate Damage** (Instant)\n\nIf the compromised Owner sets a malicious Curator who begins submitting harmful proposals, the **Sentinel** (if not yet replaced) can revoke all pending actions.\n\nThe Sentinel should also proactively:\n\n- Decrease all caps to zero (preventing new allocations).\n- Deallocate all funds to idle (moving funds to the safest position).\n\n**Step 2 — Depositors Exit Within the Timelock Window**\n\nAll depositors should withdraw their funds before any malicious timelocked actions expire. The timelock is the depositors' primary defense.\n\n**Step 3 — Last Resort: `forceDeallocate`**\n\nIf the vault lacks idle liquidity for normal withdrawals, depositors can use the **permissionless** `forceDeallocate` to move assets from adapters to idle, then withdraw.\n\n**Warning: Full Loss of Vault.** Once the Owner is compromised and all depositors have exited, the vault should be considered permanently compromised. A new vault must be deployed.\n\n---\n\n## Sentinel Compromise\n\nSentinel compromise is the **least severe** role compromise, because the Sentinel can only perform risk-*reducing* actions: revoking pending actions, decreasing caps, and deallocating.\n\n### Impact\n\nA compromised Sentinel could:\n\n- Revoke legitimate pending proposals (denial of service, not loss of funds).\n- Decrease caps to zero (forces vault to idle, no loss of funds).\n- Deallocate funds to idle (moves everything to idle, no loss of funds).\n\n### Procedure\n\nThe **Owner** calls `setIsSentinel(compromisedAddress, false)` to remove the compromised sentinel and appoint a new one.\n\n```solidity\nvault.setIsSentinel(compromisedAddress, false);\nvault.setIsSentinel(newSentinel, true);\n```\n\nThe Curator then re-submits any legitimate proposals that were revoked by the compromised sentinel."
  },
  "/curate/tutorials-v2/liquidity-curation/": {
    "title": "Liquidity Curation with MarketV1AdapterV2",
    "url": "https://docs.morpho.org/curate/tutorials-v2/liquidity-curation/",
    "section": "Curate",
    "content": "## How the Liquidity Adapter Works\n\nWhen a `MorphoMarketV1AdapterV2` is set as the vault's `liquidityAdapter`, it points to **one specific underlying Variable Rate Market (Market V1)** at a time, configured via `liquidityData`.\n\nAll deposits flow into this market, and all withdrawals are sourced from it.\n\nThis means:\n\n- If the adapter is deployed across multiple Variable Rate Markets (Markets V1) (e.g., cbBTC/USDC, WETH/USDC, WBTC/USDC), only the one selected as the liquidity adapter is used for deposits and withdrawals.\n- On Morpho Vault V2 withdrawals, the vault's idle assets are used first, and then the liquidity adapter's available liquidity.\n- If that specific market reaches 100% utilization, and the vault's idle assets are empty, the vault is effectively illiquid from the user's perspective. Any withdrawal attempt will revert.\n- There is **no automatic fallthrough** to other markets within the same adapter. There is no configurable withdrawal queue in Morpho Vault V2 — unlike Vault V1, where the allocator can define and reorder the queue.\n- If the liquidity adapter's allocation caps are reached, deposit and mint operations will **revert**. There is no fallback to idle assets for deposits.\n\n**Key difference from Morpho Vault V1:** In Morpho Vault V1, the withdraw queue iterates through multiple markets to fulfill a withdrawal. In Morpho Vault V2 with a liquidity adapter sourcing via a MarketV1AdapterV2, liquidity is sourced from a single Variable Rate Market (Market V1) at a time.\n\n## Dynamic Reallocation\n\nA good practice to maintain liquidity is to run a **reallocation bot** that continuously manages the liquidity adapter configuration:\n\n1. **Monitor** the available liquidity of the current liquidity adapter.\n2. **Switch** the liquidity adapter to the most liquid Variable Rate Market when needed, or **reallocate** funds after a large withdrawal or when available liquidity drops below a defined threshold.\n\nBoth the `liquidityAdapter` and the underlying `liquidityData` (i.e. which Variable Rate Market is used) can be changed on the fly by the allocator bot to meet demand. This is conceptually similar to how Morpho Vaults V1 already work: you need to reallocate liquidity between withdrawal and deposit events to avoid allocation drift.\n\nWhile you are setting up your reallocation bot, you can use a [`MorphoVaultV1Adapter`](/curate/tutorials-v2/listing-adapters/) as a transitional liquidity adapter. Variable Rate Market adapters (via MarketV1AdapterV2) remain the long-term target.\n\n## The `forceDeallocate` Safety Net\n\nEven if the reallocation bot has not caught up, users have a way out. The `forceDeallocate` mechanism allows **anyone** to permissionlessly trigger available liquidity movement from an adapter into the vault's idle assets, thus making these idle assets available for withdrawals.\n\n### Zero-Fee `forceDeallocate`\n\nSetting the `forceDeallocatePenalty` to zero on the Morpho Vault V2 for the `MorphoMarketV1AdapterV2` adapter allows users to trigger reallocation at no cost. This effectively makes all vault available liquidity accessible for withdrawals at all times.\n\n**Important:** The `forceDeallocatePenalty` is configured at Morpho Vault V2 level **per adapter**, not globally. You can set it to zero for the `MorphoMarketV1AdapterV2` without affecting other adapters in the vault.\n\n## Griefing Risk with Zero-Fee `forceDeallocate`\n\nSetting the penalty to zero introduces a griefing vector: anyone can repeatedly force all available liquidity into the vault's idle assets, even if the curator's intended allocation is different. This is analogous to the [Public Allocator](/curate/tutorials-v1/public-allocator/) griefing dynamics in Morpho Vault V1.\n\nAfter a griefing event, the allocator bot would need to reallocate funds back to the intended distribution.\n\n### Mitigation\n\nThis is a fundamental tradeoff of making all liquidity available at all times. To reduce the impact of griefing:\n\n- Ensure the reallocation bot can respond quickly to restore the intended allocation.\n- Monitor for repeated `forceDeallocate` calls and adjust the penalty if griefing becomes persistent.\n\n## Summary\n\n| Aspect             | Morpho Vault V1                                         | Morpho Vault V2 with MarketV1AdapterV2                                                      |\n| ------------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------------------- |\n| Withdrawal source  | Iterates through withdraw queue across multiple markets | Single liquidity market at a time                                                           |\n| Liquidity curation | Manual or bot-driven reallocation                       | Bot dynamically reallocates liquidity via `liquidityData` or changes the liquidity adapter  |\n| Fallback mechanism | Queue iteration                                         | `forceDeallocate` (permissionless)                                                          |\n| Gas cost           | Higher per tx                                           | Lower per tx                                                                                |\n| Griefing surface   | Public Allocator manipulation                           | `forceDeallocate` manipulation (if penalty is zero)                                         |\n\n## Good Practices\n\n1. **Use `MorphoMarketV1AdapterV2`** as your liquidity adapter for lower gas costs.\n2. **Run a reallocation bot** that monitors liquidity and dynamically switch the liquidity adapter as conditions change.\n3. **Set `forceDeallocatePenalty` to zero** on the Morpho Vault V2 for the `MorphoMarketV1AdapterV2` adapter to ensure withdrawals are never stuck.\n4. **Monitor for allocation drift**. As with Morpho Vault V1, the allocator should reallocate to maintain yield and risk profile."
  },
  "/curate/tutorials-v2/listing-adapters/": {
    "title": "Curate Adapters (Vaults V2)",
    "url": "https://docs.morpho.org/curate/tutorials-v2/listing-adapters/",
    "section": "Curate",
    "content": "Adapters are the core of a Morpho Vault V2's extensibility. They are smart contracts that act as bridges, allowing your vault to connect to and allocate assets in any version of the Morpho protocol. As a `Curator`, enabling and managing adapters is how you define your vault's investment universe.\n\nThis guide will walk you through the process of deploying, listing, and managing adapters, with a focus on two key adapters:\n1. **`MorphoMarketV1AdapterV2`**: Connects your Morpho Vault V2 directly to Morpho V1 markets.\n2. **`MorphoVaultV1Adapter`**: Connects your Morpho Vault V2 to a Morpho Vault V1.\n\n**What is an Adapter?**\nAn adapter contains the specific logic needed to `allocate` and `deallocate` funds to a target protocol. It must be enabled via `addAdapter` (a **timelocked** action) before the vault can interact with it. Adapters also define the \"ids\" used for risk management caps.\n\n## Setting Up Your First Adapter: The `MorphoMarketV1AdapterV2` \n\nThe `MorphoMarketV1AdapterV2` allows your Morpho Vault V2 to allocate directly to Morpho Markets V1. It is deployed via the `MorphoMarketV1AdapterV2Factory`, which takes the parent vault address and automatically connects to the Morpho V1 contract.\n\n### Method 1: via the [Curator App V2](https://curator.morpho.org/vaults) (Recommended)\n\nOn your Morpho Vault V2 page, click on the **Adapters** tab. If none setup yet, the interface will propose a flow to set an adapter.\n\n  \n\nThe flow will implement the steps below:\n- Deploy adapter\n- Submit adapter\n- Approve adapter timelock\n- Set adapter caps\n- Set collateral token caps\n- Set market caps\n\n#### 1. Review and deploy the `MorphoMarketV1AdapterV2`\n\n#### 2. Once deployed, you can refer to the flow presented on the Submit Market Adapter frame and `Submit Adapter`.\n\n  \n\n#### 3. Once submitted and potential timelock has passed, reclick on the flow to actually add the Adapter.\n\n#### 4. To finalize the Adapter setup, head over the **Caps** tab, and set the following caps:\n- **Adapter Caps**: via the \"Edit Caps\" button, set the Absolute (in loan asset) and Relative (in % of vault allocation) caps for the Adapter you just deployed and set to your Morpho Vault V2.\n- **Collateral Token Caps**: via the \"Add collateral\" button specify a collateral asset address and the related Absolute and Relative Caps.\n- **Market Caps**: via the \"Add market\" button specify a market ID and the related Absolute and Relative Caps.\n\n  \n\nNote that for all caps, the process happens in 2 steps:\n- First, you submit the caps\n- Then, once timelock has passed (if any), click on the \"Timelocks\" button to accept the Caps.\n\nTip: you can first submit all the caps, and then batch accept all the Caps at once with the \"Timelocks\" button.\n\n### Method 2: via Script\n\nThe deployment repository handles adapter setup automatically:\n**[https://github.com/morpho-org/vault-v2-deployment](https://github.com/morpho-org/vault-v2-deployment)**\n\nThis repository is for educational purposes only. Do not use in production without thorough review and testing.\n\nFor adding adapters after deployment:\n\n**`script/AddAdapter.s.sol`**\n```solidity\npragma solidity 0.8.28;\n\nimport {Script, console} from \"forge-std/Script.sol\";\nimport {IVaultV2} from \"vault-v2/interfaces/IVaultV2.sol\";\nimport {IMorphoMarketV1AdapterV2Factory} from \"vault-v2/adapters/interfaces/IMorphoMarketV1AdapterV2Factory.sol\";\n\ncontract AddAdapter is Script {\n    function run() external {\n        address vaultAddress = vm.envAddress(\"VAULT_V2_ADDRESS\");\n        address factoryAddress = vm.envAddress(\"MORPHO_MARKET_V1_ADAPTER_V2_FACTORY\");\n\n        IVaultV2 vault = IVaultV2(vaultAddress);\n\n        vm.startBroadcast();\n\n        // Deploy new adapter via factory\n        address newAdapter = IMorphoMarketV1AdapterV2Factory(factoryAddress)\n            .createMorphoMarketV1AdapterV2(vaultAddress);\n\n        // Submit enablement proposal\n        bytes memory enableData = abi.encodeCall(IVaultV2.addAdapter, (newAdapter));\n        vault.submit(enableData);\n\n        // Submit cap increases\n        bytes memory idData = abi.encode(\"this\", newAdapter);\n        vault.submit(abi.encodeCall(IVaultV2.increaseAbsoluteCap, (idData, type(uint128).max)));\n        vault.submit(abi.encodeCall(IVaultV2.increaseRelativeCap, (idData, 1e18)));\n\n        vm.stopBroadcast();\n\n        console.log(\"Adapter deployed at:\", newAdapter);\n        console.log(\"Proposals submitted. Execute after timelock.\");\n    }\n}\n```\n\n### Method 3: via Etherscan\n\n#### 1. Deploy the Adapter\n\nDeploy `MorphoMarketV1AdapterV2` via its factory by calling:\n```solidity\nfactory.createMorphoMarketV1AdapterV2(vaultV2Address)\n```\nwhere `factory` is the deployed `MorphoMarketV1AdapterV2Factory` contract.\n\n#### 2. Enable the Adapter\n\n1. As Curator, encode: `abi.encodeCall(IVaultV2.addAdapter, (adapterAddress))`.\n2. Call `submit(bytes)` with the encoded data.\n3. After timelock, call `addAdapter(adapterAddress)`.\n\n#### 3. Set Risk Caps\n\nThe adapter's ID is computed as:\n```solidity\nbytes memory idData = abi.encode(\"this\", adapterAddress);\nbytes32 id = keccak256(idData);\n```\n\nSubmit and execute cap increases:\n- `increaseAbsoluteCap(idData, capAmount)`\n- `increaseRelativeCap(idData, relativeCapWad)` (where 1e18 = 100%)\n\n#### 4. Set as Liquidity Adapter (if needed)\n\nAs Allocator, call with the default `MarketParams` encoded as data. The encoded market params identify which Morpho V1 market will receive new user deposits and serve withdrawals:\n```solidity\nbytes memory liquidityData = abi.encode(marketParams);\nvault.setLiquidityAdapterAndData(adapterAddress, liquidityData);\n```\n\n### Allocating to Morpho Markets V1\n\nOnce enabled, allocate to specific markets by encoding the market parameters:\n\n```solidity\n// Prepare market parameters\nMarketParams memory marketParams = MarketParams({\n    loanToken: loanTokenAddress,\n    collateralToken: collateralTokenAddress,\n    oracle: oracleAddress,\n    irm: irmAddress,\n    lltv: lltv\n});\n\n// Allocate as Allocator\nbytes memory data = abi.encode(marketParams);\nvault.allocate(morphoMarketV1AdapterV2, data, amount);\n```\n\n## Optional: Adding a `MorphoVaultV1Adapter`\n\nA `MorphoVaultV1Adapter` can be added in addition to connect your Morpho Vault V2 to an existing Morpho Vault V1.\n\n### Method 1: via the [Curator App V2](https://curator.morpho.org/vaults) (Recommended)\n\nOn your Morpho Vault V2 page, click on the **Adapters** tab. If none setup yet, the interface will propose a flow to set an adapter.\n\n  \n\nYou will then be able to:\n- Deploy the Adapter\n- Set the Adapter (two steps submit/approve timelocked operation) on the **Adapters** page\n- Set the Adapter caps (two steps submit/approve timelocked operation) on the **Caps** page\n\n### Method 2: via Script\n\nThe `DeployVaultV2.s.sol` script in the deployment repository includes automatic setup:\n\n```solidity\n// Deploy MorphoVaultV1Adapter\naddress morphoVaultV1Adapter = address(new MorphoVaultV1Adapter(address(vaultV2), address(vaultV1)));\n\n// --- Step 1: Submit proposals (run immediately) ---\nbytes memory idData = abi.encode(\"this\", morphoVaultV1Adapter);\nvaultV2.submit(abi.encodeCall(vaultV2.addAdapter, (morphoVaultV1Adapter)));\nvaultV2.submit(abi.encodeCall(vaultV2.increaseAbsoluteCap, (idData, type(uint128).max)));\nvaultV2.submit(abi.encodeCall(vaultV2.increaseRelativeCap, (idData, 1e18)));\n\n// --- Step 2: Execute after the vault's timelock has elapsed (run in a separate transaction) ---\nvaultV2.addAdapter(morphoVaultV1Adapter);\nvaultV2.increaseAbsoluteCap(idData, type(uint128).max);\nvaultV2.increaseRelativeCap(idData, 1e18);\n\n// Set as liquidity adapter (no timelock required)\nvaultV2.setLiquidityAdapterAndData(morphoVaultV1Adapter, bytes(\"\"));\n```\n\nTo add it manually after deployment, follow the same steps as above (deploy with `_parentVault` and `_morphoVaultV1` constructor params, then enable and set caps via the timelock flow).\n\n## Managing Adapter Caps\n\n### Method 1: via the [Curator App V2](https://curator.morpho.org/vaults) (Recommended)\n\nDirectly on the **Caps** page of your Morpho Vault V2 by clicking on the \"Edit Caps\" button.\n\n  \n\n### Method 2: via Script\n\nEach adapter has associated IDs for risk management:\n\n- **MorphoMarketV1AdapterV2**: Three IDs:\n  - Adapter ID: `keccak256(abi.encode(\"this\", adapterAddress))`\n  - Collateral ID: `keccak256(abi.encode(\"collateralToken\", collateralAddress))`\n  - Market ID: `keccak256(abi.encode(\"this/marketParams\", address(this), marketParams))` — where `address(this)` is the deployed adapter address\n- **MorphoVaultV1Adapter**: Single ID based on `keccak256(abi.encode(\"this\", adapterAddress))`\n\nSentinels can decrease caps immediately:\n```solidity\nvault.decreaseAbsoluteCap(idData, newLowerCap);\nvault.decreaseRelativeCap(idData, newLowerRelativeCap);\n```\n\n## Delisting an Adapter\n\n**Critical Pre-check**\nBefore delisting an adapter, ensure the vault has **zero assets allocated** through it. Use `deallocate` to withdraw all funds first. Check with `vault.allocation(id)`.\n\nTo delist:\n\n1. **Deallocate All Funds**:\n```solidity\nvault.deallocate(adapterAddress, data, totalAllocated);\n```\n\n2. **Submit Delisting Proposal** (as Curator):\n```solidity\nbytes memory data = abi.encodeCall(IVaultV2.removeAdapter, (adapterAddress));\nvault.submit(data);\n```\n\n3. **Execute After Timelock**:\n```solidity\nvault.removeAdapter(adapterAddress);\n```\n\n## Setting Force Deallocate Penalty\n\nTo enable emergency withdrawals with a penalty:\n\n```solidity\n// As Curator, submit proposal (max 2% = 0.02e18)\nvault.submit(abi.encodeCall(IVaultV2.setForceDeallocatePenalty, (adapterAddress, 0.01e18)));\n\n// After timelock\nvault.setForceDeallocatePenalty(adapterAddress, 0.01e18); // 1% penalty\n```"
  },
  "/curate/tutorials-v2/roles/": {
    "title": "Manage Vault V2 Roles",
    "url": "https://docs.morpho.org/curate/tutorials-v2/roles/",
    "section": "Curate",
    "content": "This tutorial guides you through setting up and managing roles for a **Morpho Vault V2**. A clear understanding and proper assignment of roles are critical for the vault's security, governance, and operational success.\n\n**Separation of Concerns is Key**\n\nThe Vault V2 role system is designed with a strict separation of powers. The `Owner` manages permissions, the `Curator` sets strategy, the `Allocator` executes it, and the `Sentinel` ensures safety. Unlike V1, roles do not inherit permissions from each other. For a detailed breakdown, please refer to the [Vaults V2 Roles concept page](/curate/concepts/roles#morpho-vaults-v2-roles).\n\n**Handle Private Keys with Extreme Care**\n\nThe `Owner` and `Curator` roles hold significant power. It is highly recommended to secure these roles with a multisig or an institutional-grade MPC wallet. Never use a single EOA (hot wallet) for these roles in a production environment. Always verify addresses before executing transactions.\n\n## The Role Setup Workflow\n\nSetting up roles for a new Vault V2 follows a specific sequence. The `Owner` first assigns the `Curator` and `Sentinels` (actions which are immediate). Then, the `Curator` proposes strategic changes, such as appointing an `Allocator`.\n\nCrucially, most of the `Curator`'s actions are **timelocked**. The process for these actions depends on whether a timelock duration is set.\n\n## Managing Roles via Scripts (Recommended)\n\nThe official deployment repository handles role management efficiently:\n**[https://github.com/morpho-org/vault-v2-deployment](https://github.com/morpho-org/vault-v2-deployment)**\n\n### Scenario 1: Initial Vault Setup (Zero Timelock)\n\nThe `DeployVaultV2.s.sol` script handles the complete initial setup. Here's how it manages roles:\n\n```solidity\n// The script sets the broadcaster as temporary owner and curator\nVaultV2 vaultV2 = new VaultV2(broadcaster, vaultV1.asset());\nvaultV2.setCurator(broadcaster);\n\n// Submit allocator role assignments\nvaultV2.submit(abi.encodeCall(vaultV2.setIsAllocator, (broadcaster, true)));\nvaultV2.submit(abi.encodeCall(vaultV2.setIsAllocator, (allocator, true)));\n\n// Execute immediately (timelock is 0 by default)\nvaultV2.setIsAllocator(broadcaster, true);\nvaultV2.setIsAllocator(allocator, true);\n\n// After configuration, transfer roles to final addresses\nvaultV2.setCurator(curator);\nif (sentinel != address(0)) {\n    vaultV2.setIsSentinel(sentinel, true);\n}\nvaultV2.setOwner(owner);\n```\n\n### Scenario 2: Production Management (Non-Zero Timelock)\n\nOnce a vault has non-zero timelocks, role changes require a two-step process:\n\n#### Step 1: Submitting a Role Change\n\nCreate a script to submit the proposal:\n\n**`script/SubmitRoleChange.s.sol`**\n```solidity\npragma solidity 0.8.28;\n\nimport {Script} from \"forge-std/Script.sol\";\nimport {IVaultV2} from \"vault-v2/interfaces/IVaultV2.sol\";\n\ncontract SubmitRoleChange is Script {\n    function run() external {\n        address vaultAddress = vm.envAddress(\"VAULT_V2_ADDRESS\");\n        address newAllocator = vm.envAddress(\"NEW_ALLOCATOR_ADDRESS\");\n        \n        IVaultV2 vault = IVaultV2(vaultAddress);\n        \n        vm.startBroadcast();\n        \n        // Submit the proposal\n        bytes memory data = abi.encodeCall(IVaultV2.setIsAllocator, (newAllocator, true));\n        vault.submit(data);\n        \n        vm.stopBroadcast();\n        \n        uint256 timelock = vault.timelock(IVaultV2.setIsAllocator.selector);\n        console.log(\"Proposal submitted. Execute after\", timelock, \"seconds\");\n    }\n}\n```\n\n#### Step 2: Executing the Role Change\n\nAfter the timelock expires, execute the change:\n\n**`script/ExecuteRoleChange.s.sol`**\n```solidity\npragma solidity 0.8.28;\n\nimport {Script} from \"forge-std/Script.sol\";\nimport {IVaultV2} from \"vault-v2/interfaces/IVaultV2.sol\";\n\ncontract ExecuteRoleChange is Script {\n    function run() external {\n        address vaultAddress = vm.envAddress(\"VAULT_V2_ADDRESS\");\n        address newAllocator = vm.envAddress(\"NEW_ALLOCATOR_ADDRESS\");\n        \n        IVaultV2 vault = IVaultV2(vaultAddress);\n        \n        vm.startBroadcast();\n        \n        // Execute the timelocked action\n        vault.setIsAllocator(newAllocator, true);\n        \n        vm.stopBroadcast();\n        \n        console.log(\"Allocator role assigned successfully\");\n    }\n}\n```\n\n### Revoking Proposals\n\nCurators and Sentinels can revoke pending proposals:\n\n```solidity\n// To revoke a pending proposal\nbytes memory dataToRevoke = abi.encodeCall(IVaultV2.setIsAllocator, (address, bool));\nvault.revoke(dataToRevoke);\n```\n\n## Managing Roles via Etherscan\n\nFor manual management, the process mirrors the scripted approach.\n\n### Owner Actions (Immediate)\n\nAs the `Owner`, connect your wallet to the Vault V2 contract on Etherscan and use the `Write Contract` tab to:\n- Execute `setCurator(address newCurator)` to appoint the Curator.\n- Execute `setIsSentinel(address account, bool newIsSentinel)` to add or remove Sentinels.\n- Execute `setOwner(address newOwner)` to transfer ownership.\n\n### Curator Actions (Timelocked)\n\nAs the `Curator`, connect your wallet to:\n1. **Submit the Proposal**:\n   - Use a tool like [Foundry's `cast calldata`](https://book.getfoundry.sh/reference/cast/cast-calldata) to ABI-encode your intended function call (e.g., `setIsAllocator(0x..., true)`).\n   - Call the `submit(bytes)` function with the encoded data.\n2. **Wait for the Timelock**: Check `executableAt(bytes data)` to see when execution is allowed.\n3. **Execute the Proposal**: After the timelock, **anyone** can call the original function to finalize the change.\n\n### Checking Role Status\n\nUse the `Read Contract` tab to verify current roles:\n- `owner()`: Returns the current owner\n- `curator()`: Returns the current curator\n- `isAllocator(address)`: Check if an address is an allocator\n- `isSentinel(address)`: Check if an address is a sentinel"
  },
  "/curate/tutorials-v2/vault-creation/": {
    "title": "Create a Morpho Vault V2",
    "url": "https://docs.morpho.org/curate/tutorials-v2/vault-creation/",
    "section": "Curate",
    "content": "Deploying a Morpho Vault V2 is a permissionless process that anyone can initiate. This guide covers three methods for deploying your vault, ranging from the simplest user-friendly interface to more advanced technical approaches.\n\nThis guide covers three methods for deploying your vault:\n1. **Using the Curator App (Recommended)**: The easiest and most user-friendly method with a graphical interface for vault creation and configuration.\n2. **Using a Deployment Script**: A powerful and efficient method for developers, allowing you to create, configure, and assign roles for your vault in a single, automated process.\n3. **Using Etherscan**: A manual approach suitable for those who prefer interacting directly with contracts on a block explorer.\n\n## Method 1: Create a Vault via the Curator App\n\nThe Curator App provides the easiest and most user-friendly way to deploy a Morpho Vault V2. This web-based interface guides you through the entire vault creation process without requiring any coding or command-line experience.\n\n**Curator App**: [**https://curator.morpho.org/vaults**](https://curator.morpho.org/vaults)\n\n### Why Use the Curator App?\n\n- **No Technical Knowledge Required**: User-friendly graphical interface suitable for all experience levels.\n- **Guided Setup**: Step-by-step wizard walks you through every configuration option.\n- **Instant Deployment**: Deploy your vault directly from your browser using your connected wallet.\n- **Built-in Validation**: Automatic validation of parameters to prevent common configuration mistakes.\n- **Visual Configuration**: Easily configure roles, adapters, and risk parameters through intuitive forms.\n\n### Getting Started with the Curator App\n\n#### 1. Connect Your Wallet\n\nNavigate to [https://curator.morpho.org/vaults](https://curator.morpho.org/vaults) and connect your Ethereum wallet (e.g., MetaMask, WalletConnect).\n\n#### 2. Select Network\n\nChoose the network where you want to deploy your vault. Morpho Vault V2 is available on multiple networks including Ethereum mainnet, Base, and other supported chains.\n\n#### 3. Configure Vault Parameters\n\nYou will first be asked to set the main vault's parameters:\n- **Asset**: Select the ERC-20 token your vault will use (e.g., USDC, WETH).\n- **Owner**: Set the initial owner address (ideally a multisig for security).\n\nOnce the vault created, set and abdicate the [Morpho registry](/curate/concepts/adapter-registry/#the-morpho-registry).\n\nYou can then set the other Vault's parameters:\n- **Vault Symbol**: Choose a token symbol for your vault.\n- **Vault Name**: Choose a descriptive name for your vault.\n- **Curator**: Assign the curator role for managing vault parameters.\n- **Allocator**: Set the allocator address for managing fund allocations.\n- **Sentinel** (Optional): Optionally assign a sentinel for emergency actions.\n- **MaxRate**: The maximum rate earn by vault's suppliers. MaxRate must be set for suppliers to earn yield (more [here](/curate/concepts/yield/#interest-rate-controls)).\n\n#### 4. Configure Adapters and Risk Parameters\n\n- Select which Morpho Vault V1 instances you want to use as underlying liquidity markets.\n- Set initial risk caps (absolute and relative) for each adapter.\n- Configure the liquidity adapter for managing fund flows.\n\n#### 5. Set Timelock (Optional)\n\nConfigure timelock durations for critical functions to add an additional security layer for production vaults.\n\n#### 6. Review and Deploy\n\nReview all your configuration settings, then click \"Deploy Vault\". Your wallet will prompt you to confirm the transaction.\n\nOnce deployed, you can continue managing your vault through the Curator App or use the advanced methods described below for programmatic management.\n\n## Method 2: Create and Configure a Morpho Vault V2 via Script\n\nFor developers who prefer a code-based approach, you can refer to the Morpho Vault V2 deployment repository. This repository contains an example script that bundles multiple setup actions into a single transaction.\n\n**Repository**: [**https://github.com/morpho-org/vault-v2-deployment**](https://github.com/morpho-org/vault-v2-deployment)\n\n**Educational Purpose Only**: This repository and script are provided for **demonstration and educational purposes only**. Do not use in production without thorough review and testing. Always test extensively on testnets before any mainnet deployment. You are solely responsible for understanding every line of code and any consequences of using it.\n\n### Overview\n\nThe `DeployVaultV2WithMarketAdapter.s.sol` script demonstrates how to deploy and configure a Morpho Vault V2. It leverages the fact that new vaults have a zero-second timelock by default, allowing all initial configuration to be executed immediately.\n\nThis script deploys a Morpho Vault V2 using **MorphoMarketV1AdapterV2**, which connects directly to Morpho Markets V1.\n\nThe deployment process consists of the following phases:\n\n| Phase | Description                                 |\n|-------|---------------------------------------------|\n| 1     | Deploy Morpho Vault V2 instance via factory |\n| 2     | Configure temporary permissions             |\n| 3     | Deploy MorphoMarketV1AdapterV2              |\n| 4     | Submit timelocked configuration changes     |\n| 5     | Execute configuration + gates abdication    |\n| 6     | Set final role assignments                  |\n| 7     | Configure market and liquidity adapter      |\n| 8     | Execute vault dead deposit                  |\n| 9     | Configure vault timelocks                   |\n| 10    | Configure adapter timelocks                 |\n\n### Prerequisites\n\nBefore deploying, ensure you have:\n\n- [Foundry](https://getfoundry.sh/) installed\n- Git installed\n- An Ethereum wallet with sufficient funds for deployment\n- RPC URL for your target network\n- Sufficient tokens for the dead deposit (required for [inflation attack protection](/curate/concepts/security-considerations/#inflation-front-running-attack-protection))\n\n### Running the Deployment Script\n\n#### 1. Clone the Repository and Install Dependencies\n\n```bash\ngit clone https://github.com/morpho-org/vault-v2-deployment\ncd vault-v2-deployment\nforge install\n```\n\n#### 2. Configure Environment Variables\n\nCreate a `.env` file with your deployment configuration:\n\n```bash\n# Network\nRPC_URL=https://...            # Your RPC endpoint\nPRIVATE_KEY=0x...              # Your private key (keep secure!)\n\n# Role addresses (replace with your actual addresses)\nOWNER=0x...                    # Final owner of the vault (ideally a multisig)\nCURATOR=0x...                  # Curator address (defaults to OWNER if not set)\nALLOCATOR=0x...                # Allocator address (defaults to OWNER if not set)\nSENTINEL=0x...                 # Sentinel address (optional)\n\n# Deployed contract addresses (network-specific)\n# See https://docs.morpho.org/get-started/resources/addresses/ for addresses\nASSET=0x...                    # Underlying asset token (e.g., USDC, WETH)\nADAPTER_REGISTRY=0x...         # Morpho Registry address\nVAULT_V2_FACTORY=0x...         # VaultV2 Factory address\nMORPHO_MARKET_V1_ADAPTER_V2_FACTORY=0x...  # MorphoMarketV1AdapterV2 Factory address\n\n# First market configuration (optional - set to 0x0 to skip)\nMARKET_ID=0x...                # Morpho Blue market ID\nCOLLATERAL_TOKEN_CAP=...       # Max allocation to collateral token\nMARKET_CAP=...                 # Max allocation to specific market\n\n# Timelock configuration (in seconds)\n# Good practice is a minimum 3 days = 259200 seconds\nVAULT_TIMELOCK_DURATION=259200\nADAPTER_TIMELOCK_DURATION=259200\n\n# Optional: For contract verification\nETHERSCAN_API_KEY=...          # Your Etherscan API key\n```\n\n**Security Note**: Never commit your `.env` file to version control. It contains sensitive information like private keys.\n\n#### 3. Simulate the Deployment\n\nFirst, simulate the deployment to verify everything works:\n\n```bash\nsource .env && forge script script/DeployVaultV2WithMarketAdapter.s.sol \\\n  --fork-url \"$RPC_URL\" \\\n  --private-key \"$PRIVATE_KEY\" \\\n  -vvv\n```\n\nIn simulation mode (without `--broadcast`), the script will complete all deployment phases and gracefully skip the dead deposit if the deployer has no tokens.\n\n#### 4. Deploy the Morpho Vault V2\n\nRun the deployment script with `--broadcast` to execute on-chain:\n\n```bash\n# Without block explorer verification\nforge script script/DeployVaultV2WithMarketAdapter.s.sol \\\n  --rpc-url $RPC_URL \\\n  --private-key $PRIVATE_KEY \\\n  --broadcast\n```\n\nOr with verification on Etherscan:\n\n```bash\n# With verification on Etherscan\nforge script script/DeployVaultV2WithMarketAdapter.s.sol \\\n  --rpc-url $RPC_URL \\\n  --private-key $PRIVATE_KEY \\\n  --broadcast \\\n  --etherscan-api-key $ETHERSCAN_API_KEY \\\n  --verify\n```\n\nThe script will output the addresses of all deployed contracts and confirm each configuration step.\n\n### Testing Before Mainnet Deployment\n\nThe repository includes testing tools to help you validate your deployment:\n\n```bash\n# Run all tests on fork\nsource .env && forge test --fork-url \"$RPC_URL\" -vvv\n\n# Run specific test\nforge test --match-test test_FullDeploymentWithTimelocks -vvv\n```\n\n**Important**: Always test your deployment configuration on a testnet before deploying to mainnet.\n\n### Good practices\n\nThe script addresses the following good practices:\n\n| Good practices          | How Script Addresses It                                       |\n|-------------------------|---------------------------------------------------------------|\n| **Non-custodial Gates** | Phase 5: Gates abdicated (cannot be re-enabled)               |\n| **No Idle Liquidity**   | Phase 7: liquidityAdapter allocates deposits to market        |\n| **Dead Deposit**        | Phase 8: 1e9-1e12 wei deposited on behalf of 0xdead           |\n| **Vault Timelocks**     | Phase 9: Configures timelocks for vault functions (>= 3 days) |\n| **Adapter Timelocks**   | Phase 10: Configures adapter timelocks (burnShares >= 3 days) |\n| **Naming Restriction**  | Manual check: Name/symbol cannot contain \"morpho\"             |\n\n### Understanding the Deployment Steps\n\nThe `DeployVaultV2WithMarketAdapter.s.sol` script orchestrates a comprehensive deployment process. Here's what happens internally:\n\n#### Phase 1: Deploy Morpho Vault V2 Instance\n\n```solidity\n// Deploy Morpho Vault V2 using the factory\nbytes32 uniqueSalt = keccak256(abi.encodePacked(block.timestamp + gasleft()));\nVaultV2 deployedVaultV2 = VaultV2(\n    VaultV2Factory(factoryAddress).createVaultV2(\n        temporaryOwner,\n        underlyingAsset,\n        uniqueSalt\n    )\n);\n```\n\n#### Phase 2: Configure Temporary Permissions\n\n```solidity\n// Set broadcaster as temporary curator for configuration\nvault.setCurator(temporaryCurator);\n```\n\n#### Phase 3: Deploy MorphoMarketV1AdapterV2\n\n```solidity\n// Deploy MorphoMarketV1AdapterV2 using the adapter factory\nIMorphoMarketV1AdapterV2Factory factory = IMorphoMarketV1AdapterV2Factory(factoryAddress);\naddress adapterAddress = factory.createMorphoMarketV1AdapterV2(vaultV2Address);\n```\n\n#### Phase 4: Submit Timelocked Configuration Changes\n\n```solidity\n// Submit all configuration changes that will be timelocked\nvault.submit(abi.encodeCall(vault.setIsAllocator, (allocator, true)));\nvault.submit(abi.encodeCall(vault.setAdapterRegistry, (registry)));\n\nbytes memory adapterIdData = abi.encode(\"this\", adapter);\nvault.submit(abi.encodeCall(vault.addAdapter, (adapter)));\nvault.submit(abi.encodeCall(vault.increaseAbsoluteCap, (adapterIdData, type(uint128).max)));\nvault.submit(abi.encodeCall(vault.increaseRelativeCap, (adapterIdData, 1e18)));\n\n// Submit abdication for registry and gates (non-custodial requirement)\nvault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setAdapterRegistry.selector)));\nvault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setReceiveSharesGate.selector)));\nvault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setSendSharesGate.selector)));\nvault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setReceiveAssetsGate.selector)));\n```\n\n#### Phase 5: Execute Configuration and Gates Abdication\n\n```solidity\n// Since timelock is 0 initially, execute configurations immediately\nvault.setAdapterRegistry(registry);\nvault.setIsAllocator(allocator, true);\nvault.addAdapter(adapter);\n\nbytes memory adapterIdData = abi.encode(\"this\", adapter);\nvault.increaseAbsoluteCap(adapterIdData, type(uint128).max);\nvault.increaseRelativeCap(adapterIdData, 1e18);\n\n// Abdicate registry and gates (preserves non-custodial properties)\nvault.abdicate(IVaultV2.setAdapterRegistry.selector);\nvault.abdicate(IVaultV2.setReceiveSharesGate.selector);\nvault.abdicate(IVaultV2.setSendSharesGate.selector);\nvault.abdicate(IVaultV2.setReceiveAssetsGate.selector);\n```\n\n#### Phase 6: Set Final Role Assignments\n\n```solidity\n// Assign final roles to production addresses\nvault.setCurator(vaultCurator);\n\nif (vaultSentinel != address(0)) {\n    vault.setIsSentinel(vaultSentinel, true);\n}\n\nvault.setOwner(vaultOwner);\n```\n\n#### Phase 7: Configure Market and Liquidity Adapter\n\n```solidity\n// Look up MarketParams from Morpho and set liquidity adapter\nMarketParams memory marketParams = IMorpho(morpho).idToMarketParams(Id.wrap(marketId));\nbytes memory liquidityData = abi.encode(marketParams);\nvault.setLiquidityAdapterAndData(address(adapter), liquidityData);\n\n// Configure collateral token and market caps\nbytes memory collateralTokenIdData = abi.encode(\"collateralToken\", marketParams.collateralToken);\nvault.increaseAbsoluteCap(collateralTokenIdData, collateralTokenCap);\nvault.increaseRelativeCap(collateralTokenIdData, 1e18);\n\nbytes memory marketIdData = abi.encode(\"this/marketParams\", address(adapter), marketParams);\nvault.increaseAbsoluteCap(marketIdData, marketCap);\nvault.increaseRelativeCap(marketIdData, 1e18);\n```\n\n#### Phase 8: Execute Dead Deposit\n\n```solidity\n// Seed vault with initial liquidity to prevent inflation attacks\n// Amount depends on asset decimals: 1e9 for >= 10 decimals, 1e12 for <= 9 decimals\nIERC20(vault.asset()).approve(address(vault), depositAmount);\nvault.deposit(depositAmount, address(0xdead)); // Burned shares\n```\n\n#### Phase 9: Configure Vault Timelocks\n\n```solidity\n// Configure timelocks for vault functions (good practices: >= 3 days)\nbytes4[] memory selectors = new bytes4[](7);\nselectors[0] = IVaultV2.addAdapter.selector;\nselectors[1] = IVaultV2.increaseAbsoluteCap.selector;\nselectors[2] = IVaultV2.increaseRelativeCap.selector;\nselectors[3] = IVaultV2.setForceDeallocatePenalty.selector;\nselectors[4] = IVaultV2.abdicate.selector;\nselectors[5] = IVaultV2.removeAdapter.selector;\nselectors[6] = IVaultV2.increaseTimelock.selector; // MUST BE LAST!\n\nfor (uint256 i = 0; i < selectors.length; i++) {\n    vault.submit(abi.encodeCall(vault.increaseTimelock, (selectors[i], timelockDuration)));\n    vault.increaseTimelock(selectors[i], timelockDuration);\n}\n```\n\n#### Phase 10: Configure Adapter Timelocks\n\n```solidity\n// Configure timelocks for adapter functions (good practices: burnShares >= 3 days)\nbytes4[] memory selectors = new bytes4[](4);\nselectors[0] = IMorphoMarketV1AdapterV2.abdicate.selector;\nselectors[1] = IMorphoMarketV1AdapterV2.setSkimRecipient.selector;\nselectors[2] = IMorphoMarketV1AdapterV2.burnShares.selector;\nselectors[3] = IMorphoMarketV1AdapterV2.increaseTimelock.selector; // MUST BE LAST!\n\nfor (uint256 i = 0; i < selectors.length; i++) {\n    adapter.submit(abi.encodeCall(adapter.increaseTimelock, (selectors[i], timelockDuration)));\n    adapter.increaseTimelock(selectors[i], timelockDuration);\n}\n```\n\n## Method 3: Create a Vault Manually via Etherscan\n\nIf you prefer a manual approach without using the Curator App or deployment scripts, you can deploy a vault directly by interacting with the contracts on a block explorer like Etherscan.\n\nThis method requires deploying the vault directly via the `VaultV2` constructor. You will need to perform all the role assignment and configuration steps separately, as detailed in the [Manage Vault V2 Roles guide](/curate/tutorials-v2/roles/). This approach is more complex and error-prone than using the Curator App or deployment scripts.\n\n### Prerequisites\n\n- An Ethereum wallet (e.g., MetaMask) connected to the desired network.\n- The address of the ERC-20 token the vault will use as its `asset`.\n- The address you want to designate as the initial `owner`.\n\n### Step-by-Step Guide\n\n#### 1. Deploy a New VaultV2 Contract\n\nSince Vault V2 doesn't use a factory pattern, you'll need to deploy the contract directly. This typically requires using a development environment like Remix or Foundry.\n\nFor Remix:\n1. Copy the `VaultV2.sol` contract and its dependencies.\n2. Compile with Solidity 0.8.28.\n3. Deploy with constructor parameters:\n   - `_owner`: The initial owner address (ideally your multisig).\n   - `_asset`: The ERC-20 token address (e.g., USDC, WETH).\n\n#### 2. Verify the Contract\n\nAfter deployment, verify the contract on Etherscan to enable the `Write Contract` interface.\n\n#### 3. Configure the Vault\n\nOnce deployed and verified, you'll need to:\n1. Set up roles (see [Manage Vault V2 Roles](/curate/tutorials-v2/roles/)).\n2. Deploy and configure adapters (see [(De)List Adapters](/curate/tutorials-v2/listing-adapters/)).\n\n**Congratulations!** Your vault is now deployed. For a production-ready setup, we strongly recommend using the deployment script method as it ensures all components are properly configured."
  },
  "/tools/": {
    "title": "Introduction",
    "url": "https://docs.morpho.org/tools/",
    "section": "Tools",
    "content": "Many tools, part of the Morpho Stack, are available for any user, developers, researcher to build on top of the morpho protocol, and access any data.\n\n## Integrate\n\n    \n      Earn - Morpho Vaults\n      \n    Add yield-generating capabilities to your application.\n    More →\n  \n\n  \n      Borrow - Morpho Markets\n       \n    \n    \n      Enable borrowing functionality in your applications.\n    \n    \n      More →\n    \n\n## Use Tools\n\n### Offchain\n\n    \n      Morpho API\n      \n    Access data on Morpho users, markets, and more.\n    More →\n  \n\n  \n      Morpho SDKs\n      \n        \n      \n    \n    A suite of tools to interact with the Morpho ecosystem.\n    \n      More →\n    \n\n  \n      Morpho Subgraph\n      \n    \n    \n      Retrieve onchain data from Morpho contracts.\n    \n    \n      More →\n    \n\n  \n      Dune\n      \n        \n      \n    \n    For public shared data and analytics\n    \n      More →\n    \n\n### Onchain\n\n    \n      Public Allocator\n      \n    Provide on-demand liquidity to the protocol.\n    More →\n  \n\n## Discover Community Contributions\n\n    \n      Oracles\n      \n    Community-contributed oracle implementations and adapters.\n    More →\n  \n\n  \n      Liquidations\n      \n        \n      \n    \n    Community-contributed liquidation bot implementations.\n    \n      More →\n    \n\n## Build with Examples\n\n    \n      Paperclip OS\n      \n    \n    Complete application implementation with both earn and borrow functionality.\n    \n        Code (Earn & Borrow)\n        |\n        e.stopPropagation()}>Front End\n      →\n    \n  \n\n  \n      Fallback App\n      \n        \n      \n    \n    Emergency interface ensuring protocol accessibility during outages.\n    \n      \n        Code\n        |\n        e.stopPropagation()}>Front End\n      \n      →\n    \n  \n\n  \n      Lite App\n      \n        \n      \n    \n    Lightweight implementation for minimal resource usage.\n    \n    \n       Code\n              \n      →\n    \n\n  \n      Liquidation Bot\n      \n        \n      \n    \n    A simple, fast, and easily deployable liquidation bot for Morpho Market V1.\n    \n      \n        Code\n      \n      →\n    \n\n    \n      Indexer Template\n      \n        \n      \n    \n    A ready-to-use template for indexing Morpho protocol data with Ponder.\n    \n      \n        Code\n      \n      →"
  },
  "/tools/ai/llms/": {
    "title": "Using LLMs",
    "url": "https://docs.morpho.org/tools/ai/llms/",
    "section": "Tools",
    "content": "Morpho's documentation is available in LLM-friendly formats to help developers and AI agents integrate with Morpho faster.\n\n## Available Endpoints\n\n| Endpoint | Description |\n|---|---|\n| [llms.txt](https://docs.morpho.org/llms.txt) | Curated index of ~46 key pages with one-line descriptions. Start here. |\n| [llms-full.txt](https://docs.morpho.org/llms-full.txt) | All pages in clean markdown, organized by section. |\n| [llms-all.txt](https://docs.morpho.org/llms-all.txt) | All pages with code snippets inlined. Best for full context. |\n| [llms-pages.json](https://docs.morpho.org/llms-pages.json) | JSON mapping of URL path to `{title, section, content}`. |\n\n**Which file should I use?**\n\n- **Quick lookup** — Use `llms.txt` to find the right page, then fetch it individually.\n- **Full context** — Use `llms-all.txt` for complete documentation with all code examples resolved.\n- **Programmatic access** — Use `llms-pages.json` to look up specific pages by URL path.\n\n## Using with AI Code Editors\n\n### Cursor\n\n#### Navigate to `Cursor Settings` > `Features` > `Docs`\n\n#### Select \"Add new doc\" and paste the following URL:\n\n[https://docs.morpho.org/llms-all.txt](https://docs.morpho.org/llms-all.txt)\n\n#### Use @docs -> Morpho to reference Morpho's docs in your code.\n\n### Claude Code\n\nAdd Morpho docs as context by running:\n\n```bash\nclaude --add-docs https://docs.morpho.org/llms-all.txt\n```\n\n### Other Tools\n\nAny tool that supports custom documentation URLs can use:\n\n```\nhttps://docs.morpho.org/llms-all.txt\n```\n\nOr for a lighter-weight index:\n\n```\nhttps://docs.morpho.org/llms.txt\n```"
  },
  "/tools/community/": {
    "title": "Community Contributions page",
    "url": "https://docs.morpho.org/tools/community/",
    "section": "Tools",
    "content": "This page gather multiple community contributions.\nFind below the respective subject\n\n## Liquidations\n\nHere is the [liquidations contribution section page](/tools/community/liquidations/)\n\n## Oracles\n\nHere is the [Oracles contribution section page](/tools/community/oracles/)"
  },
  "/tools/offchain/": {
    "title": "Offchain Tools",
    "url": "https://docs.morpho.org/tools/offchain/",
    "section": "Tools",
    "content": "Explore the suite of offchain tools available for building on top of the Morpho protocol. These tools provide easy access to protocol data, analytics, and integration capabilities without requiring direct blockchain interaction.\n\n## Available Tools\n\n### API\nAccess comprehensive data on Morpho users, markets, and more through our REST API endpoints.\n\n### SDKs\nA suite of TypeScript SDKs designed to facilitate interaction with the Morpho ecosystem, supporting both Viem and Ethers.\n\n### Subgraphs\nQuery onchain data from Morpho contracts using GraphQL through our subgraph infrastructure.\n\n### Dune\nAccess Morpho protocol analytics and metrics through our Dune dashboard integration.\n\n## Get Started\n\nChoose the tool that best fits your development needs:\n\n- For real-time data access: **API**\n- For application development: **SDKs**\n- For complex data queries: **Subgraphs**\n- For analytics and reporting: **Dune**\n\nAll offchain tools are designed to work together seamlessly, allowing you to build comprehensive applications on top of the Morpho protocol."
  },
  "/tools/offchain/api/get-started/": {
    "title": "Morpho API",
    "url": "https://docs.morpho.org/tools/offchain/api/get-started/",
    "section": "Tools",
    "content": "The Morpho API provides a powerful, GraphQL-based interface for accessing a comprehensive range of onchain and offchain data from the Morpho ecosystem. It is designed for developers building applications, dashboards, bots, or any service that requires reliable data on Morpho Markets, Morpho Vaults, user positions, and more.\n\nThe Morpho API is provided as-is, without a Service Level Agreement (SLA). While we strive to maintain reliable service, availability and uptime are not guaranteed.\nWe recommend implementing appropriate fallback mechanisms in production applications and avoiding hard dependencies on API availability for critical operations.\n\nAn entire [API section](/tools/offchain/api/morpho) is dedicated to query examples; if you know what you are doing go there directly, otherwise read what's below\n\nThe Morpho API can evolve. Stay in touch with updates via the **[Changelog page here](https://help.morpho.org/en/collections/15838584-changelog)**.\n\n## Endpoints\n\nThe ecosystem uses two primary API endpoints:\n\n*   **Main GraphQL API**: For all data related to markets, vaults, and positions. You can explore the schema and run live queries in the [GraphQL Playground](https://api.morpho.org/graphql).\n*   **Rewards API**: A dedicated REST API for fetching data on reward programs, user eligibility, and distributions. See the [Rewards API Documentation](https://rewards.morpho.org/docs) for details.\n\n## Key Data & Features\n\n*   **Real-time & Historical Data**: Access both current state and historical timeseries data for markets and vaults.\n*   **Market & Vault Analytics**: Retrieve metrics like APYs, TVL, utilization, fees, and market allocations.\n*   **User Positions**: Fetch detailed information on supply, borrow, and collateral positions for any user.\n*   **Public Allocator Liquidity**: Query data on reallocatable liquidity available through the Public Allocator.\n\n## Supported Networks\n\nThe API provides data for fully supported deployments on networks including:\n\n*   **Ethereum** (Chain ID: 1)\n*   **Arbitrum** (Chain ID:42161)\n*   **Base** (Chain ID: 8453)\n*   **HyperEVM** (Chain ID: 999)\n*   **Katana** (Chain ID: 747474)\n*   **Monad** (Chain ID: 143)\n*   **Op Mainnet** (Chain ID: 10)\n*   **Polygon** (Chain ID: 137)\n*   **Unichain** (Chain ID: 130)\n*   **Stable** (Chain ID: 988)\n\n## Morpho API main rules\n\n### Maximum complexity of a GraphQL query\n\nA complexity score is associated with each query in the Morpho API.\n\nGraphQL complexity details:\n- **Max allowed complexity: 1,000,000**\n- Base cost per operation: 10\n- Each field adds cost; some fields declare explicit costs and/or multipliers.\n\nOne can verify its queries' complexity in https://api.morpho.org/graphql. The complexity number is returned as an extension.\n\nIf one of the query is above the threshold, you have the following alternatives:\n- **Trim the selection set**: keep only fields you actually use. Prefer cheap snapshots (state.*) over histories when possible.\n- **Lower fan-out**: reduce first (e.g., 25 or 50), then paginate.\n- **Split the work**: fetch a light list first (IDs + a few cheap fields), then run follow-up queries for heavy history on a subset.\n- **Tune multipliers**: for fields like currentIrmCurve(numberOfPoints: N), lower N.\n\n### Best Practices & Rate Limiting\n\nTo ensure reliable service for all users, **the API is subject to rate limiting: 5k/5min**. We strongly recommend implementing the following best practices in your integration:\n\n*   **Cache Responses**: Cache API query results on your backend to reduce redundant requests and improve your application's performance.\n*   **Request Only What You Need**: Structure your GraphQL queries to fetch only the data fields required for your use case.\n*   **Avoid Excessive Polling**: Design your application to fetch data efficiently, respecting API limits to prevent interruptions.\n\nThe `numberOfResults` parameter in the search root resolver is constrained to be within [0, 1000] (default value being 5).\n\n## Where to Find Query Examples\n\nThis page serves as a high-level overview. For detailed documentation and hands-on query examples, please refer to the dedicated sections below.\n\n### Comprehensive API Documentation\n\nFor a full list of available queries, schemas, and example use cases for each part of the protocol, explore these sections:\n\n*   [**Morpho Markets API**](/tools/offchain/api/morpho/)\n*   [**Morpho Vaults API**](/tools/offchain/api/morpho-vaults/)\n*   [**Public Allocator API**](/tools/offchain/api/public-allocator/)\n*   [**Rewards API**](/tools/offchain/api/rewards/)\n\n### Practical Integration Tutorials\n\nTo see how the API is used in practical integration scenarios, check out our step-by-step tutorials:\n\n*   **Integrating Earn Data**: See the [Get Data for Earn](/build/earn/tutorials/get-data) tutorial.\n*   **Integrating Borrow Data**: Follow the [Get Data for Borrow](/build/borrow/tutorials/get-data) guide.\n*   **Fetching Public Allocator Data**: Visit the [Trigger the Public Allocator](/build/borrow/tutorials/public-allocator) tutorial."
  },
  "/tools/offchain/api/morpho-vaults/": {
    "title": "Morpho Vaults",
    "url": "https://docs.morpho.org/tools/offchain/api/morpho-vaults/",
    "section": "Tools",
    "content": "## How to query Morpho Vaults Data thanks to the API?\n\nSelect the query you are interested in in the list below, and paste it into the GraphQL Playground: [https://api.morpho.org/graphql](https://api.morpho.org/graphql)\n\n## Discovery and Listing\n\n### Vaults List\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2s(first: 1000, where: { chainId_in: [1, 8453] }) {\n    items {\n      address\n      symbol\n      name\n      listed\n      asset {\n        id\n        address\n        decimals\n      }\n      chain {\n        id\n        network\n      }\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaults(first: 1000, where: { chainId_in: [1, 8453] }) {\n    items {\n      address\n      symbol\n      name\n      listed\n      asset {\n        id\n        address\n        decimals\n      }\n      chain {\n        id\n        network\n      }\n    }\n  }\n}\n```\n\n## Vault Metrics\n\n### Total Deposits & Assets\n\n#### All Vaults\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2s(first: 100) {\n    items {\n      address\n      totalAssets\n      totalAssetsUsd\n      totalSupply\n      liquidityUsd\n      idleAssetsUsd\n      }\n    }\n  }\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      state {\n        totalAssets\n        totalAssetsUsd\n        totalSupply\n      }\n    }\n  }\n}\n```\n\n#### Specific Vault\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    address\n     totalAssets\n      totalAssetsUsd\n      totalSupply\n      liquidity\n      liquidityUsd\n      idleAssetsUsd\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    state {\n      totalAssets\n      totalAssetsUsd\n      totalSupply\n    }\n    liquidity {\n      underlying\n      usd\n    }\n  }\n}\n```\n\n### APY (Native + Rewards)\n\n#### All Vaults\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      address\n      asset {\n        yield {\n          apr\n        }\n      }\n      avgApy\n      avgNetApy\n      performanceFee\n      managementFee\n      maxRate\n      rewards {\n        asset {\n          address\n          chain {\n            id\n          }\n        }\n        supplyApr\n        yearlySupplyTokens\n      }\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      asset {\n        yield {\n          apr\n        }\n      }\n      state {\n        apy\n        netApy\n        netApyWithoutRewards\n        avgApy\n        avgNetApy\n        dailyApy\n        dailyNetApy\n        weeklyApy\n        weeklyNetApy\n        monthlyApy\n        monthlyNetApy\n        rewards {\n          asset {\n            address\n            chain {\n              id\n            }\n          }\n          supplyApr\n          yearlySupplyTokens\n        }\n        allocation {\n          supplyAssets\n          supplyAssetsUsd\n          market {\n            uniqueKey\n            state {\n              rewards {\n                asset {\n                  address\n                  chain {\n                    id\n                  }\n                }\n                supplyApr\n                borrowApr\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n#### Specific Vault\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    address\n    asset {\n      yield {\n        apr\n      }\n    }\n    avgApy\n    avgNetApy\n    performanceFee\n    managementFee\n    maxRate\n    rewards {\n      asset {\n        address\n        chain {\n          id\n        }\n      }\n      supplyApr\n      yearlySupplyTokens\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    asset {\n      yield {\n        apr\n      }\n    }\n    state {\n      apy\n      netApy\n      netApyWithoutRewards\n      avgApy\n      avgNetApy\n      dailyApy\n      dailyNetApy\n      weeklyApy\n      weeklyNetApy\n      monthlyApy\n      monthlyNetApy\n      rewards {\n        asset {\n          address\n          chain {\n            id\n          }\n        }\n        supplyApr\n        yearlySupplyTokens\n      }\n      allocation {\n        supplyAssets\n        supplyAssetsUsd\n        market {\n          uniqueKey\n          state {\n            rewards {\n              asset {\n                address\n                chain {\n                  id\n                }\n              }\n              supplyApr\n              borrowApr\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n### Share Price (Token Value)\n\n#### All Vaults\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      address\n      totalSupply\n      totalAssets\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      state {\n        sharePrice\n        sharePriceUsd\n      }\n    }\n  }\n}\n```\n\nVault V2 responses do not expose a `sharePrice` field directly. Compute the share price offchain with `sharePrice = totalAssets / totalSupply` (and use the USD equivalents if you need the value in dollars). As discussed in this [section](/build/earn/tutorials/get-data#share-price-token-value), this formula is an approximation because the API returns raw totals rather than a pre-rounded share price.\n\n#### Specific Vault\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    totalAssets\n    totalSupply\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    state {\n      sharePrice\n      sharePriceUsd\n    }\n  }\n}\n```\n\n## Allocation & Strategy\n\nVault V2 allocation data is expressed via adapters, whereas Vault V1 allocations reference the underlying Morpho Markets V1. Keep that distinction in mind when mapping results.\n\n### Current Allocations\n\n#### All Vaults\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      address\n      totalAssetsUsd\n      totalAssets\n      totalSupply\n      adapters {\n        items {\n          address\n          assets\n          assetsUsd\n          type\n        }\n      }\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      state {\n        allocation {\n          market {\n            uniqueKey\n            loanAsset {\n              name\n            }\n            collateralAsset {\n              name\n            }\n            oracleAddress\n            irmAddress\n            lltv\n          }\n          supplyCap\n          supplyAssets\n          supplyAssetsUsd\n        }\n      }\n    }\n  }\n}\n```\n\n#### Specific Vault\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    totalAssetsUsd\n    totalAssets\n    totalSupply\n    adapters {\n      items {\n        address\n        assets\n        assetsUsd\n        type\n      }\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    state {\n      allocation {\n        market {\n          uniqueKey\n          loanAsset {\n            name\n          }\n          collateralAsset {\n            name\n          }\n          oracleAddress\n          irmAddress\n          lltv\n        }\n        supplyCap\n        supplyAssets\n        supplyAssetsUsd\n      }\n    }\n  }\n}\n```\n\n### Strategy: Vault Queues (Morpho Vaults V1)\n\n```graphql [All Vaults]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      state {\n        totalAssets\n        lastTotalAssets\n        allocation {\n          supplyQueueIndex\n          withdrawQueueIndex\n          market {\n            uniqueKey\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n```graphql [Specific Vault]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    state {\n      totalAssets\n      lastTotalAssets\n      allocation {\n        supplyQueueIndex\n        withdrawQueueIndex\n        market {\n          uniqueKey\n        }\n      }\n    }\n  }\n}\n```\n\n## Configuration & Curation\n\n### Vault Parameters\n\n#### All Vaults\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      address\n      name\n      listed\n      metadata {\n        description\n        forumLink\n        image\n      }\n      allocators {\n        allocator {\n          address\n        }\n      }\n      owner {\n        address\n      }\n      curators {\n        items {\n          addresses {\n            address\n          }\n        }\n      }\n      sentinels {\n        sentinel {\n          address\n        }\n      }\n      timelocks {\n        duration\n        selector\n        functionName\n      }\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaults(first: 100, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      name\n      listed\n      metadata {\n        description\n      }\n      allocators {\n        address\n      }\n      state {\n        owner\n        curator\n        guardian\n        timelock\n        curators {\n          name\n          socials {\n            type\n            url\n          }\n          image\n        }\n      }\n    }\n  }\n}\n```\n\n#### Specific Vault\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    address\n    name\n    listed\n    metadata {\n      description\n      forumLink\n      image\n    }\n    allocators {\n      allocator {\n        address\n      }\n    }\n    owner {\n      address\n    }\n    curators {\n      items {\n        addresses {\n          address\n        }\n      }\n    }\n    sentinels {\n      sentinel {\n        address\n      }\n    }\n    timelocks {\n      duration\n      selector\n      functionName\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaultByAddress(\n    address: \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n    chainId: 1\n  ) {\n    address\n    name\n    listed\n    metadata {\n      description\n    }\n    allocators {\n      address\n    }\n    state {\n      owner\n      curator\n      guardian\n      timelock\n      curators {\n         name\n        socials {\n          type\n          url\n          }\n        image\n      }\n    }\n  }\n}\n```\n\n### Risk Indicators\n\n#### Vault Warnings\n\na. Warning `type` can be:\n\n- unrecognized_deposit_asset,\n- unrecognized_vault_curator.\n- not_whitelisted.\n\nb. Warning `level` is either:\n\n- `YELLOW`,\n- `RED`.\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2s(first: 5) {\n    items {\n      name\n      warnings {\n        type\n        level\n      }\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaults {\n    items {\n      name\n      warnings {\n        type\n        level\n      }\n    }\n  }\n}\n```\n\nYou can read more about warnings in the dedicated section [here](/get-started/resources/app-ecosystem/#more-resources-below).\n\n### Vault Curation\n\n_Note: These curator-focused endpoints currently expose Vault V1 data._\n\n#### Current Vaults Pending Caps\n\n```graphql\nquery {\n  vaults {\n    items {\n      pendingCaps {\n        validAt\n        supplyCap\n        market {\n          uniqueKey\n        }\n      }\n    }\n  }\n}\n```\n\n#### Current Vaults Allocators\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2s(first: 10) {\n    items {\n      name\n      allocators {\n        allocator {\n          address\n        }\n      }\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaults(first: 10) {\n    items {\n      name\n      allocators {\n        address\n      }\n    }\n  }\n}\n```\n\n## Fee Wrapper\n\nA Fee Wrapper is a Vault V2 configured in a specific, constrained mode that enables distribution channels to add a fee layer on top of an existing Morpho Vault V2.\n\n### FeeWrapper List\n\n```graphql [Unique FeeWrapper]\nquery VaultV2ByAddress {\n  vaultV2ByAddress(\n    address: \"0xd4468EF3745c315949a97090eD27b3F73b9b7C02\"\n    chainId: 8453\n  ) {\n    type\n    address\n    name\n  }\n}\n```\n\n```graphql [All FeeWrappers]\nquery VaultV2s {\n  vaultV2s(skip: 0, first: 20, where: { type_in: [FeeWrapper] }) {\n    items {\n      address\n      name\n    }\n  }\n}\n```\n\n### FeeWrapper Exposure\n\n```graphql [Unique FeeWrapper]\nquery VaultV2ByAddress {\n  vaultV2ByAddress(\n    address: \"0xd4468EF3745c315949a97090eD27b3F73b9b7C02\"\n    chainId: 8453\n  ) {\n    type\n    adapters {\n      items {\n        type\n        address\n        ... on MorphoVaultV2Adapter {\n          address\n          innerVault {\n            address\n            name\n          }\n        }\n      }\n    }\n    historicalState {\n      sharePrice(options: {\n        startTimestamp: 1771015645\n        endTimestamp: 1771915645\n        interval: HOUR\n      }) {\n        x\n        y\n      }\n    }\n  }\n}\n```\n\n```graphql [All FeeWrappers]\nquery VaultV2s {\n  vaultV2s(skip: 0, first: 20, where: { type_in: [FeeWrapper] }) {\n    items {\n      type\n      address\n      adapters {\n        items {\n          type\n          address\n          ... on MorphoVaultV2Adapter {\n            address\n            innerVault {\n              address\n              name\n            }\n          }\n        }\n      }\n      historicalState {\n        sharePrice(options: {\n          startTimestamp: 1771015645\n          endTimestamp: 1771915645\n          interval: HOUR\n        }) {\n          x\n          y\n        }\n      }\n    }\n  }\n}\n```\n\n### FeeWrapper Yield\n\n```graphql [Unique FeeWrapper]\nquery VaultV2ByAddress {\n  vaultV2ByAddress(\n    address: \"0xd4468EF3745c315949a97090eD27b3F73b9b7C02\"\n    chainId: 8453\n  ) {\n    type\n    apy\n    avgNetApyExcludingRewards\n    avgNetApy\n    performanceFee\n    performanceFeeRecipient\n    managementFee\n    managementFeeRecipient\n    rewards {\n      asset {\n        symbol\n        address\n      }\n      supplyApr\n    }\n  }\n}\n```\n\n```graphql [All FeeWrappers]\nquery VaultV2s {\n  vaultV2s(skip: 0, first: 20, where: { type_in: [FeeWrapper] }) {\n    items {\n      type\n      address\n      apy\n      avgNetApyExcludingRewards\n      avgNetApy\n      performanceFee\n      performanceFeeRecipient\n      managementFee\n      managementFeeRecipient\n      rewards {\n        asset {\n          symbol\n          address\n        }\n        supplyApr\n      }\n    }\n  }\n}\n```\n\n## Position Tracking\n\n### Vault Depositors\n\n#### Specific Vault\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2ByAddress(\n    address: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\"\n    chainId: 1\n  ) {\n    positions(first: 10, skip:0) {\n      items {\n        user {\n          address\n        }\n        assets\n        assetsUsd\n        shares\n      }\n    }\n    totalSupply\n    asset {\n      address\n      symbol\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  vaultPositions(\n    first: 10\n    orderBy: Shares\n    orderDirection: Desc\n    where: { vaultAddress_in: [\"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"] }\n  ) {\n    items {\n      user {\n        address\n      }\n      state {\n        shares\n        assets\n        assetsUsd\n      }\n    }\n  }\n}\n```\n\n#### Set of Vaults (Morpho Vaults V1)\n\n_Vault V2 does not yet expose an equivalent batched depositor query._\n\n```graphql\nquery {\n  vaultPositions(\n    first: 10\n    orderBy: Shares\n    orderDirection: Desc\n    where: {\n      vaultAddress_in: [\n        \"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"\n        \"0x73e65DBD630f90604062f6E02fAb9138e713edD9\"\n      ]\n    }\n  ) {\n    items {\n      vault {\n        address\n      }\n      user {\n        address\n      }\n      state {\n        shares\n        assets\n        assetsUsd\n      }\n    }\n  }\n}\n```\n\n### User Positions\n\n#### User All Vaults Position\n\n```graphql\nquery GetUserVaultPositions($address: String!, $chainId: Int!) {\n  userByAddress(address: $address, chainId: $chainId) {\n    id\n    vaultV2Positions {\n      shares\n      vault {\n        address\n        symbol\n      }\n    }\n    vaultPositions {\n      state {\n        shares\n      }\n      vault {\n        address\n        symbol\n      }\n    }\n  }\n}\n```\n\n**Query Variables example:**\n\n```json\n{\n  \"address\": \"USER_ADDRESS\",\n  \"chainId\": 8453\n}\n```\n\n#### User Account Overview\n\n```graphql\nquery {\n  userByAddress(\n    chainId: 1\n    address: \"0x821880a3E2bac432d67E5155e72BB655Ef65fa5E\"\n  ) {\n    address\n    marketPositions {\n      market {\n        uniqueKey\n      }\n      borrowAssets\n      borrowAssetsUsd\n      supplyAssets\n      supplyAssetsUsd\n    }\n    vaultPositions {\n      vault {\n        address\n        name\n      }\n      assets\n      assetsUsd\n      shares\n    }\n    transactions {\n      hash\n      timestamp\n      type\n    }\n  }\n}\n```\n\n### Transaction History\n\n#### Specific Vault\n\n```graphql [Morpho Vaults V2]\nquery {\n  vaultV2transactions(\n    first: 10\n    skip: 0\n    where: { vaultAddress_in: \"0x04422053aDDbc9bB2759b248B574e3FCA76Bc145\" }\n  ) {\n    items {\n      vault {\n        address\n      }\n      type\n      shares\n      blockNumber\n      timestamp\n      txHash\n      txIndex\n    }\n  }\n}\n```\n\n```graphql [Morpho Vaults V1]\nquery {\n  transactions(\n    first: 10\n    orderBy: Timestamp\n    orderDirection: Desc\n    where: { vaultAddress_in: [\"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"] }\n  ) {\n    items {\n      blockNumber\n      hash\n      type\n      user {\n        address\n      }\n    }\n  }\n}\n```\n\n#### Latest Transactions (All Vaults)\n\n```graphql\nquery {\n  transactions(\n    first: 10\n    orderBy: Timestamp\n    orderDirection: Desc\n    where: { type_in: [MetaMorphoFee, MetaMorphoWithdraw, MetaMorphoWithdraw] }\n  ) {\n    items {\n      hash\n      timestamp\n      type\n      chain {\n        id\n        network\n      }\n      user {\n        address\n      }\n      data {\n        ... on VaultTransactionData {\n          shares\n          assets\n          vault {\n            address\n          }\n        }\n        ... on MarketTransferTransactionData {\n          shares\n          market {\n            uniqueKey\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n## Public Allocator\n\n### Configuration\n\n```graphql\nquery {\n  vaultByAddress(\n    address: \"0x38989BBA00BDF8181F4082995b3DEAe96163aC5D\"\n    chainId: 1\n  ) {\n    address\n    publicAllocatorConfig {\n      fee\n      flowCaps {\n        market {\n          uniqueKey\n        }\n        maxIn\n        maxOut\n      }\n    }\n  }\n}\n```\n\n### Reallocations\n\n```graphql\nquery {\n  vaultReallocates(\n   first: 10\n   skip: 0\n   orderBy: Timestamp\n   where: {vaultAddress_in:[\"0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB\"]}\n   orderDirection: Desc\n  ) {\n   items {\n    id\n    timestamp\n    hash\n    blockNumber\n    caller\n    shares\n    assets\n    type\n    vault {\n     id\n     chain {\n      id\n     }\n    }\n    market {\n     id\n     uniqueKey\n     lltv\n     oracleAddress\n     irmAddress\n     creationBlockNumber\n     loanAsset {\n      symbol\n     }\n     collateralAsset {\n      symbol\n     }\n    }\n   }\n   pageInfo {\n    countTotal\n    count\n    skip\n    limit\n   }\n  }\n }\n```\n\n## Historical Data\n\n### APY Historical State (Morpho Vaults V1)\n\n```graphql [All Vaults]\nquery VaultApys($options: TimeseriesOptions) {\n  vaults(first: 10, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      historicalState {\n        apy(options: $options) {\n          x\n          y\n        }\n        netApy(options: $options) {\n          x\n          y\n        }\n      }\n    }\n  }\n}\n```\n\n```graphql [Specific Vault]\nquery VaultApys($options: TimeseriesOptions) {\n  vaultByAddress(address: \"0x73e65DBD630f90604062f6E02fAb9138e713edD9\") {\n    address\n    historicalState {\n      apy(options: $options) {\n        x\n        y\n      }\n      netApy(options: $options) {\n        x\n        y\n      }\n    }\n  }\n}\n```\n\n**Query Variables:**\n\n```json\n{\n  \"options\": {\n    \"startTimestamp\": 1716249600,\n    \"endTimestamp\": 1716422400,\n    \"interval\": \"DAY\"\n  }\n}\n```\n\n### Historical Allocation (Morpho Vaults V1)\n\n```graphql [All Vaults]\nquery Vaults($options: TimeseriesOptions) {\n  vaults (first: 10, skip: 0, orderBy: TotalAssetsUsd, orderDirection: Desc) {\n    items {\n      address\n      name\n      historicalState {\n        allocation {\n          market {\n            uniqueKey\n          }\n          supplyAssets(options: $options) {\n            x\n            y\n          }\n          supplyAssetsUsd(options: $options)  {\n            x\n            y\n          }\n        }\n      } \n    }\n  }\n}\n```\n\n```graphql [Specific Vault]\nquery VaultApys($options: TimeseriesOptions) {\n  vaultByAddress(address: \"0x73e65DBD630f90604062f6E02fAb9138e713edD9\") {\n    address\n    historicalState {\n      allocation {\n        market {\n          uniqueKey\n        }\n        supplyAssets(options: $options) {\n          x\n          y\n        }\n        supplyAssetsUsd(options: $options) {\n          x\n          y\n        }\n      }\n    }\n  }\n}\n```\n\n**Query Variables:**\n\n```json\n{\n  \"options\": {\n    \"startTimestamp\": 1768211594,\n    \"endTimestamp\": 1768384394,\n    \"interval\": \"DAY\"\n  }\n}\n```"
  },
  "/tools/offchain/api/morpho/": {
    "title": "Morpho Markets",
    "url": "https://docs.morpho.org/tools/offchain/api/morpho/",
    "section": "Tools",
    "content": "## How to query Morpho Markets Data thanks to the API?\n\nSelect the query you are interested in in the list below, and paste it into the GraphQL Playground: [https://api.morpho.org/graphql](https://api.morpho.org/graphql)\n\nBy default, the Morpho API returns only the 100 first results and retrieve\ninformations on the Ethereum network.\n\n## Discovery and Listing\n\n### Markets List\n\n```graphql [All Markets]\nquery {\n  markets {\n    items {\n      uniqueKey\n      lltv\n      oracleAddress\n      irmAddress\n      loanAsset {\n        address\n        symbol\n        decimals\n      }\n      collateralAsset {\n        address\n        symbol\n        decimals\n      }\n      state {\n        borrowAssets\n        supplyAssets\n        fee\n        utilization\n      }\n    }\n  }\n}\n```\n\n```graphql [Listed Markets]\nquery {\n  markets(where: { listed: true }) {\n    items {\n      uniqueKey\n      listed\n      lltv\n      oracleAddress\n      irmAddress\n      loanAsset {\n        address\n        symbol\n        decimals\n      }\n      collateralAsset {\n        address\n        symbol\n        decimals\n      }\n      state {\n        borrowAssets\n        supplyAssets\n        fee\n        utilization\n      }\n    }\n  }\n}\n```\n\n### Market Parameters\n\n```graphql [All Markets]\nquery {\n  markets(\n    first: 100\n    orderBy: SupplyAssetsUsd\n    orderDirection: Desc\n    where: { chainId_in: [1, 8453] }\n  ) {\n    items {\n      uniqueKey\n      loanAsset { address }\n      collateralAsset { address }\n      lltv\n      irmAddress\n      oracleAddress\n    }\n  }\n}\n```\n\n```graphql [Specific Market]\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    uniqueKey\n    loanAsset { address }\n    collateralAsset { address }\n    lltv\n    irmAddress\n    oracleAddress\n  }\n}\n```\n\n## Market Metrics\n\n### Total Collateral, Borrow & Supply\n\n```graphql [All Markets]\nquery {\n    markets(\n      first: 100\n      orderBy: SupplyAssetsUsd\n      orderDirection: Desc\n      where: { chainId_in: [1, 8453] }\n    ) {\n      items {\n        uniqueKey\n        state {\n          collateralAssets\n          collateralAssetsUsd\n          borrowAssets\n          borrowAssetsUsd\n          supplyAssets\n          supplyAssetsUsd\n          liquidityAssets\n          liquidityAssetsUsd\n        }\n      }\n    }\n  }\n```\n\n```graphql [Specific Market]\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    state {\n      collateralAssets\n      borrowAssets\n      supplyAssets\n      liquidityAssets\n    }\n  }\n}\n```\n\n### Market APY (Native & Rewards)\n\n```graphql [All Markets]\nquery {\n  markets(\n    first: 100\n    orderBy: SupplyAssetsUsd\n    orderDirection: Desc\n    where: { chainId_in: [1, 8453] }\n  ) {\n    items {\n      uniqueKey\n      state {\n        borrowApy\n        avgBorrowApy\n        avgNetBorrowApy\n        supplyApy\n        avgSupplyApy\n        avgNetSupplyApy\n        rewards {\n          asset {\n            address\n            chain {\n              id\n            }\n          }\n          supplyApr\n          borrowApr\n        }\n      }\n    }\n  }\n}\n```\n\n```graphql [Specific Market]\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    state {\n      borrowApy\n      avgBorrowApy\n      avgNetBorrowApy\n      supplyApy\n      avgSupplyApy\n      avgNetSupplyApy\n      rewards {\n        supplyApr\n        borrowApr\n      }\n    }\n  }\n}\n```\n\n## Asset Information\n\n### Assets (Price & Yield)\n\n```graphql\nquery GetAssetsWithPrice {\n  assets(where: { symbol_in: [\"wstETH\", \"WETH\"], chainId_in: [1] }) {\n    items {\n      symbol\n      address\n      priceUsd\n      chain {\n        id\n        network\n      }\n    }\n  }\n}\n```\n\n- `priceUsd` is the current price of the asset in USD.\n- `oraclePriceUsd` is a deprecated field, please use priceUsd instead.\n\n## Position Tracking\n\n### User Positions\n\n#### User All Markets Position\n\n```graphql\nquery {\n  marketPositions(\n    first: 10,\n    orderBy: BorrowShares,\n    orderDirection: Desc\n    where: {\n      marketUniqueKey_in: [\"0x698fe98247a40c5771537b5786b2f3f9d78eb487b4ce4d75533cd0e94d88a115\"]\n    }\n  ) {\n    items {\n      user { address }\n      state {\n        collateral\n        borrowAssets\n        borrowAssetsUsd\n      }\n    }\n  }\n}\n```\n\n#### User Account Overview\n\n```graphql\nquery {\n  userByAddress(\n    chainId: 1\n    address: \"0x821880a3E2bac432d67E5155e72BB655Ef65fa5E\"\n  ) {\n    address\n    marketPositions {\n      market {\n        uniqueKey\n      }\n      borrowAssets\n      borrowAssetsUsd\n      supplyAssets\n      supplyAssetsUsd\n    }\n    vaultPositions {\n      vault {\n        address\n        name\n      }\n      assets\n      assetsUsd\n      shares\n    }\n    transactions {\n      hash\n      timestamp\n      type\n    }\n  }\n}\n```\n\n### All Market Positions\n\n```graphql\nquery {\n  marketPositions(\n    first: 10\n    orderBy: SupplyShares\n    orderDirection: Desc\n    where: {\n      marketUniqueKey_in: [\n        \"0x698fe98247a40c5771537b5786b2f3f9d78eb487b4ce4d75533cd0e94d88a115\"\n      ]\n    }\n  ) {\n    items {\n      market {\n        uniqueKey\n        loanAsset {\n          address\n          symbol\n        }\n        collateralAsset {\n          address\n          symbol\n        }\n      }\n      user {\n        address\n      }\n      state {\n        supplyShares\n        supplyAssets\n        supplyAssetsUsd\n        borrowShares\n        borrowAssets\n        borrowAssetsUsd\n        collateral\n        collateralUsd\n      }\n    }\n  }\n}\n```\n\n## Risk & Oracle Data\n\n### Oracle Data\n\nOracle data is returned if the oracle's type is `ChainlinkOracle` or `ChainlinkOracleV2`.\n`creationEvent` field is specific to `ChainlinkOracleV2` oracles.\nMore on oracles and `ChainlinkOracleV2` oracles in the oracle section [here](/learn/concepts/oracle/#morphochainlinkoraclev2-a-reference-implementation).\n\n#### All Markets\n\n```graphql\nquery Markets($first: Int, $skip: Int, $orderBy: MarketOrderBy, $orderDirection: OrderDirection, $where: MarketFilters) {\n  markets(first: $first, skip: $skip, orderBy: $orderBy, orderDirection: $orderDirection, where: $where) {\n    items {\n      uniqueKey\n      oracle {\n        address\n        type\n        data {\n          ... on MorphoChainlinkOracleData {\n            baseFeedOne {\n              address\n            }\n            baseFeedTwo {\n              address\n            }\n            baseOracleVault {\n              address\n            }\n            quoteFeedOne {\n              address\n            }\n            quoteFeedTwo {\n              address\n            }\n            scaleFactor\n            vaultConversionSample\n          }\n          ... on MorphoChainlinkOracleV2Data {\n            baseFeedOne {\n              address\n            }\n            baseFeedTwo {\n              address\n            }\n            baseOracleVault {\n              address\n            }\n            baseVaultConversionSample\n            quoteFeedOne {\n              address\n            }\n            quoteFeedTwo {\n              address\n            }\n            quoteOracleVault {\n              address\n            }\n            quoteVaultConversionSample\n            scaleFactor\n          }\n        }\n        creationEvent {\n          txHash\n          timestamp\n          blockNumber\n        }\n      }\n    }\n  }\n}\n```\n\nWith the following `variables` as example:\n\n```json\n{\n  \"first\": 100,\n  \"skip\": 0,\n  \"orderBy\": \"SupplyAssetsUsd\",\n  \"orderDirection\": \"Desc\",\n  \"where\": {\n    \"chainId_in\": [\n      1,\n      8453\n    ],\n    \"listed\": true\n  }\n}\n```\n\n#### Specific Market\n\n```graphql\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    uniqueKey\n    oracle {\n      address\n      type\n      creationEvent {\n        txHash\n        timestamp\n        blockNumber\n      }\n      data {\n        ... on MorphoChainlinkOracleV2Data {\n          baseFeedOne {\n            address\n          }\n          baseFeedTwo {\n            address\n          }\n          baseOracleVault {\n            address\n          }\n          baseVaultConversionSample\n          quoteFeedOne {\n            address\n          }\n          quoteFeedTwo {\n            address\n          }\n          quoteOracleVault {\n            address\n          }\n          quoteVaultConversionSample\n          scaleFactor\n        }\n        ... on MorphoChainlinkOracleData {\n          baseFeedOne {\n            address\n          }\n          baseFeedTwo {\n            address\n          }\n          baseOracleVault {\n            address\n          }\n          quoteFeedOne {\n            address\n          }\n          quoteFeedTwo {\n            address\n          }\n          scaleFactor\n          vaultConversionSample\n        }\n      }\n    } \n  }\n}\n```\n\n### Liquidations\n\n```graphql\nquery {\n  transactions(\n    where: {\n      marketUniqueKey_in: [\n        \"0x49bb2d114be9041a787432952927f6f144f05ad3e83196a7d062f374ee11d0ee\"\n        \"0x093d5b432aace8bf6c4d67494f4ac2542a499571ff7a1bcc9f8778f3200d457d\"\n      ]\n      type_in: [MarketLiquidation]\n    }\n  ) {\n    items {\n      blockNumber\n      hash\n      type\n      user {\n        address\n      }\n      data {\n        ... on MarketLiquidationTransactionData {\n          seizedAssets\n          repaidAssets\n          seizedAssetsUsd\n          repaidAssetsUsd\n          badDebtAssetsUsd\n          liquidator\n          market {\n            uniqueKey\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n### Market Warnings\n\n```graphql\nquery {\n  markets {\n    items {\n      uniqueKey\n      warnings {\n        type\n        level\n      }\n    }\n  }\n}\n```\n\n## Integration\n\n### Vault Listing\n\n```graphql\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\"\n    chainId: 8453\n  ) {\n    uniqueKey\n    supplyingVaults {\n      address\n      symbol\n      metadata {\n        description\n      }\n    }\n  }\n}\n```\n\n## Historical Data\n\nThe `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).\n\n### How to use the historicalState variables\n\nHere are the available variables when using an `historicalState` query:\n\n- `startTimestamp`: beginning of the historical data in UNIX timestamp format,\n- `endTimestamp`: end of the historical data in UNIX timestamp format,\n- `interval`: interval of the historical data points (`YEAR`, `QUARTER`, `MONTH`, `WEEK`, `DAY`, `HOUR`).\nInputting these variables is not mandatory but it is advised to specify them to control the specific data returned.\n\nIf no variables are specified, the default values will be:\n\n- `startTimestamp`: 0,\n- `endTimestamp`: infinity,\n- `interval`: will adjust according to `startTimestamp` and `endTimestamp` to return around 50 data points.\n\nNote that the `historicalState` field is not accessible through the (multiple) markets(...) and vaults(...) list queries. Historical data is only available through individual market or vault queries like `market(id: \"\")`, `marketByUniqueKey`, `vault(id: \"\")` or `vaultByAddress`.\n\nBelow you will find examples of `historicalData` queries.\n\n### Historical APYs\n\n```graphql\nquery MarketByUniqueKey($uniqueKey: String!, $chainId: Int, $options: TimeseriesOptions) {\n  marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {\n    historicalState {\n      borrowApy(options: $options) {\n        x\n        y\n      }\n      supplyApy(options: $options) {\n        x\n        y\n      }\n    }\n  }\n}\n```\n\nWith the following `variables`:\n\n```json\n{\n  \"uniqueKey\": \"0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836\",\n  \"chainId\": 8453,\n  \"options\": {\n    \"startTimestamp\": 1755420554,\n    \"endTimestamp\": 1755506954,\n    \"interval\": \"HOUR\"\n  }\n}\n```\n\n### Historical Market States\n\n```graphql\nquery MarketApys($options: TimeseriesOptions) {\n  marketByUniqueKey(\n    uniqueKey: \"0x608929d6de2a10bacf1046ff157ae38df5b9f466fb89413211efb8f63c63833a\"\n  ) {\n    uniqueKey\n    historicalState {\n      supplyAssetsUsd(options: $options) {\n        x\n        y\n      }\n      borrowAssetsUsd(options: $options) {\n        x\n        y\n      }\n    }\n  }\n}\n```\n\nWith the following `variables`:\n\n```json\n\"variables\": {\n\"startTimestamp\": 1707749700,\n\"endTimestamp\": 1708354500,\n\"interval\": HOUR,\n}\n```\n\n### Historical Asset Price\n\n```graphql\nquery {\n  wstETHWeeklyPriceUsd: assetByAddress(\n    address: \"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0\"\n    chainId: 1\n  ) {\n    historicalPriceUsd(\n      options: {\n        startTimestamp: 1707749700\n        endTimestamp: 1708354500\n        interval: HOUR\n      }\n    ) {\n      x\n      y\n    }\n  }\n}\n```\n\nAll queries sent for `assetByAddress`, `marketByUniqueKey` and `vaultByAddress` should include the `chainId` parameter.\n\n## Advanced Features\n\n### Paging, Ordering & Filtering\n\n```graphql\nquery {\n  markets(\n    first: 3\n    skip: 1\n    orderBy: Lltv\n    orderDirection: Desc\n    where: {\n      collateralAssetAddress_in: [\"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\"]\n    }\n  ) {\n    pageInfo {\n      count\n      countTotal\n    }\n    items {\n      uniqueKey\n      lltv\n      collateralAsset {\n        symbol\n      }\n      loanAsset {\n        symbol\n      }\n    }\n  }\n}\n```"
  },
  "/tools/offchain/api/public-allocator/": {
    "title": "Public Allocator",
    "url": "https://docs.morpho.org/tools/offchain/api/public-allocator/",
    "section": "Tools",
    "content": "## How to query Public Allocator's Data thanks to the API?\n\nSelect the query you are interested in in the list below, and paste it into the GraphQL Playground: [https://api.morpho.org/graphql](https://api.morpho.org/graphql)\n\n## Basic Queries\n\n### Public Allocator address\n\n```graphql\nquery {\n  publicAllocators {\n    items {\n      address\n      creationBlockNumber\n      morphoBlue {\n        address\n        chain {\n          id\n          network\n        }\n      }\n    }\n  }\n}\n```\n\n### Total reallocatable liquidity\n\nReallocations necessary to reach this number\n\n```graphql\nquery {\n  marketByUniqueKey(\n    uniqueKey: \"0xe7e9694b754c4d4f7e21faf7223f6fa71abaeb10296a4c43a54a7977149687d2\"\n    chainId: 1\n  ) {\n    reallocatableLiquidityAssets\n    state {\n      liquidityAssets\n    }\n    publicAllocatorSharedLiquidity {\n      assets\n      vault {\n        address\n        name\n      }\n      allocationMarket {\n        uniqueKey\n      }\n    }\n  }\n}\n```\n\n### Market's Available liquidity\n\nAvailable liquidity of a market taking account for the public Allocator.\n\n```graphql\nquery MarketByUniqueKey($uniqueKey: String!, $chainId: Int) {\n  marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {\n    reallocatableLiquidityAssets\n    state {\n      liquidityAssets\n    }\n    publicAllocatorSharedLiquidity {\n      assets\n      vault {\n        address\n        name\n      }\n      withdrawMarket {\n        uniqueKey\n      }\n    }\n  }\n}\n```\n\nwith the following variables:\n\n```graphql\n{\n  \"uniqueKey\": \"0xb8fc70e82bc5bb53e773626fcc6a23f7eefa036918d7ef216ecfb1950a94a85e\",\n  \"chainId\": 1\n}\n```\n\nMarket's Available liquidity is `liquidityAssets` (the market liquidity) + `reallocatableLiquidityAssets` (what can be reallocated from other markets).\n`reallocatableLiquidityAssets` being the sum of `publicAllocatorSharedLiquidity.assets`\n\n### Reallocations that occurred for a Morpho Vault\n\n```graphql\nquery {\n  publicAllocatorReallocates(\n    where: { vaultAddress_in: [\"0xBEEf050ecd6a16c4e7bfFbB52Ebba7846C4b8cD4\"] }\n  ) {\n    items {\n      timestamp\n      assets\n      type\n      vault {\n        address\n      }\n      market {\n        uniqueKey\n      }\n    }\n  }\n}\n```\n\n### Config of the Public Allocator for a Morpho Vault\n\n```graphql\nquery {\n  vaultByAddress(\n    address: \"0x38989BBA00BDF8181F4082995b3DEAe96163aC5D\"\n    chainId: 1\n  ) {\n    address\n    publicAllocatorConfig {\n      fee\n      flowCaps {\n        market {\n          uniqueKey\n        }\n        maxIn\n        maxOut\n      }\n    }\n  }\n}\n```"
  },
  "/tools/offchain/api/rewards/": {
    "title": "Rewards",
    "url": "https://docs.morpho.org/tools/offchain/api/rewards/",
    "section": "Tools",
    "content": "## Endpoints\n\nThere are several endpoints to get information about rewards:\n\n1. Morpho API: https://api.morpho.org/graphql\n2. Rewards API: https://rewards.morpho.org/docs\n3. Merkl API: https://api.merkl.xyz/docs (external)\n\nYou can read more about Rewards integration in your product in the dedicated section [here](/build/rewards/get-started).\n\n## Rewards API\n\nThe rewards distribution, previously handled via the Morpho rewards stack, has been migrated to the Merkl stack.\n\nThe rewards API only supports the Morpho rewards stack and will not return details of new Merkl campaigns but will still return call data for claims at this point.\nIntegrators will need to claim future MORPHO rewards and third parties rewards from Merkl's contracts directly.\n\nFollowing the above, we invite any Morpho rewards integrators to also check the following sections:\n- How to [Fetch Rewards Data](/build/rewards/tutorials/fetch-rewards-data).\n- How to [Integrate Rewards Claim](/build/rewards/tutorials/claim-rewards)\n- How to [Integrate Rewards Display](/build/rewards/tutorials/integrate-display)\n\nRewards API endpoint: https://rewards.morpho.org/docs\n\n### All Rewards for a User\n\nThis endpoint returns all rewards at the current timestamp on all chains for one user.\n\nhttps://rewards.morpho.org/docs#tag/users/GET/v1/users/{user}/rewards\n\n```http\nGET /v1/users/[Address]/rewards\n```\n\nExample:\n\n```\nhttps://rewards.morpho.org/v1/users/0x0ec553110e53122d1226646670a8475D4C8E6F04/rewards\n```\n\nHere is part of what the above example returns, specific to a rewards program (the endpoint can return several rewards programs for the same user depending on his eligibility).\nFor each rewards program, you will get:\n\n- The accruing rewards: `\"claimable_next\"`\n- The claimable rewards: `\"claimable_now\"`\n- The already claimed rewards: `\"claimed\"`\n- The sum of the above: `\"total\"`\n\n```\n[...]\n    {\n      \"user\": \"0x0ec553110e53122d1226646670a8475D4C8E6F04\",\n      \"type\": \"uniform-reward\",\n      \"asset\": {\n        \"id\": \"0x58D97B57BB95320F9a05dC918Aef65434969c2B2-1\",\n        \"address\": \"0x58D97B57BB95320F9a05dC918Aef65434969c2B2\",\n        \"chain_id\": 1\n      },\n      \"program_id\": \"0x5068269e48209fcd731fa6e02c54646871431970ea8eaca4c5b56ba1bc34afad\",\n      \"amount\": {\n        \"total\": \"115631364898103632676\",\n        \"claimable_now\": \"22676259927164556632\",\n        \"claimable_next\": \"1688912463745536463\",\n        \"claimed\": \"91266192507193539581\"\n      }\n    }\n[...]\n```\n\n### All Distributions for a User\n\nThis endpoint returns all distributions on all chains for one user.\n\nhttps://rewards.morpho.org/docs#tag/users/GET/v1/users/{user}/distributions\n\n```http\nGET /v1/users/[Address]/distributions\n```\n\nExample:\n\n```\nhttps://rewards.morpho.org/v1/users/0x0ec553110e53122d1226646670a8475D4C8E6F04/distributions\n```\n\nThe `\"claimable\"` amount retrieved for a specific `distributor` (URD) is what has been pushed onchain at the tree level to the URD making this user eligible to rewards up to this amount since inception. This amount is the sum of claimed and unclaimed rewards for a specific asset on a specific distributor.\n\nThis is used to claim rewards at contract level as detailed [here](/build/rewards/tutorials/claim-rewards).\n\n### All Programs\n\nThis endpoint returns all programs on all chains.\n\nhttps://rewards.morpho.org/docs#tag/programs/GET/v1/programs\n\n```http\nGET /v1/programs\n```\n\nExample:\n\n```\nhttps://rewards.morpho.org/v1/programs\n```\n\n### State of rewards distribution\n\nThis endpoint returns all rewards distribution on all chains. This gives a dynamic state of the rewards distributed on Morpho (claimed and unclaimed) and it is updated every 24 hours at 00:00:00 UTC.\n\nhttps://rewards.morpho.org/docs#tag/rewards/GET/v1/rewards/stats\n\n```\nhttps://rewards.morpho.org/v1/rewards/stats\n```\n\n## Morpho API\n\nMorpho API endpoint: https://api.morpho.org/graphql\n\n### Morpho markets rewards\n\n```graphql\n{\n  markets(orderBy: SupplyAssetsUsd, orderDirection: Desc) {\n    items {\n      uniqueKey\n      state {\n        rewards {\n          supplyApr\n          borrowApr\n          asset {\n            address\n            chain {\n              id\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n### Morpho Vaults rewards received through Vault programs\n\n```graphql\n{\n  vaults(where: { chainId_in: [8453] }) {\n    items {\n      state {\n        rewards {\n          asset {\n            address\n            chain {\n              id\n            }\n          }\n          yearlySupplyTokens\n          supplyApr\n        }\n      }\n    }\n  }\n}\n```\n\n### Morpho Vaults rewards per allocated market\n\n```graphql\n{\n  marketPositions(\n    where: { userAddress_in: [\"0xEbFA750279dEfa89b8D99bdd145a016F6292757b\"] }\n  ) {\n    items {\n      supplyAssets\n      market {\n        uniqueKey\n        loanAsset {\n          name\n          symbol\n        }\n        collateralAsset {\n          name\n          symbol\n        }\n        lltv\n        oracleAddress\n        irmAddress\n        state {\n          rewards {\n            asset {\n              address\n              chain {\n                id\n              }\n            }\n            supplyApr\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n### Morpho Vaults rewards\n\nTo retrieve the rewards that a vault inherit, not only you have to check the rewards of the vault, but also the one inherited form the allocated markets:\n\n```graphql\nquery VaultByAddress($address: String!, $chainId: Int) {\n  vaultByAddress(address: $address, chainId: $chainId) {\n    address\n    state {\n      rewards {\n        asset {\n          address\n          name\n          chain {\n            id\n          }\n        }\n        supplyApr\n      }\n      allocation {\n        market {\n          uniqueKey\n          state {\n            rewards {\n              supplyApr\n              asset {\n                address\n                chain {\n                  id\n                }\n              }\n            }\n          }\n        }\n        supplyAssetsUsd\n      }\n    }\n    chain {\n      id\n    }\n  }\n}\n```\n\nWith the following variables:\n\n```graphql\n{\n  \"address\": \"0x9aB2d181E4b87ba57D5eD564D3eF652C4E710707\",\n  \"chainId\": 8453\n}\n```\n\nYou can then compute the overall Vault rewards following [the Morpho Vault rewards computation](/build/earn/tutorials/get-data#apy-native--rewards).\n\n Explanation of Fields\n\n- `supplyApr`: The annual percentage rate for supplying tokens, available if the reward token is priced.\n- `borrowApr`: The annual percentage rate for borrowing tokens, available if the reward token is priced.\n\nFor any questions on how to integrate the data, feel free to message Morpho via the chatbox on **[help.morpho.org](https://help.morpho.org)**."
  },
  "/tools/offchain/dune/": {
    "title": "Dune",
    "url": "https://docs.morpho.org/tools/offchain/dune/",
    "section": "Tools",
    "content": "[Dune](https://dune.com/home) defines itself as the Crypto's Data Hub.\n\nIt is a platform that provides comprehensive data and analytics for the cryptocurrency space. It offers access to community dashboards, allowing users to track metrics for DeFi, NFTs, and various crypto projects. It provides data infrastructure to Web3 teams, supporting multiple blockchains and offering tools for data analysis, integration, and application development.\n\nMultiple open source dashboards are provided below:\n\n## High-level dashboards\n\n- [GMorpho Dashboard](https://dune.com/morpho/gmorpho-dashboard)\n- [Morpho protocol](https://dune.com/morpho/multichain-activity)\n\n## Domain specific dashboards\n\n- [Morpho Migrations](https://dune.com/morpho/morpho-migration)\n- [Coinbase Onchain Borrowing & Lending](https://dune.com/morpho/coinbase-onchain-lending-borrowing)\n- [Vault Performance](https://dune.com/morpho/single-vault-performance)\n- [Vault Curators](https://dune.com/morpho/vaults-curators-analysis)\n- [Morpho Credit Risk](https://dune.com/morpho/morpho-credit-risk)\n- [Morpho Liquidations](https://dune.com/morpho/morpho-liquidation)\n\nIf you want to be displayed here, please reach out via the chatbox on **[help.morpho.org](https://help.morpho.org)**."
  },
  "/tools/offchain/sdks/get-started/": {
    "title": "Morpho SDKs",
    "url": "https://docs.morpho.org/tools/offchain/sdks/get-started/",
    "section": "Tools",
    "content": "The Morpho Software Development Kits (SDKs) are a comprehensive suite of TypeScript packages designed to streamline development on the Morpho protocol. Whether you're building a full-featured DeFi application, a liquidation bot, or a simple data dashboard, these SDKs provide the tools you need to interact with Morpho's onchain and offchain ecosystems efficiently.\n\nThe SDKs are built with a modular, framework-agnostic core and offer powerful integrations for modern tools like **Viem** and **Wagmi**.\n\nAn entire [SDK section](/tools/offchain/sdks/blue-sdk/) is dedicated; if you know what you are doing go there directly, otherwise read what's below\n\n## The SDK Stack\n\nThe SDKs are organized into logical layers, allowing you to pick and choose the packages that best fit your needs.\n\n## Core Packages\n\nThese framework-agnostic packages form the foundation of the Morpho SDK ecosystem.\n\n*   **`@morpho-org/blue-sdk`**: The heart of the stack. Defines core entity classes like `Market`, `Vault`, and `Position`, and handles essential offchain computations.\n*   **`@morpho-org/simulation-sdk`**: A powerful engine for simulating user interactions like supplying, borrowing, or depositing into vaults before executing them onchain.\n*   **`@morpho-org/blue-api-sdk`**: A GraphQL client for fetching data directly from the [Morpho API](/tools/offchain/api/get-started/), complete with types and an Apollo cache controller.\n\n## Viem Integration Packages\n\nThese packages augment the core SDKs with Viem-based fetchers for seamless onchain interaction.\n\n*   **`@morpho-org/blue-sdk-viem`**: Extends `@morpho-org/blue-sdk` with methods to fetch live market and position data from the blockchain using Viem.\n*   **`@morpho-org/liquidity-sdk-viem`**: Simplifies calculations for available liquidity, including funds accessible via the Public Allocator.\n*   **`@morpho-org/liquidation-sdk-viem`**: Provides utilities to build robust, Viem-based liquidation bots.\n\n## Wagmi (React) Integration Packages\n\nDesigned for frontend developers, these packages provide React hooks for fetching Morpho data in your application.\n\n*   **`@morpho-org/blue-sdk-wagmi`**: A set of Wagmi hooks for fetching Morpho-related entities.\n*   **`@morpho-org/simulation-sdk-wagmi`**: Wagmi hooks for fetching and managing simulation states in a React environment.\n\n## Get Started\n\nReady to build?\n\n*   **Explore the full list of SDKs** in our [SDKs Introduction](/tools/offchain/sdks/get-started/).\n*   **Dive into the source code** on the [Morpho SDKs GitHub Repository](https://github.com/morpho-org/sdks).\n*   **Get in touch** via the chatbox on **[help.morpho.org](https://help.morpho.org)**."
  },
  "/tools/offchain/subgraphs/": {
    "title": "Morpho Subgraphs",
    "url": "https://docs.morpho.org/tools/offchain/subgraphs/",
    "section": "Tools",
    "content": "## Introduction\n\nThe Morpho Subgraphs provide a powerful and efficient way to access and retrieve data from the Morpho Protocol using GraphQL. These subgraphs index onchain data for all Morpho Markets and Morpho Vaults, making it easy for developers to track protocol activity, user positions, and other key analytics without needing to process raw blockchain data directly.\n\nThe subgraphs follow the [Messari Schema standard for Lending protocols](https://github.com/messari/subgraphs/blob/master/schema-lending.graphql), ensuring a familiar and standardized data structure. Note that some entity names may differ from Morpho's internal naming to align with this standard.\n\n## Disclaimer: Open-Source and Community Maintained\n\nThe Morpho Subgraphs are open-source and maintained by the community. The source code is available in the [morpho-blue-subgraph repository on GitHub](https://github.com/morpho-org/morpho-blue-subgraph).\n\nPlease be aware that Morpho Association does not provide official support for these subgraphs. Developers are encouraged to understand the code and use it at their own discretion.\n\n## Accessing the Subgraphs\n\nTo query the subgraphs, you need a basic understanding of GraphQL. All subgraphs are accessible through The Graph's decentralized network.\n\n1.  **Explore in the Playground**: You can find all official deployments on [The Graph Explorer](https://thegraph.com/explorer/profile/0x84d3e4ee550dd5f99e76a548ac59a6be1c8dcf79?view=Subgraphs). Select a subgraph and use the \"Playground\" tab to write and test queries directly in your browser.\n\n2.  **Programmatic Access (API Key)**: For use in applications or scripts, you must generate an API key from [The Graph Studio](https://thegraph.com/studio/apikeys/). Add this key to the query URL provided on each subgraph's explorer page.\n\nSubgraph Studio users start on a free plan, which is sufficient for most development and testing purposes. For more details on pricing and query limits, refer to [The Graph's official documentation](https://thegraph.com/docs).\n\n## Subgraph Deployments\n\nHere is a list of the official subgraph deployments across various networks:\n\n-   [Ethereum Mainnet](https://thegraph.com/explorer/subgraphs/8Lz789DP5VKLXumTMTgygjU2xtuzx8AhbaacgN5PYCAs)\n-   [Base](https://thegraph.com/explorer/subgraphs/71ZTy1veF9twER9CLMnPWeLQ7GZcwKsjmygejrgKirqs)\n-   [Arbitrum](https://thegraph.com/explorer/subgraphs/XsJn88DNCHJ1kgTqYeTgHMQSK4LuG1LR75339QVeQ26)\n-   [Corn](https://thegraph.com/explorer/subgraphs/4SswjwWRyBryaEBwzHfwayEpJWRS9f7xvsGC5kE6govQ)\n-   [Fraxtal](https://thegraph.com/explorer/subgraphs/CDFzHFQTXj1ryFgA8KpkUuv6qu3Jk6fLG7kzdpuCe95g)\n-   [Hemi](https://thegraph.com/explorer/subgraphs/2JZScBV6sD7BdoU9JBAwYPrbzUarPGGz9P1xVWFQxmdX)\n-   [Ink](https://thegraph.com/explorer/subgraphs/7pezYZCEJVBbZbbkjLFcPo3hdVUxUv8skF2FqGibRcfk)\n-   [MODE](https://thegraph.com/explorer/subgraphs/341uEcvH1UAzWETvVB974Au1YR3MksJdf2jhjuHXDLQ7)\n-   [OP Mainnet](https://thegraph.com/explorer/subgraphs/5y8d3K3vVCR7r5YwANGCjupLc3hUge54XvhYMEq3Jmq1)\n-   [Polygon POS](https://thegraph.com/explorer/subgraphs/EhFokmwryNs7qbvostceRqVdjc3petuD13mmdUiMBw8Y)\n-   [Scroll](https://thegraph.com/explorer/subgraphs/Aic7prLAxhtipUEbLu5BhDDWf4LssT9n3DG4fT9yCRqm)\n-   [Sonic](https://thegraph.com/explorer/subgraphs/J2THmwKHrTLKT9HPZNwZ69NkJ7WSbtLKz7pUQZW1Z1Qc)\n-   [Unichain](https://thegraph.com/explorer/subgraphs/ESbNRVHte3nwhcHveux9cK4FFAZK3TTLc5mKQNtpYgmu)\n\n## Query Examples\n\n### Morpho Market Examples\n\n#### 1. `BorrowAPY`\n\nThis query retrieves the annualized borrow rate for the top 100 markets.\n\n```graphql\n{\n  interestRates(\n    first: 100\n    where: { side: BORROWER }\n    orderBy: market__totalValueLockedUSD\n    orderDirection: desc\n  ) {\n    id\n    rate\n    side\n  }\n}\n```\n\nThe returned `rate` is an annualized value. To get the APY, you can use the formula: `BorrowAPY = e^(rate) - 1`.\n\n#### 2. `SupplyAPY`\n\nThis query retrieves the annualized supply rate for the top 100 markets.\n\n```graphql\n{\n  interestRates(\n    first: 100\n    where: { side: LENDER }\n    orderBy: market__totalValueLockedUSD\n    orderDirection: desc\n  ) {\n    id\n    rate\n    side\n  }\n}\n```\n\nSimilarly, the `SupplyAPY` can be calculated as `e^(rate) - 1`.\n\n#### 3. `Market Data`\n\nThis query fetches comprehensive data for the top 1000 markets by TVL.\n\n```graphql\n{\n  markets(first: 1000, orderBy: totalValueLockedUSD, orderDirection: desc) {\n    id\n    name\n    isActive\n    inputToken {\n      name\n    }\n    borrowedToken {\n      name\n      symbol\n    }\n    totalValueLockedUSD\n    totalBorrowBalanceUSD\n    totalDepositBalanceUSD\n    cumulativeBorrowUSD\n    cumulativeDepositUSD\n    maximumLTV\n    liquidationThreshold\n    liquidationPenalty\n  }\n}\n```\n\n#### 4. `Positions Data`\n\nThis query retrieves all positions for the first 1000 accounts.\n\n```graphql\n{\n  accounts(first: 1000) {\n    id\n    positionCount\n    openPositionCount\n    positions {\n      id\n      market {\n        id\n      }\n      asset {\n        id\n      }\n      side\n      isCollateral\n      balance\n    }\n  }\n}\n```\n\n### Morpho Vault Examples\n\n#### 1. Vault-Specific Data\n\nThis query fetches detailed configuration data for a specific Morpho Vault.\n\n```graphql\n{\n  metaMorphos(where: { id: \"0xbeef02e5e13584ab96848af90261f0c8ee04722a\" }) {\n    id\n    name\n    symbol\n    owner {\n      id\n    }\n    curator {\n      id\n    }\n    fee\n    asset {\n      id\n    }\n    supplyQueue {\n      market {\n        id\n      }\n    }\n    withdrawQueue {\n      market {\n        id\n      }\n    }\n    timelock\n  }\n}\n```\n\n## Questions\n\nIf you have any questions or need further assistance, please don't hesitate to reach out via the chatbox on **[help.morpho.org](https://help.morpho.org)**."
  },
  "/tools/onchain/public-allocator/": {
    "title": "Public Allocator",
    "url": "https://docs.morpho.org/tools/onchain/public-allocator/",
    "section": "Tools",
    "content": "The Public Allocator is a powerful onchain tool that solves liquidity fragmentation across isolated markets. For developers, it provides a mechanism to programmatically move liquidity on-demand, ensuring a user's borrow transaction can be fulfilled even if the target market initially has insufficient funds.\n\nThis creates a user experience similar to a single, deep liquidity pool while retaining the risk-isolated benefits of Morpho's market design.\n\n**Before you start**\nFor a full conceptual overview of what the Public Allocator is and why it's beneficial, please review the **[Public Allocator Concepts page](/learn/concepts/public-allocator/)**.\n\n## Core Integration: `reallocateTo`\n\nThe primary function for interacting with the Public Allocator is `reallocateTo`. This function pulls assets from multiple source markets within a vault and supplies them to a single destination market in one atomic transaction.\n\n### Function Signature\n\n```solidity\nfunction reallocateTo(\n    address vault,\n    Withdrawal[] calldata withdrawals,\n    MarketParams calldata supplyMarketParams\n) external payable;\n```\n\n### Parameters\n\n-   **`vault`**: The address of the MetaMorpho vault containing the liquidity.\n-   **`withdrawals`**: An array of `Withdrawal` structs, each specifying a source market and an amount to withdraw.\n-   **`supplyMarketParams`**: A `MarketParams` struct defining the single destination market where all withdrawn funds will be deposited.\n\n### Important Requirements\n\nTo successfully call `reallocateTo`, you must adhere to the following rules:\n\n-   **Sorted Withdrawals**: The `withdrawals` array **must be sorted in ascending order by market ID**.\n-   **Pay the Fee**: The transaction must be sent with the correct `fee` in gas token (E.g Ethereum: in ETH ) as `msg.value`. You can query this fee by calling the `fee(vaultAddress)` view function on the Public Allocator contract. Note: This fee is set and collected by the vault curator, not by Morpho. The curator can set it to 0.\n-   **Respect Flow Caps**: The withdrawal and supply amounts must not exceed the `maxOut` and `maxIn` flow caps configured by the vault curator for each market.\n-   **Valid Markets**: All source and destination markets must be enabled in the vault's configuration.\n-   **No Self-Supply**: The destination market (`supplyMarketParams`) cannot be included in the `withdrawals` array.\n\n### Example: Solidity Integration\n\nHere is a simplified example of how you might construct and call `reallocateTo` within a smart contract.\n\n```solidity\n// Assuming IPublicAllocator and IMetaMorpho interfaces are available\nIPublicAllocator publicAllocator = IPublicAllocator(PA_ADDRESS);\nIMetaMorpho vault = IMetaMorpho(VAULT_ADDRESS);\n\n// 1. Check prerequisites\nrequire(vault.isAllocator(address(publicAllocator)), \"PA: Not an allocator\");\nuint256 requiredFee = publicAllocator.fee(address(vault));\n\n// 2. Prepare withdrawal parameters (must be sorted by market ID)\nWithdrawal[] memory withdrawals = new Withdrawal[](2);\n\n// Withdrawal from Market A (e.g., Idle Market)\nwithdrawals[0] = Withdrawal({\n    marketParams: marketAParams, // MarketParams for Market A\n    amount: 70 * 1e18\n});\n\n// Withdrawal from Market B (e.g., wstETH Market)\n// The ID of Market B must be greater than the ID of Market A\nwithdrawals[1] = Withdrawal({\n    marketParams: marketBParams, // MarketParams for Market B\n    amount: 800 * 1e18\n});\n\n// 3. Define the destination market\nMarketParams memory supplyMarketParams = rETHMarketParams; // MarketParams for rETH Market\n\n// 4. Execute the reallocation\npublicAllocator.reallocateTo{value: requiredFee}(\n    address(vault),\n    withdrawals,\n    supplyMarketParams\n);\n```\n\n## Recommended Integration Flow\n\nFor a robust dApp integration, the onchain `reallocateTo` call should be the final step in a flow that uses offchain data to ensure success.\n\n#### 1. Check Target Market Liquidity\n\nFirst, check if the user's borrow can be fulfilled by the target market's existing liquidity. If so, no reallocation is needed.\n\n#### 2. Query for Reallocatable Liquidity\n\nIf more liquidity is required, use the **[Morpho API](#api-data-endpoints)** to query the `publicAllocatorSharedLiquidity` for the target market. This will return a list of all source markets across all vaults that can provide liquidity.\n\n#### 3. Simulate and Build Transaction\n\nUsing the data from the API, construct the `withdrawals` array. It is highly recommended to use the **Morpho SDKs** to simulate the transaction before asking the user to sign. This verifies that flow caps are respected and the call will succeed.\n\n#### 4. Bundle and Execute\n\nFor the best user experience, bundle the `reallocateTo` call with the user's `borrow` call into a single transaction using a **Morpho Bundler**. This ensures atomicity: if the reallocation fails, the entire operation (including the borrow) reverts, preventing failed transactions for the user.\n\n**Reference Implementation**\nA complete, working script demonstrating this flow with the Morpho API and SDKs is available on GitHub. This is the best starting point for your integration.\n\n**[View the Public Allocator Integration Script](https://github.com/morpho-org/public-allocator-scripts/blob/main/scripts/api/apiPublicAllocatorSimulated.ts)**\n\n## Key Resources\n\n| Resource                             | Link                                                               | Description                                                                                             |\n| ------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |\n| **Step-by-Step Tutorial**            | **[/build/borrow/tutorials/public-allocator/](/build/borrow/tutorials/public-allocator/)** | A practical guide on how to trigger a reallocation, including an Etherscan walkthrough.               |\n| **Contract Addresses**               | **[/get-started/resources/addresses/](/get-started/resources/addresses/)** | Official addresses for the Public Allocator contract on all supported chains.                         |\n| **Solidity Specs & Errors**          | **[/get-started/resources/contracts/public-allocator/](/get-started/resources/contracts/public-allocator/)** | Detailed contract specifications, function descriptions, and a table of common error messages. |\n| **API & Data Endpoints**             | **[/tools/offchain/api/](/tools/offchain/api/get-started/)** | How to query GraphQL for flow caps, fees, and available reallocatable liquidity.                           |"
  }
}