# Offer Pre-Liquidation

> The offer-based pre-liquidation band between the safe LTV and the liquidation LTV, introduced in v1.3.0.

Starting with v1.3.0, Morpho Borrow Positions open an earlier, privileged liquidation band **between the safe LTV and the liquidation LTV**. In this band, trusted proposers post standing, timelocked **offers** — a quantity of collateral in exchange for a quantity of debt repayment — and liquidators consume them through the same `preLiquidate` entrypoint used for proportional pre-liquidation.

This lets the protocol de-risk a position *before* it reaches the liquidation LTV, on terms the protocol itself proposes, while the proportional path above the liquidation LTV remains unchanged.

## Three LTV Bands

Every Morpho Borrow Position is configured with two immutable thresholds: a **safe LTV** and a **liquidation LTV** (`safeLtv < liquidationLtv ≤ market LLTV`). A `preLiquidate` call accrues interest, then dispatches on the position's current LTV:

| Band | Behavior |
|------|----------|
| `LTV ≤ safeLtv` | Healthy — `preLiquidate` reverts with `PositionHealthy()`. |
| `safeLtv < LTV ≤ liquidationLtv` | **Offer band** — standing offers can be consumed. If none are fillable, the call reverts with `NoConsumableOffer()`. |
| `LTV > liquidationLtv` | **Proportional pre-liquidation** — the [existing mechanism](/liquidator/pre-liquidation/), behaviorally unchanged. |

```mermaid
graph LR
    H["Healthy<br/>LTV ≤ safe LTV"] -->|"Safe LTV"| O["Offer Band<br/>offers consumable"]
    O -->|"Liquidation LTV"| P["Proportional<br/>Pre-Liquidation"]
    P -->|"Market LLTV"| M["Morpho<br/>Liquidation"]

    style H fill:#16a34a,color:#fff
    style O fill:#ca8a04,color:#fff
    style P fill:#ea580c,color:#fff
    style M fill:#dc2626,color:#fff
```

The safe LTV is also the operational ceiling for the Position Manager: borrows and collateral withdrawals must leave the position at or below it. So a position only enters the offer band through interest accrual or price movement — exactly the situations where a controlled, early de-risking is valuable.

## Offers

An offer is an *authorization*, not an escrow — no tokens are held by the offer itself. It states that up to `remainingCollateral` collateral tokens may be seized in exchange for repaying up to `remainingDebtShares` of the position's Morpho borrow shares, at the fixed ratio implied by those two amounts. Offers are partially fillable.

Key properties:

- **Debt is denominated in Morpho borrow shares**, not loan-token units. As interest accrues, a fixed share amount converts to more loan tokens, so an offer's effective price gradually worsens for the liquidator. An offer that drifts below profitability is simply skipped, and eventually expires.
- **Timelocked** — an offer becomes consumable only at `activeAt = proposalTime + timelock`. The timelock is fixed at proposal time, so a later configuration change can never shorten an existing offer's veto window.
- **Bounded** — at most 32 offers can be live on a position at once, and an offer can live at most 365 days past its `activeAt`.

### Roles and the BorrowOffersRegistry

Offer roles and configuration live on a single protocol-wide **BorrowOffersRegistry** (deployed behind an ERC1967 proxy; see [Deployments](/protocol/deployments/)), shared by every borrow position:

| Actor | Power |
|-------|-------|
| **Proposer** (`PROPOSER_ROLE`) | Post offers on any position; revoke its own offers. |
| **Guardian** (`GUARDIAN_ROLE`) | Revoke any offer on any position — the veto during the timelock window, and the kill switch for a bad standing offer. |
| **Registry owner** | Grants/revokes roles, tunes configuration, and holds both powers above. |

Configuration is keyed by **collateral token**, not by position: the economics of a veto window and a bonus floor follow the collateral's volatility and liquidity rather than the individual position.

| Setting | Default | Bounds | Change semantics |
|---------|---------|--------|------------------|
| **Offer timelock** | 15 minutes | `MIN_OFFER_TIMELOCK` (15 min) to `MAX_OFFER_TIMELOCK` (7 days) | Itself timelocked: a new value becomes effective only after the collateral's current timelock elapses. Applies to future proposals only |
| **Minimum offer bonus** | `DEFAULT_MIN_OFFER_BONUS_BPS` (100 bps) | 0 to `MAX_MIN_OFFER_BONUS_BPS` (1000 bps) | Effective immediately |

A collateral that was never configured reads the floor timelock and the default bonus, so the offer band is **open by default** rather than disabled.

The minimum bonus is not timelocked because it can only ever gate a consumption: it can skip a fill, never force or enlarge one. But that cuts both ways. Lowering the floor instantly re-admits standing offers that it had been gating, with no fresh veto window, since their terms were fixed at proposal and they already served their timelock. A guardian who wants an offer gone must **revoke it**, not rely on the floor to keep it unconsumable.

### Proposing and Revoking

```solidity
// Proposer or registry owner. activeAt is fixed here from the collateral's
// current effective timelock; expiresAt must be within 365 days of it.
function proposeOffer(uint128 collateral, uint128 debtShares, uint40 expiresAt)
    external returns (uint8 id);

// Proposers may revoke their own offers at any time; guardians and the
// registry owner may revoke any offer. Batched, and all-or-nothing.
function revokeOffers(uint8[] calldata ids) external;
```

An offer's `activeAt` is stamped at proposal time and never moves, so a later timelock change cannot retroactively shorten a veto window that is already running.

## Consuming Offers

Liquidators use the **same `preLiquidate` signature** as proportional pre-liquidation — same inputs (exactly one of `seizedAssets` or `repaidShares` non-zero), same return values, and the same `onPreLiquidate` callback ordering, so existing flash-liquidation integrations work unchanged in the offer band.

When the position's LTV is in the offer band, the call walks the consumable offers **cheapest first** (most favorable effective price for the position), filling each against the caller's target. Each fill must:

1. be **strictly profitable** for the liquidator and clear the collateral's minimum bonus floor, and
2. **strictly reduce the position's LTV**.

The walk stops when the target is met, the position's collateral or debt is exhausted, all offers are visited, or the next offer would fail the de-risking check. All fills settle in a single shares-mode Morpho repay, and the whole call reverts unless the aggregate fill strictly lowered the LTV.

Because of the skip/stop rules and conservative rounding, a call can **underfill** its target. Use `previewConsume` to simulate before sending. `previewConsume` simulates the walk only: the post-settlement LTV guard runs solely on the real call, so a dust-sized quote from the view can still revert there.

All fills are applied to the offer book as effects **before** the single Morpho repay, and the `OfferConsumed` events are emitted after the walk completes, in ascending order of effective price rather than slab-id order.

### Worked Example

A position sits at 84% LTV, between a safe LTV of 80% and a liquidation LTV of 88%. Two offers are live and past their timelock:

| Offer | Collateral offered | Debt shares requested | Effective bonus now |
|-------|--------------------|-----------------------|---------------------|
| `#3` | 1,000 | worth 970 | 3.1% |
| `#7` | 500 | worth 493 | 1.4% |

A liquidator targets 1,200 of collateral. The walk visits `#3` first (cheaper for the position), fills it entirely for 1,000 collateral against 970 of debt value, then moves to `#7` and fills 200 of its 500 collateral against the proportional 197 of debt value. Both fills clear the 1% floor and both strictly lower the LTV, so the walk fills the target exactly.

Had `#7` been priced at a 0.9% bonus, it would have been skipped, the call would have returned an underfill of 1,000, and `#7` would have stayed in the book until either the accrual moved it further out of the money or it expired.

Note that a fixed share amount buys more loan-token debt as interest accrues, so every standing offer's effective bonus **decays over time**. An offer that is unprofitable today may simply never become profitable again.

### Views and Events

| View | Use |
|------|-----|
| `offers()` / `offer(id)` / `offerCount()` | Enumerate live offers (expired offers are pruned lazily — filter on `expiresAt`). |
| `isConsumable(id)` | Whether an offer would currently pass the consume gates, evaluated in isolation. |
| `previewConsume(seizedAssets, repaidShares)` | Simulate a consume walk for a target without mutating state. |
| `safeLtv()` / `liquidationLtv()` | The position's band thresholds. |

To monitor the offer book, track `OfferProposed`, `OfferRevoked`, and `OfferConsumed` events on each borrow position.

## For Liquidators, in Practice

- A position with `safeLtv < LTV ≤ liquidationLtv` is only liquidatable through standing offers. If the band is entered but no offer is fillable, `preLiquidate` reverts with `NoConsumableOffer()` — nothing to do until a proposer posts an offer or the LTV crosses the liquidation LTV.
- In the offer band, your bonus is set by the offer's terms (at least the collateral's minimum bonus floor), not by the `1 - LTV` proportional formula.
- Above the liquidation LTV, everything works exactly as described in [Pre-Liquidation](/liquidator/pre-liquidation/).