# Liquidations

> Markdown export of the Gearbox Protocol documentation page for agents and retrieval systems.

Canonical page: https://docs.gearbox.finance/developers/gm-liquidations
Source file: content/developers/gm-liquidations.mdx
Section router: https://docs.gearbox.finance/developers/llms.txt
Section full export: https://docs.gearbox.finance/developers/llms-full.txt

Liquidations close undercollateralized positions to ensure protocol solvency. Gearbox V3 supports both full liquidations (complete account closure) and partial liquidations (debt reduction while keeping the account open).

## When Liquidations Occur

An account becomes liquidatable when:

- **Health Factor < 1.0** (undercollateralized)
- **Account has expired** (past the configured expiration timestamp)

Anyone can liquidate an unhealthy account - there is no whitelist.

## Full Liquidation

### Liquidation Parameters

| Parameter        | Description                                |
| ---------------- | ------------------------------------------ |
| `creditAccount`  | The account to liquidate                   |
| `to`             | Where liquidator receives remaining assets |
| `calls`          | Multicall array for converting collateral  |
| `lossPolicyData` | Custom data for loss handling              |

### Liquidation Math

| Parameter                | Description                                      |
| ------------------------ | ------------------------------------------------ |
| **Liquidation Premium**  | % of account value liquidator receives as reward |
| **Liquidation Discount** | % used to cover debt and fees (100% - Premium)   |

### Outcomes

**Solvent Liquidation** (totalFunds > liabilities):

- Pool repaid in full
- DAO receives liquidation fee
- Remaining funds go to original borrower

**Bad Debt** (totalFunds < liabilities):

- DAO profit reduced first
- If insufficient, loss reported to Pool
- Pool burns Treasury shares to cover
- If Treasury empty: "uncovered loss" (socialized across LPs)

### Executing a Full Liquidation

```typescript
// Liquidation bot example
const calls = [
  // Swap collateral tokens to underlying via adapters
  {
    target: uniswapAdapterAddress,
    callData: encodeFunctionData({
      abi: uniswapAdapterAbi,
      functionName: "exactAllInputSingle",
      args: [{ tokenIn: wbtcAddress, tokenOut: usdcAddress /* ... */ }],
    }),
  },
  // Additional swaps as needed...
];

await creditFacade.write.liquidateCreditAccount([
  creditAccountAddress,
  liquidatorAddress, // receives remaining assets
  calls,
  "0x", // lossPolicyData
]);
```

### Internal Execution Steps

1. Calculate payments via `CreditLogic.calcLiquidationPayments`
2. Execute multicall (convert collateral to underlying)
3. Transfer `amountToPool` to the Pool
4. Remove active quotas via PoolQuotaKeeper

### Fee Types

| Fee Type                     | Description                       |
| ---------------------------- | --------------------------------- |
| `feeLiquidation`             | Standard liquidation fee to DAO   |
| `feeLiquidationExpired`      | Higher fee for expired accounts   |
| `liquidationDiscount`        | Discount for healthy liquidations |
| `liquidationDiscountExpired` | Discount for expired liquidations |

Expired accounts have higher fees to incentivize timely liquidation.

---

## Partial Liquidation

Partial liquidation reduces debt while keeping the account open. This is useful when market liquidity is insufficient for full conversion or a "deleverage" strategy is preferred.

### Constraints

- Account must remain open after liquidation
- Must pass collateral check post-liquidation (HF >= 1)
- Cannot leave "dust" debt below `minDebt`

### Executing a Partial Liquidation

```typescript
const seizedAmount = await creditFacade.write.partiallyLiquidateCreditAccount([
  creditAccountAddress,
  wbtcAddress, // token to seize
  parseUnits("1000", 6), // repaid USDC amount
  parseUnits("0.03", 8), // min BTC to receive
  liquidatorAddress,
  [], // price updates
]);
```

### Health Factor Thresholds

**Protocol Level:**

- **Liquidation Trigger**: HF < 1.0
- **Post-Liquidation**: HF >= 1.0 (enforced)

**Bot-Specific** (configurable in `PartialLiquidationBotV3`):

- `minHealthFactor`: HF threshold for intervention
- `maxHealthFactor`: Maximum HF after partial liquidation (prevents over-liquidation)

---

## RWA Liquidations

RWA-backed positions use the same liquidation entrypoints as permissionless collateral, but liquidators face different capital, compliance, and unwind constraints.

### On-Chain Flow

A liquidation is a swap between RWA collateral and the market underlying: the liquidator supplies underlying to repay debt and receives RWA tokens (typically to the `to` address on full liquidation, or directly on partial liquidation). There is no DEX conversion step inside the credit account.

| Step                  | What happens                                                                         |
| --------------------- | ------------------------------------------------------------------------------------ |
| **Liquidation tx**    | Liquidator repays debt with underlying; protocol transfers RWA to the liquidator     |
| **After liquidation** | Liquidator redeems or disposes of RWA outside Gearbox (issuer redemption, OTC, etc.) |

Redemption cannot be performed on the credit account. The liquidator must hold the RWA in their own wallet and complete issuer flows off-protocol.

### Liquidator Requirements

- **Upfront capital**: Underlying must be available before the liquidation tx; debt is repaid immediately and RWA is received in the same transaction
- **No market liquidity**: RWA tokens generally lack deep secondary-market liquidity, so exit timing depends on issuer redemption or other off-protocol disposal
- **Duration risk**: Capital is locked until the RWA is unwound; economics depend on issuer timelines and terms, not spot DEX prices
- **KYC** (if applicable): Many RWAs are permissioned; the liquidator may need issuer onboarding before they can hold or redeem the specific asset

### Entrypoints

Otherwise the interface matches permissionless tokens:

- Full liquidation: `liquidateCreditAccount` (often with an empty or minimal `calls` array — no adapter swaps)
- Partial liquidation: `partiallyLiquidateCreditAccount`

### Additional Liquidation Flows

Some RWA integrations expose helper contracts for positions that do not fit the standard RWA ↔ underlying swap. The Securitize integration is the primary example today.

#### Securitize: Pending Redemption Liquidations

Securitize offramp is asynchronous: when a credit account redeems DS tokens, each request is held in a dedicated `SecuritizeRedeemer` clone while Securitize processes the redemption. Stablecoins settle to the redeemer address later; until then, pending value is reflected as phantom-token collateral on the account.

If the account is liquidatable but **immediate liquid balances are insufficient to cover debt** — wrapper underlying, stablecoin on the account, and stablecoin already received on redeemers (after liquidation discount) — use `SecuritizeLiquidator` instead of calling `liquidateCreditAccount` directly. That path transfers **unclaimed redeemers** to the liquidator and closes the account in one transaction.

| Condition                                                                                                        | Use                                               |
| ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| Discounted liquid balances on account + redeemers ≥ total debt                                                   | Standard `liquidateCreditAccount`                 |
| Liquid balances < total debt, but collateral (including pending redemptions at **current NAV**) supports closure | `SecuritizeLiquidator.liquidatePendingRedemption` |

**What the liquidator receives**

- Ownership of each unclaimed `SecuritizeRedeemer` (transferred to `msg.sender` via the redemption gateway adapter)
- Any DS token balance withdrawn from the credit account
- Stablecoin on redeemers can be claimed later through normal Securitize flows once settlement arrives

The liquidator still supplies **upfront underlying** (computed from collateral value and liquidation discount). The helper pulls it from the caller, adds it as collateral, and invokes `liquidateCreditAccount` with a composed multicall.

Pending redemption value in this path uses **current NAV** (not the conservative `min(starting, current)` cap used for passive collateral), so liquidation pricing reflects the NAV at liquidation time.

```typescript
const phantomToken = getContract({
  address: redemptionPhantomTokenAddress,
  abi: securitizeRedemptionPhantomTokenAbi,
  client: publicClient,
});

const redemptionGatewayAddress = await phantomToken.read.redemptionGateway();

const redemptionGateway = getContract({
  address: redemptionGatewayAddress,
  abi: securitizeRedemptionGatewayAbi,
  client: publicClient,
});

const securitizeLiquidator = getContract({
  address: await redemptionGateway.read.transferMaster(),
  abi: securitizeLiquidatorAbi,
  client: walletClient,
});

await securitizeLiquidator.write.liquidatePendingRedemption([
  creditAccountAddress,
  redemptionGatewayAddress,
  priceUpdates, // optional PriceFeedStore updates
  "0x", // lossPolicyData
]);
```

The liquidator can then claim the settled redemption via `SecuritizeRedeemer.claim` (called through the redemption gateway once stablecoin has arrived on the redeemer clones):

```typescript
const redeemers = await redemptionGateway.read.getUnclaimedRedeemers([
  liquidatorAddress,
]);

const stableCoin = getContract({
  address: await redemptionGateway.read.stableCoinToken(),
  abi: erc20Abi,
  client: publicClient,
});

const settledRedeemers: Address[] = [];
for (const redeemer of redeemers) {
  const balance = await stableCoin.read.balanceOf([redeemer]);
  if (balance > 0n) settledRedeemers.push(redeemer);
}

await redemptionGateway.write.claim([settledRedeemers]);
```

**Liquidator requirements**

- Securitize **KYC / wallet allowlisting** for the address that receives redeemers (`msg.sender` must be an approved Securitize investor wallet)
- **Upfront underlying** approved to `SecuritizeLiquidator` for the computed `underlyingAmount`
- **Duration risk** on redeemers until Securitize settles stablecoins to them; the liquidator claims via the redemption gateway after settlement
- Market must use the Securitize collateral set (wrapper underlying, stablecoin, DS token, redemption phantom token) with a single configured redemption gateway

---

## Emergency Liquidations

### Regular vs Emergency

| Type          | When                          | Who                              |
| ------------- | ----------------------------- | -------------------------------- |
| **Regular**   | Protocol functioning normally | Anyone                           |
| **Emergency** | Protocol/Facade paused        | `EMERGENCY_LIQUIDATOR` role only |

Emergency liquidations ensure positions can be closed even during protocol pause, preventing bad debt accumulation.

### Treasury Backstop

The `TreasuryLiquidator` contract allows the DAO treasury to provide emergency liquidity when external liquidators are absent, acting as a backstop during extreme market conditions.

---

## Checking If an Account Is Liquidatable

```typescript
const creditFacade = getContract({
  address: facadeAddress,
  abi: creditFacadeV3Abi,
  client: publicClient,
});

const creditManager = getContract({
  address: cmAddress,
  abi: creditManagerV3Abi,
  client: publicClient,
});

// Get health factor
const debtData = await creditManager.read.calcDebtAndCollateral([
  creditAccount,
  2, // DEBT_COLLATERAL
]);

const hf = (debtData.twvUSD * 10000n) / debtData.totalDebtUSD;

// Check expiration
const expirationDate = await creditFacade.read.expirationDate();
const isExpired = BigInt(Math.floor(Date.now() / 1000)) > expirationDate;

const isLiquidatable = hf < 10000n || isExpired;
console.log(`Liquidatable: ${isLiquidatable}, HF: ${Number(hf) / 100}%`);
```

## Learn More

- [Credit Accounts](https://docs.gearbox.finance/developers/gm-accounts) - Account data and querying
- [External Calls](https://docs.gearbox.finance/developers/gm-mc-external) - Adapter calls used during liquidation multicalls
- [Slippage & Safety](https://docs.gearbox.finance/developers/gm-mc-safety) - Price feeds and collateral checks
