> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vanna.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Liquidation

> The debt clearance mechanism that runs when an account's health factor falls to or below 1.1x. Repays all outstanding debt and returns remaining direct token collateral to the account owner.

Liquidation is the enforcement mechanism that resolves an unhealthy account. When an account's health factor drops below the 1.1x threshold, the owner can call `AccountManager.liquidate()` to clear all outstanding debt and recover any remaining collateral value. The protocol blocks this call when the account is healthy - it is an emergency exit only.

***

## The Liquidation Guard

Liquidation is gated by the same `is_account_healthy()` function described in [Health Factor](/learn/health-factor):

$$
\frac{\text{total collateral value}}{\text{total debt value}} < 1.1
$$

The `liquidate()` function calls the Risk Engine directly before taking any action:

```rust theme={null}
if risk_engine_client.is_account_healthy(
    &risk_engine_client.get_current_total_balance(&smart_account),
    &risk_engine_client.get_current_total_borrows(&smart_account),
) {
    panic!("Cannot liquidate when account is healthy!!");
}
```

If the account is healthy, the call panics and reverts. Liquidation can only proceed when `is_account_healthy()` returns `false`.

***

## Authorization

The `liquidate()` function requires the account owner's authorization:

```rust theme={null}
let trader_address = Self::get_trader_address(&env, &smart_account);
trader_address.require_auth();
```

`require_auth()` on the trader address means the transaction must include a valid authorization entry from the account owner. This is not a permissionless operation - it requires the trader's direct participation or a pre-signed delegation. The protocol uses this model because the collateral is swept back to the owner, not to an external caller.

***

## Debt Repayment

For every token the account has borrowed, the Account Manager:

1. Reads the full outstanding balance from the Lending Pool:

   ```rust theme={null}
   let liquidate_amount = xlm_client.get_borrow_balance(&smart_account);
   ```

   Unlike the health check (which uses raw borrow shares), liquidation uses `get_borrow_balance()` - the full outstanding amount including all accrued interest settled as of the current state.

2. Clears the debt on the Lending Pool side:

   ```rust theme={null}
   xlm_client.collect_from(&liquidate_amount, &smart_account);
   ```

3. Transfers the corresponding tokens from the Smart Account to the pool and updates internal accounting:

   ```rust theme={null}
   smart_account_client.remove_borrowed_token_balance(&XLM_SYMBOL, &amount_wad_u128);
   ```

4. Removes the token from the account's borrowed token list if the debt is fully cleared.

This loop runs for every token in the account's borrowed token list: XLM and USDC. All debt positions are closed in a single transaction - partial liquidation is not supported.

***

## Collateral Sweep

After all debt is cleared, the Account Manager calls:

```rust theme={null}
smart_account_client.sweep_to(&trader_address);
```

`sweep_to()` iterates over every token in the Smart Account's collateral list and transfers the full balance to the specified address - in this case, the account owner.

### Tokens covered by sweep

`sweep_to()` calls `remove_collateral_token_bal_internal()` for each collateral token. This function contains explicit handlers for XLM and USDC, which transfer the actual token balances:

```rust theme={null}
if token_symbol == XLM_SYMBOL {
    xlm_token.transfer(&this_account, &user_address, &amount_scaled);
} else if token_symbol == USDC_SYMBOL {
    usdc_token.transfer(&this_account, &user_address, &amount_scaled);
}
```

For Blend yield positions (`BLEND_XLM`, `BLEND_USDC`) and Aquarius LP tracking positions (`AQ_XLM_USDC`), the internal collateral balance is zeroed and the token is removed from the collateral list. However, no token transfer occurs for these positions - the underlying b-tokens held in Blend's pool and LP positions in Aquarius are not unwound. Their tracking records are cleared from the Smart Account but the assets remain in the external protocols.

***

## No Liquidation Fee

The current implementation contains no fee mechanism. The `collect_from()` call transfers exactly the amount needed to repay the debt. The `sweep_to()` call transfers the full remaining collateral balance to the trader. No percentage is deducted for any party.

***

## Account State After Liquidation

The `liquidate()` function does not call `deactivate_account()` or `registry.close_account()`. After liquidation completes:

* All borrowed token entries are removed from the Smart Account
* `has_debt` is set to false when the last borrowed token is removed
* All collateral balances are zeroed
* The Smart Account remains in its current activation state in the registry

This differs from `close_account()`, which explicitly deactivates the Smart Account and updates the Registry. `liquidate()` is not an account closure - it is a position clear.

***

## `settle_account()` - The Voluntary Alternative

`settle_account()` provides a voluntary path to repay all debt without sweeping collateral:

```rust theme={null}
pub fn settle_account(env: Env, smart_account: Address) -> Result<bool, AccountManagerError> {
    let trader_address = Self::get_trader_address(&env, &smart_account);
    trader_address.require_auth();

    let borrowed_tokens = smart_account_contract_client.get_all_borrowed_tokens();
    for tokenx in borrowed_tokens.iter() {
        let token_debt = smart_account_contract_client.get_borrowed_token_debt(&tokenx.clone());
        Self::repay(env.clone(), token_debt, tokenx, smart_account.clone())...
    }
}
```

`settle_account()` calls `repay()` for each borrowed token. Unlike `liquidate()`, it does not check whether the account is healthy or unhealthy - it can be called at any time. Collateral remains in the Smart Account after settlement; the owner must then call `close_account()` to recover it.

|                     | `liquidate()`              | `settle_account()`     |
| ------------------- | -------------------------- | ---------------------- |
| Health check        | Account must be unhealthy  | No check               |
| Debt cleared        | All borrowed tokens        | All borrowed tokens    |
| Collateral returned | Swept to owner immediately | Stays in Smart Account |
| Account deactivated | No                         | No                     |

***

## Full Execution Flow

<img src="https://mintcdn.com/vannafinance/UHj8oBBMt2jwIvZH/images/learn/liquidationExecutionFlow.png?fit=max&auto=format&n=UHj8oBBMt2jwIvZH&q=85&s=1bbafa489413aa5732245b128ce85cfb" alt="Liquidation execution flow" style={{ maxWidth: "100%", borderRadius: "16px" }} width="1535" height="1024" data-path="images/learn/liquidationExecutionFlow.png" />

***

## Related

* [Health Factor](/learn/health-factor) - the invariant that determines when liquidation becomes possible
* [Smart Accounts](/learn/smart-accounts) - the isolated contract that holds collateral and debt
* [Lending Pools](/learn/lending-pools) - where borrow shares are stored and debt is cleared on repayment
* [Liquidation Guide](/guides/margin/liquidation) - user-facing explanation of what liquidation means for a position
