Liquidations
When an account's equity can no longer cover its maintenance margin, the program lets anyone reduce its risk. Liquidation on Flint is permissionless, partial and on-chain: a keeper closes just enough of the account to bring it back above maintenance, at prices the program bounds, and is paid a share of a fee for doing it.
When an account is liquidatable
liquidatable ⇔ net_equity < MMmeasured at forced-action fair prices — the oracle's unbanded
fair price, not the conservative risk-on prices used to open
positions. net_equity and MM are the same totals described in
Collateral & margin: weighted collateral, debt,
weighted perp PnL (including accrued funding and unsettled fees),
and the maintenance margin of every borrow and perp position.
The API flags it as meets_maintenance_margin = false, a positive
deficit, or a health_ratio below 1.
Resting limit orders reserve initial margin only, so they never make
an account liquidatable. Before that, once an account falls below
initial margin, anyone may call force_cancel_perp_orders to
take its margin-reserving orders off one contract's book; its
reduce-only orders stay. See Orders.
Who liquidates
Anyone. There is no privileged liquidator: a keeper with its own trader account calls the instruction, and the program checks every condition itself. Flint runs keepers that watch account health and liquidate; any third party can do the same. In a perp close the liquidator takes on no position — it is paid in fee ticks only.
Closing perp positions
liquidate_perp closes part of one position on one contract. It
first cancels every order the liquidatee rests on that contract,
reduce-only ones included. The liquidatee is then the taker: the
close crosses the makers' quotes and resting orders exactly like an
order, and the makers take the other side. The liquidator must pass
every enabled maker quoting slot except the liquidatee's, so a close
can't skip live quotes; owners of resting orders are optional.
Sizing. The program sizes the close itself, level by level, until the account's maintenance deficit plus a 1% buffer is covered, so the account lands just above maintenance rather than on the line. The close is then bounded per call by the contract's:
| Term | Listing default | Effect |
|---|---|---|
min_liquidation_notional_usd | $1,000 | A smaller close is lifted to it; a smaller position is closed whole |
max_liquidation_notional_usd | $100,000 | Large positions unwind in tranches across several calls |
max_liquidation_band | 0.1% | Every fill must land within mark × (1 ± band) |
The band is the liquidatee's protection against a bad choice of makers: a close that cannot fill inside it does not fill.
Charges. The liquidatee pays the normal taker fee on the close,
plus a liquidation_fee on the closed notional:
| Charge | Listing default | Paid to |
|---|---|---|
| Taker fee | Contract's taker_fee | Maker rebate share to the makers, the rest to the protocol |
| Liquidation fee | 0.05% of notional (cap 5%) | liquidator_share (default 50%) to the liquidator, the rest to the protocol |
The liquidation fee is capped at the equity the account has left, so the fee can never itself create bad debt.
Guarantees. The instruction reverts unless the account's maintenance surplus is no worse after the close than before, and every maker filled still passes its own margin check.
Repaying borrows
Spot debt — including debt created by settling perp losses — is
reduced with liquidate_spot, one (borrow, collateral) pair per
call. The liquidator repays part of the borrow and seizes collateral
worth 1 + liquidation_bonus per dollar repaid, where the bonus is
set per seized asset. The pair and size are chosen to clear the
maintenance deficit plus the same 1% buffer, and the liquidator must
itself stay above initial margin.
Backstop
Some accounts fall too far, too fast for small closes to help. Once
net_equity ≤ MM × backstop_mm_ratio (default ratio: 0.5)or equity is outright negative, any account may call backstop
and take over the same percentage of every spot and perp position
of the distressed account at once. The takeover:
- must not reduce the distressed account's maintenance surplus,
- must leave the backstopper above initial margin, and
- must take everything, or leave the distressed account with at least $500 of net equity.
The distressed account's resting orders stay on the book.
Backstopping is voluntary. It replaces a dedicated backstop fund with last-resort takers who judge the account worth absorbing.
Bad debt
If an account's debts outlive all of its collateral, what remains is bad debt.
- Spot debt is written off by
socialize_loss(Flint admin, only for an account with strictly negative unweighted equity and at most $1 of collateral left). The insurance fund's balance of the same asset is drawn first, up to the configured fraction per call; any remainder lowers the market's deposit share price, spreading the loss across that market's depositors. - Perp winners are paid from each contract's settle pool, which holds the losses losers have actually paid in. A gain is settled only as far as the pool reaches; the rest stays owed and is paid as further losses arrive.
The insurance fund is funded by a configurable share of collected
fees (see Fees); RiskService.GetInsuranceFund
reports its balances.
Worked example
Continuing the margin example:
long 50 SOL-PERP from $150, USDC balance 992.50 after fees, devnet
parameters (mmf = 5%, USDC deposit_weight = 0.9, taker fee
0.10%, liquidation fee 0.05%, liquidator_share = 50%,
min close $1,000). The liquidation price was about $137.81.
SOL marks at $137.
USDC balance + PnL = 992.50 − 50 × 13 = 342.50
net_equity = 342.50 × 0.9 = 308.25
MM = 0.05 × 50 × 137 = 342.50
deficit = 342.50 − 308.25 = 34.25
target (+1%) ≈ 34.59Each SOL closed at the mark releases 0.05 × 137 = 6.85 of MM and
costs 0.15% in fees (0.2055, or 0.185 of equity after the 0.9
weight), a net gain of about 6.67 per SOL. Clearing the target
needs about 5.2 SOL ($711) — below the $1,000 floor, so the close is
lifted to it: 7.289 SOL, $998.59 of notional.
taker fee = 0.10% × 998.59 ≈ 1.00 (0.50 to makers, 0.50 protocol)
liquidation fee = 0.05% × 998.59 ≈ 0.50 (0.25 liquidator, 0.25 protocol)
after the close (filled at the mark):
remaining position = 42.711 SOL
net_equity = (342.50 − 1.50) × 0.9 ≈ 306.90
MM = 0.05 × 42.711 × 137 ≈ 292.57
health ratio ≈ 1.05The account is back above maintenance and keeps the rest of its position. Fills worse than the mark (up to the 0.1% band) cost a little more equity per SOL and would size the close slightly larger.
Avoiding liquidation
- Watch health, not price. Every position, borrow and funding
accrual feeds one number.
SubscribeAccountstreams it; aim to stay well above ahealth_ratioof 1. - Hold settlement-asset cash. Perp losses settle in USDC. Without USDC behind them they become USDC debt with its own, much larger margin requirement (see the warning).
- Size with free collateral to spare. Opening at exactly initial
margin leaves only the
imf − mmfband before liquidation. - Reduce early. Below initial margin you can still close: a reduce-only fill only has to clear maintenance.
- Expect to lose resting orders under stress. Below initial margin anyone can force-cancel your margin-reserving orders, and a liquidation cancels all of them on the contract it closes.
- Mind funding. A large adverse funding rate drains equity hour after hour, capped by the contract's maximum rate.
- Use the simulators.
RiskService.SimulateAccountRiskapplies price shocks to your account;PreviewOrdershows the margin an order leaves you with.