> 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/core-markets.md).

# Core Markets

The `ChainlinkOEVWrapper` is used for liquidations in Moonwell's Core lending markets (mToken markets). The liquidator transfers loan tokens to the wrapper, which unlocks the fresh price, executes the liquidation, and splits the seized collateral (mTokens) between the liquidator and the protocol.

## Function Signature

```solidity
function updatePriceEarlyAndLiquidate(
    address borrower,
    uint256 repayAmount,
    address mTokenCollateral,
    address mTokenLoan
) external nonReentrant
```

| Parameter          | Type      | Description                                   |
| ------------------ | --------- | --------------------------------------------- |
| `borrower`         | `address` | The underwater borrower to liquidate          |
| `repayAmount`      | `uint256` | Amount of loan tokens to repay                |
| `mTokenCollateral` | `address` | The mToken market for collateral being seized |
| `mTokenLoan`       | `address` | The mToken market for the loan being repaid   |

{% hint style="warning" %}
The OEV wrapper must be registered as the Chainlink feed for the **underlying collateral** token in Moonwell's ChainlinkOracle. The contract derives the underlying token via `MErc20Storage(mTokenCollateral).underlying()` and verifies `chainlinkOracle.getFeed(underlyingCollateral.symbol()) == address(this)`. Use the correct wrapper for each collateral asset.
{% endhint %}

## Liquidation Flow

```
┌─────────────────┐     ┌──────────────────────┐     ┌─────────────────┐
│   Liquidator    │────▶│  ChainlinkOEVWrapper │────▶│  Moonwell Pool  │
│                 │     │                      │     │   (Comptroller) │
└─────────────────┘     └──────────────────────┘     └─────────────────┘
        │                        │                           │
        │  1. Transfer loan      │                           │
        │     tokens             │                           │
        │───────────────────────▶│                           │
        │                        │  2. Update cachedRoundId  │
        │                        │     (unlock fresh price)  │
        │                        │                           │
        │                        │  3. Execute liquidation   │
        │                        │─────────────────────────▶│
        │                        │                           │
        │                        │  4. Receive mToken        │
        │                        │     collateral            │
        │                        │◀─────────────────────────│
        │                        │                           │
        │  5. Receive mToken     │  6. Send protocol fee    │
        │     (repay + bonus)    │     to feeRecipient      │
        │◀───────────────────────│                           │
```

## Collateral Distribution

After liquidation, the seized mTokens are split:

* **Liquidator receives**: Repayment value + (Profit × `liquidatorFeeBps` / 10000)
* **Protocol receives**: Remaining profit (Profit × (10000 − `liquidatorFeeBps`) / 10000)

**Example** with `liquidatorFeeBps = 4000` (40%):

|                                   | Amount                          |
| --------------------------------- | ------------------------------- |
| Repayment                         | 1,000 USDC                      |
| Collateral seized (10% incentive) | 1,100 USDC                      |
| Gross profit                      | 100 USDC                        |
| Liquidator bonus (40%)            | 40 USDC                         |
| **Liquidator total**              | **1,040 USDC worth of mTokens** |
| **Protocol total**                | **60 USDC worth of mTokens**    |

## Solidity Example

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

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

interface IChainlinkOEVWrapper {
    function updatePriceEarlyAndLiquidate(
        address borrower,
        uint256 repayAmount,
        address mTokenCollateral,
        address mTokenLoan
    ) external;
}

contract OEVLiquidator {
    IChainlinkOEVWrapper public oevWrapper;

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

    function liquidate(
        address borrower,
        uint256 repayAmount,
        address mTokenCollateral,
        address mTokenLoan,
        address loanToken
    ) external {
        // 1. Transfer loan tokens from caller
        IERC20(loanToken).transferFrom(msg.sender, address(this), repayAmount);

        // 2. Approve OEV wrapper to spend loan tokens
        IERC20(loanToken).approve(address(oevWrapper), repayAmount);

        // 3. Execute liquidation with early price access
        oevWrapper.updatePriceEarlyAndLiquidate(
            borrower,
            repayAmount,
            mTokenCollateral,
            mTokenLoan
        );

        // 4. mToken collateral is now in this contract
        // Transfer to caller or redeem for underlying
    }
}
```

## Revert Conditions

The following conditions will cause `updatePriceEarlyAndLiquidate` to revert:

| Condition                        | Error Message                                                     |
| -------------------------------- | ----------------------------------------------------------------- |
| `repayAmount == 0`               | `"ChainlinkOEVWrapper: repay amount cannot be zero"`              |
| `borrower == address(0)`         | `"ChainlinkOEVWrapper: borrower cannot be zero address"`          |
| `mTokenCollateral == address(0)` | `"ChainlinkOEVWrapper: mToken collateral cannot be zero address"` |
| `mTokenLoan == address(0)`       | `"ChainlinkOEVWrapper: mToken loan cannot be zero address"`       |
| Wrong wrapper for collateral     | `"ChainlinkOEVWrapper: chainlink oracle feed does not match"`     |
| Chainlink price ≤ 0              | `"Chainlink price cannot be lower or equal to 0"`                 |
| Incomplete round                 | `"Round is in incompleted state"`                                 |
| Stale Chainlink data             | `"Stale price"`                                                   |
| No collateral seized             | `"ChainlinkOEVWrapper: collateral seized cannot be zero"`         |
| Liquidation failed               | `"ChainlinkOEVWrapper: liquidation failed"`                       |

## Events

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

## Deployed Contracts

### Base - ChainlinkOEVWrapper

| Asset | Address                                                                                                                 |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| WETH  | [`0xeb083d234ec636A10325ea42bCbbE09Aa56d1547`](https://basescan.org/address/0xeb083d234ec636A10325ea42bCbbE09Aa56d1547) |

#### WETH Core Market Addresses (Base)

| Contract               | Address                                                                                                                 |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| WETH                   | `0x4200000000000000000000000000000000000006`                                                                            |
| Moonwell WETH (mToken) | [`0x628ff693426583D9a7FB391E54366292F509D457`](https://basescan.org/address/0x628ff693426583D9a7FB391E54366292F509D457) |

### OP Mainnet - ChainlinkOEVWrapper

| Asset | Address                                                                                                                            |
| ----- | ---------------------------------------------------------------------------------------------------------------------------------- |
| WETH  | [`0x531f69127bB04Ebb0Fd321b8092d34a4C2B4E0f1`](https://optimistic.etherscan.io/address/0x531f69127bB04Ebb0Fd321b8092d34a4C2B4E0f1) |

#### WETH Core Market Addresses (OP Mainnet)

| Contract               | Address                                                                                                                            |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| WETH                   | `0x4200000000000000000000000000000000000006`                                                                                       |
| Moonwell WETH (mToken) | [`0xb4104C02BBf4E9be85AAa41a62974E4e28D59A33`](https://optimistic.etherscan.io/address/0xb4104C02BBf4E9be85AAa41a62974E4e28D59A33) |


---

# 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/core-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.
