> For the complete documentation index, see [llms.txt](https://docs.moonwell.fi/moonwell/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.moonwell.fi/moonwell/developers/protocol/oev/morpho-markets.md).

# Morpho Markets

The `ChainlinkOEVMorphoWrapper` is used for liquidations in Morpho Blue isolated lending markets. Unlike the core market wrapper, this variant receives **underlying tokens** (not mTokens) as collateral and supports slippage protection via `maxRepayAmount`.

## Key Differences from Core Markets

| Aspect                | Core (ChainlinkOEVWrapper) | Morpho (ChainlinkOEVMorphoWrapper)        |
| --------------------- | -------------------------- | ----------------------------------------- |
| Market type           | Moonwell Core (mToken)     | Morpho Blue isolated                      |
| Collateral received   | mTokens                    | Underlying tokens                         |
| Market identification | mToken addresses           | `MarketParams` struct                     |
| Slippage protection   | Fixed repay amount         | `maxRepayAmount` parameter                |
| Excess return         | N/A                        | Unused loan tokens returned automatically |

## Function Signature

```solidity
function updatePriceEarlyAndLiquidate(
    MarketParams memory marketParams,
    address borrower,
    uint256 seizedAssets,
    uint256 maxRepayAmount
) external
```

| Parameter        | Type           | Description                                                |
| ---------------- | -------------- | ---------------------------------------------------------- |
| `marketParams`   | `MarketParams` | Morpho market identification struct                        |
| `borrower`       | `address`      | The underwater borrower to liquidate                       |
| `seizedAssets`   | `uint256`      | Amount of collateral to seize                              |
| `maxRepayAmount` | `uint256`      | Maximum loan tokens willing to repay (slippage protection) |

### MarketParams Struct

```solidity
struct MarketParams {
    address loanToken;       // Token being borrowed (e.g. USDC)
    address collateralToken; // Token used as collateral (e.g. xWELL)
    address oracle;          // Must use this OEV wrapper as BASE_FEED_1
    address irm;             // Interest rate model
    uint256 lltv;            // Liquidation loan-to-value ratio
}
```

## Liquidation Flow

```
┌─────────────────┐     ┌────────────────────────────┐     ┌─────────────────┐
│   Liquidator    │────▶│  ChainlinkOEVMorphoWrapper │────▶│   Morpho Blue   │
└─────────────────┘     └────────────────────────────┘     └─────────────────┘
        │                           │                              │
        │  1. Transfer max loan     │                              │
        │     tokens                │                              │
        │──────────────────────────▶│                              │
        │                           │  2. Update cachedRoundId     │
        │                           │                              │
        │                           │  3. Approve & call liquidate │
        │                           │─────────────────────────────▶│
        │                           │                              │
        │                           │  4. Receive collateral       │
        │                           │     tokens                   │
        │                           │◀─────────────────────────────│
        │                           │                              │
        │  5. Return excess loan    │                              │
        │     tokens                │                              │
        │◀──────────────────────────│                              │
        │                           │                              │
        │  6. Receive collateral    │  7. Send protocol fee        │
        │     (repay + bonus)       │     to feeRecipient          │
        │◀──────────────────────────│                              │
```

## Solidity Example

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

struct MarketParams {
    address loanToken;
    address collateralToken;
    address oracle;
    address irm;
    uint256 lltv;
}

interface IChainlinkOEVMorphoWrapper {
    function updatePriceEarlyAndLiquidate(
        MarketParams memory marketParams,
        address borrower,
        uint256 seizedAssets,
        uint256 maxRepayAmount
    ) external;
}

contract MorphoOEVLiquidator {
    IChainlinkOEVMorphoWrapper public oevWrapper;

    constructor(address _oevWrapper) {
        oevWrapper = IChainlinkOEVMorphoWrapper(_oevWrapper);
    }

    function liquidate(
        MarketParams calldata marketParams,
        address borrower,
        uint256 seizedAssets,
        uint256 maxRepayAmount
    ) external {
        address loanToken = marketParams.loanToken;

        // 1. Transfer max loan tokens from caller
        IERC20(loanToken).transferFrom(msg.sender, address(this), maxRepayAmount);

        // 2. Approve OEV wrapper
        IERC20(loanToken).approve(address(oevWrapper), maxRepayAmount);

        // 3. Execute liquidation - excess tokens returned automatically
        oevWrapper.updatePriceEarlyAndLiquidate(
            marketParams,
            borrower,
            seizedAssets,
            maxRepayAmount
        );

        // 4. Collateral tokens (not mTokens) are now in this contract
        uint256 collateralBalance = IERC20(marketParams.collateralToken).balanceOf(
            address(this)
        );
        IERC20(marketParams.collateralToken).transfer(msg.sender, collateralBalance);

        // 5. Return any remaining loan tokens
        uint256 loanBalance = IERC20(loanToken).balanceOf(address(this));
        if (loanBalance > 0) {
            IERC20(loanToken).transfer(msg.sender, loanBalance);
        }
    }
}
```

{% hint style="warning" %}
The market's Morpho oracle must have this OEV wrapper as `BASE_FEED_1`. The contract verifies this requirement and will revert if the oracle is not configured correctly.
{% endhint %}

## Revert Conditions

| Condition                  | Error Message                                                             |
| -------------------------- | ------------------------------------------------------------------------- |
| `borrower == address(0)`   | `"ChainlinkOEVMorphoWrapper: borrower cannot be zero address"`            |
| `seizedAssets == 0`        | `"ChainlinkOEVMorphoWrapper: seized assets cannot be zero"`               |
| `maxRepayAmount == 0`      | `"ChainlinkOEVMorphoWrapper: max repay amount cannot be zero"`            |
| Wrong oracle `BASE_FEED_1` | `"ChainlinkOEVMorphoWrapper: oracle must be the same as the base feed 1"` |
| Chainlink price ≤ 0        | `"Chainlink price cannot be lower or equal to 0"`                         |
| Incomplete round           | `"Round is in incompleted state"`                                         |
| Stale Chainlink data       | `"Stale price"`                                                           |
| Actual repay > max         | `"ChainlinkOEVMorphoWrapper: repaid amount exceeds maximum"`              |
| Invalid loan token price   | `"ChainlinkOEVMorphoWrapper: invalid loan token price"`                   |

## Events

| Event                            | Parameters                                                                                                         |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `PriceUpdatedEarlyAndLiquidated` | `address indexed borrower, uint256 seizedAssets, uint256 repaidAssets, uint256 protocolFee, uint256 liquidatorFee` |
| `FeeRecipientChanged`            | `address oldFeeRecipient, address newFeeRecipient`                                                                 |
| `LiquidatorFeeBpsChanged`        | `uint16 oldLiquidatorFeeBps, uint16 newLiquidatorFeeBps`                                                           |
| `MaxRoundDelayChanged`           | `uint256 oldMaxRoundDelay, uint256 newMaxRoundDelay`                                                               |
| `MaxDecrementsChanged`           | `uint256 oldMaxDecrements, uint256 newMaxDecrements`                                                               |

{% hint style="info" %}
Note: The Morpho wrapper's `PriceUpdatedEarlyAndLiquidated` event has **different parameters** than the core wrapper - it uses `seizedAssets` and `repaidAssets` instead of `repayAmount`, `mTokenCollateral`, and `mTokenLoan`.
{% endhint %}

## Deployed Contracts

### Base - ChainlinkOEVMorphoWrapper

| Asset    | Address                                                                                                                 |
| -------- | ----------------------------------------------------------------------------------------------------------------------- |
| WELL/USD | [`0xAEeE6335f50e1f8aF924DF0742b1879C9761F5f5`](https://basescan.org/address/0xAEeE6335f50e1f8aF924DF0742b1879C9761F5f5) |

#### WELL/USDC Morpho Market Parameters (Base)

```solidity
MarketParams memory params = MarketParams({
    loanToken: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913,       // USDC
    collateralToken: 0xA88594D404727625A9437C3f886C7643872296AE, // xWELL
    oracle: 0x71FBaD6c2200C8A5B89380f9B6bb8a35d411c852,          // Morpho Chainlink Oracle
    irm: 0x46415998764C29aB2a25CbeA6254146D50D22687,             // Adaptive Curve IRM
    lltv: 625000000000000000                                     // 62.5%
});
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.moonwell.fi/moonwell/developers/protocol/oev/morpho-markets.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
