Liquidations
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
// 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
- Calculate payments via
CreditLogic.calcLiquidationPayments - Execute multicall (convert collateral to underlying)
- Transfer
amountToPoolto the Pool - 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
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 interventionmaxHealthFactor: 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 minimalcallsarray — 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 tomsg.sendervia 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.
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):
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.sendermust be an approved Securitize investor wallet) - Upfront underlying approved to
SecuritizeLiquidatorfor the computedunderlyingAmount - 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
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 - Account data and querying
- External Calls - Adapter calls used during liquidation multicalls
- Slippage & Safety - Price feeds and collateral checks