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
- It does not front-run anything. There is no mempool watching, no bundle, no priority auction. If somebody else takes a position first, your transaction reverts and costs gas.
-
It cannot strike without capital. A capital-free liquidation needs a contract that can
receive Morpho's callback and swap inside it. Morpho's own Bundler3 and GeneralAdapter1 are
deployed on this chain, but the adapter has no
morphoLiquidate— its ABI carries supply, borrow, repay, withdraw and flash-loan entry points and nothing for liquidation — so that route does not exist here without deploying something. Scarp deploys nothing, and strikes with your own dollars. - It does not tell you a position will fall. "Left to fall" is a distance, not a forecast.
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.