# Liquidations and Keepers

Most lending protocols answer "what happens when a loan goes bad?" with an auction: sell the collateral on an external venue, use the proceeds to repay the debt, pay the liquidator a discount. AEGIS Engine answers the question differently. There is no auction. There is no external venue. The restoration operation is local to the pool, bounded in size, and gated by a TWAP.

This page explains what actually happens when a vault becomes unhealthy, what tools keepers have, and what their economic incentive looks like.

### When is a vault "unhealthy"?

A vault is unhealthy when its debt in L exceeds its allowed fraction of its collateral floor:

rL(v) > C\_min(v) × MAX\_LTV\_PIPS / PIPS

This can happen between transactions even though every individual transaction had to pass the cap at lockVault time, because C\_min(v) is a function of the pool's current √P. If the pool moves adversely, the floor drops, and a vault that was fine yesterday can be under water today.

A vault is critically unhealthy if it exceeds HARD\_LTV\_BPS = 9\_900 (99%). At this point keepers are allowed to take more aggressive actions.

### The stabilize path

The entry point is AegisRouterV1.stabilize(vaultId, params) (which routes into AegisEngine.peelOrMicroLiquidate(...)). The call has to happen inside an AE session, like all engine mutations, but the keeper does not own the vault — they are operating while the vault is locked, in the keeper lane.

The flow selects between two operations based on vault state:

#### Peel (if attached NFTs exist)

If the vault has at least one CL or LO NFT attached:

1. Engine picks one NFT (rules in CollateralFloorMath + LiquidationMath; conservatively, the one whose liquidity reduction most improves C\_min).
2. Engine calls Uniswap v4 periphery's modifyLiquiditiesWithoutUnlock to decrease liquidity on that NFT by some dL.
3. The two tokens produced by the liquidity reduction are taken into AE's ERC-6909 balance and credited to the vault's idle.
4. The vault's C\_min recomputes; the operation reverts if C\_min\_post ≤ C\_min\_pre.

The effect is that some of the vault's concentrated collateral is converted into idle token collateral at the pool's current √P. Idle balances contribute more efficiently to C\_min than concentrated positions out of range, so the net effect is almost always to improve health.

Utilization is unchanged by peel — no L is minted or burned on the pool.

A small bounty is paid to the keeper in the pool's currencies. Bounty size is controlled by Constants.PEEL\_BOUNTY\_BPS (compile-time).

#### Micro-liquidation (if no NFTs to peel, or peel is insufficient)

If the vault has no attachable collateral to peel, or after peeling the vault is still unhealthy, Engine performs a micro-liquidation:

1. Engine inspects the vault's idle balances. One side will typically be too heavy relative to the other for the pool's current √P.
2. Engine performs an AE-owned, exact-input swap on the pool using the over-weighted side as input. The swap is bounded by:
3. A ±N\_TICKS = ±5 tick limit.
4. The pool's TWAP\_WINDOW = 30 minutes oracle check, which must remain within the allowed band.
5. If the swap partially fills (common under ±5 tick bounds on volatile pools), Engine proceeds with the tokens it did get. If it zero-fills, the call returns without reverting — this is a deliberate design choice so keepers don't spam transactions that revert and burn gas.
6. With the rebalanced idle, Engine mints full-range liquidity into the pooled position and applies the minted L as a debt repayment on the vault. rL decreases; utilization decreases.
7. The operation reverts if the post-state does not improve LTV, or if utilization would exceed the cap.

The keeper receives a bounty in the vault's currencies, capped by Constants.MICRO\_LIQ\_FEE\_MAX\_BPS.

Key invariant: a micro-liquidation always improves LTV when it fills. It never makes a vault worse to pay a bigger bounty.

#### Stabilize as a composite

The router exposes stabilize(v, params) as a single action that internally orchestrates both: peel one NFT if available and worth doing, then micro-liquidate if the vault is still unhealthy. The two operations share a single TWAP read within the session to save gas and to keep the price context consistent.

### What keepers can't do

The bounded design is what makes liquidation safe. Explicitly:

* Keepers cannot choose the swap direction. The micro-liq direction is forced by the vault's own idle imbalance. A keeper cannot direct the pool to move in a favored direction.
* Keepers cannot exceed the TWAP band. The ±N\_TICKS bound and the TWAP\_WINDOW check are enforced by OracleManager and cannot be bypassed by the caller.
* Keepers cannot liquidate solvent vaults. peelOrMicroLiquidate reverts if the vault's LTV is below the cap; there is no "profitable rebalance" path that touches a healthy vault.
* Keepers cannot extract more than the bounty. All tokens flow through PoolManager ERC-6909 accounting with per-currency deltas; keepers receive their bounty via an explicit take(currency, keeper, amount) whose amount is computed from the vault's repayment and the compile-time bps cap.
* Keepers cannot force an external venue to act. All operations happen on the same Uniswap v4 pool the vault is bound to. There is no external DEX, no off-chain auction, no exogenous settlement.

### Keeper economics

Keeper bounties are intentionally small. The reasoning:

* A big bounty is a big haircut for the borrower and a tax on lenders (since it reduces the residual collateral that eventually comes back to the vault).
* A small bounty is sufficient when the operation itself is cheap (a bounded swap on the same pool) and when the liquidation frequency is low (because sharp moves that push vaults under water are rare).
* Keeper gas costs are bounded because the operation is a single PM.unlock call with a small, predictable action set.

Specific bps values are compile-time constants and may be adjusted between deploys:

* PEEL\_BOUNTY\_BPS — bounty for a successful peel, paid in the vault's currencies proportional to the peeled notional. TODO: verify exact value in Constants.sol — current working assumption is 25 bps.
* MICRO\_LIQ\_FEE\_MAX\_BPS — maximum bounty for a successful micro-liq, paid in the vault's currencies proportional to the L repaid. TODO: verify exact value — current working assumption is 50 bps.

The protocol keeps zero of the keeper bounty. All bounty proceeds go directly to the keeper address that called stabilize.

### What borrowers experience

From a borrower's perspective, a successful keeper call looks like:

* Some of your collateral has been converted (peel: NFT liquidity → idle tokens; micro-liq: one-sided idle → L applied to debt).
* Your rL decreased by the amount of debt repaid (micro-liq only).
* A small amount of tokens left the vault as the keeper bounty.
* Your LTV is lower and your vault is healthy again (or, in severe cases, closer to healthy with further stabilize calls pending).

There is no "bad debt socialization" path built into Engine: if a cascade of micro-liquidations cannot close the gap because idle has been exhausted and utilization would exceed the cap, the vault stays under-collateralized until further market moves or deposits change the picture. In that interval, lenders bear first-loss on the uncovered amount.

See How AEGIS Handles Solvency and Liquidation for a deeper treatment of the edge cases and what lenders should expect in worst-case scenarios.

### Running a keeper

Keepers are permissionless. Anyone can watch pool state, compute C\_min and rL for every vault in a market (both exposed via views in AegisStateLibrary), and call stabilize when the inequality flips.

Practical guidance:

* Index via the subgraph. aegis-engine-subgraph exposes per-vault and per-market state for efficient off-chain selection. Polling on-chain state every block for every vault is wasteful.
* Simulate before sending. Both peel and micro-liq can zero-fill (peel if the chosen dL is too small to improve C\_min meaningfully; micro-liq if the TWAP bound is tight). Simulating via eth\_call avoids paying gas for zero-fill calls.
* Respect the ±N\_TICKS window. On volatile pools, micro-liq can revert with InvalidSecondsAgo or similar TWAP errors. If a pool is outside its TWAP band, keepers should wait and retry.
* Don't fight the protocol. There is no benefit to calling stabilize on a solvent vault. The operation reverts, you burn gas, and nothing happens.

For more detail and example opcode batches, see Router and Actions Reference.


---

# Agent Instructions: 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:

```
GET https://docs.aegis.markets/part-2-core-engine-concepts/liquidations-and-keepers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
