How it works

A loan, an edge, and the fee for doing the work.

Morpho Blue is a lending primitive. Each market is an immutable set of five things — what is lent, what secures it, which oracle prices that collateral, which model sets the rate, and how far the loan may go. Nothing about a market can be changed after it is created, because a market's identifier is the hash of those five things.

What makes a position liquidatable

A borrower posts collateral and draws a debt against it. Morpho allows the debt up to a fixed fraction of what the collateral is worth — the market's LLTV. In the contract's own terms:

maxBorrow = collateral × price ÷ 1e36 × lltv, and the position is healthy while maxBorrow ≥ borrowed.

Two things move that inequality. The obvious one is the collateral price. The quieter one is interest: a debt grows every second whether or not anything else happens, so a position can cross its limit on a completely still day. Every number on the board is accrued forward to the second you are looking at it, because that is the state a transaction sent now would meet.

What a strike actually does

When a position is past its limit, liquidate() is open to anyone. You name an amount of the borrower's debt, you pay it in the market's loan token, and Morpho transfers you collateral worth more than what you paid. The difference is the liquidation incentive, and it is not negotiable or auctioned — it is a pure function of the market's LLTV:

LIF = min(1.15, 1 ÷ (1 − 0.3 × (1 − lltv)))

So a market lending against a volatile stock at 38.5% pays the full 15%, and a market lending against a dollar at 91.5% pays 2.62%. Both constants are read out of the deployed contract's own ConstantsLib, not from documentation.

Why the strike names shares, not dollars

Morpho holds debt in shares, and converts them to assets with a division that rounds up. Scarp sizes a strike by finding the largest share count whose repayment still fits inside the dollars you hold — by bisection, not by dividing — because dividing lands one wei over the budget about as often as not, and one wei over is a revert.

A plan is only true for one instant

liquidate() accrues interest before it does anything else, so the share-to-asset rate it uses belongs to the block your transaction lands in, not the block you read. On the first run of the fork suite this showed up as the seizure missing its prediction by 4.6 × 10⁻⁸ and the repayment by five units — not a rounding bug, a clock difference. Keep slightly more than the plan says.

Three ways a bounty can be a mirage

This is the part a liquidation desk exists to get right. A number that looks like profit and is not is worse than no number.

1. The debt is dust

Morpho rounds a debt up to the wei, so a position that has been repaid to nothing can sit at exactly 100% of its limit owing a fraction of a cent. The very first scan of this chain reported four positions liquidatable right now — every one of them owed $0.00. The board drops anything below a dollar of debt.

2. The oracle is lying

An oracle is a contract anyone may deploy, and a market is only as honest as its price. The largest market this chain's directory returns claims $100m borrowed against WETH — but its loan token is a counterfeit USDG at 0x8C864e58… rather than the real one at 0x5fc5360D…, its collateral is a counterfeit WETH, and its oracle answers 1e18 dollars a share. Scarp lists a market only when it lends the chain's real dollar, and checks every stock's oracle against Uniswap — a separate deployment with its own liquidity — before showing a price at all.

3. The shares cannot be sold

A strike pays its premium in collateral, and on this chain those shares go back into pools that are shallow and many: a scan found 50 stocks across 610 pools, every one of them trading in more than one. A 12.68% premium collected by moving $83,000 through a single thin pool is not 12.68%. So the board never quotes a bounty from the oracle price alone — it prices the real sale, split across every pool that lists the stock, and shows what is left after it. Where a collateral has no pool at all, it says so.

What is proved, and how

The arithmetic here is a port of Morpho's own libraries — SharesMathLib, MathLib and the body of Morpho.liquidate — in BigInt, with the same roundings in the same order. A port is a claim, so it is tested by liquidating a real position on a fork of this chain: a real borrower, in a real market, with the market's oracle replaced so the position genuinely goes under. Every number must match to the wei.

What this does not do

Reading the chain is its own problem

Morpho keeps positions in a mapping, so there is no way to ask the chain who owes money — and this chain's public node serves no log history, returning an empty list for events the explorer will happily show. Borrowers therefore come from the explorer, whose Etherscan-style endpoint ignores its own page parameter and truncates at 1,000 rows without saying so. Scarp splits a range in half by block number instead of paging, and treats the result as a hint: every address it returns has its position read out of Morpho and is dropped if it owes nothing. A bad hint costs a wasted read, never a wrong row — but a missing one costs a position absent from the board, so a market whose events hit the cap says so on the page.

Risk, plainly

A liquidation is a trade. You are buying collateral at a discount and taking the price risk of selling it. The discount is fixed, the sale is not. Gas is real, reverts are real, and a position that recovers between your read and your transaction leaves you with nothing but the fee. Nothing here is advice.