Liquidation
📖 Liquidation Mechanism in Centuari Protocol
In the Centuari protocol, the liquidation mechanism serves as a risk management tool to maintain the health of the lending system. It allows third-party liquidators to close borrower positions under specific conditions:
The loan has passed its maturity date, or
The borrower's position has fallen below the required health factor.
Liquidators repay the borrower’s outstanding debt and, in return, receive the borrower’s collateral as compensation.

📌 Liquidation Execution Flow
� Liquidation Flow (General Overview)
In Centuari Protocol, liquidation is a process that helps maintain the stability and safety of the lending system. It occurs when a borrower fails to meet the agreed conditions—either because the loan has matured without repayment, or because the value of their collateral is no longer sufficient compared to their outstanding debt.
The liquidation process follows these general steps:
Eligibility Check The system checks whether the borrower is eligible for liquidation based on maturity or collateral health.
Position Assessment The protocol reviews the borrower’s loan and collateral details to determine how much debt is owed and what assets are available.
Debt Calculation The borrower’s total outstanding debt is calculated proportionally based on their share of the lending pool.
Position Closure The borrower’s position is closed, meaning their loan and collateral records are cleared from the system.
Asset Settlement A third-party liquidator repays the borrower’s debt on their behalf. In return, the liquidator receives the borrower’s full collateral as compensation.
Transparency Logging The liquidation event is recorded on-chain to ensure transparency and enable tracking by external services and users.
This process ensures that the protocol remains solvent and fair for all participants, especially lenders, by promptly resolving risky or overdue positions.
The liquidate()
function handles the liquidation process through the following steps:
📌 Liquidation Execution Flow (Technical Details)
1 Validation of Borrower and Conditions
Before proceeding, the function validates:
That the borrower’s address is not zero.
That the borrower’s position is eligible for liquidation:
The maturity date has passed (if a maturity is set), or
The borrower's health factor is below the allowed threshold.
Example:
function liquidate(MarketConfig memory config, uint256 amount, uint256 maturity, address user)
external
nonReentrant
onlyActiveMaturity(config.marketId(), maturity)
whenNotPaused
Parameters
config: MarketConfig struct containing market-specific settings (e.g., marketId).
amount: Amount of debt (in loan tokens) to be repaid by the liquidator.
maturity: Timestamp of the position’s maturity.
user: Address of the user whose position is being liquidated.
Position Assessment The protocol reviews the borrower’s loan and collateral details to determine how much debt is owed and what assets are available.
2. Retrieve User Position
Queries IDataStore for the
market (dataStores[config.marketId()]):
userBorrowValue
: User’s total borrowed value (in loan tokens).userCollateral
: User’s total collateral (in collateral tokens).
3. Validate Liquidation Amount
Reverts with
CentuariErrorsLib.InsufficientBorrowValue if amount > userBorrowValue
.
4. Calculate Penalty
Fetches MarketRiskConfig from RISK_MANAGER.
Computes:
uint256 amountWithPenalty = amount + ((amount * riskConfig.lp) / PERCENTAGE_DENOMINATOR);
where lp is the liquidation penalty (in basis points, e.g., 500 for 5%).
5. 📈 Fetch Token Prices
Retrieves
collateralToken
andloanToken
fromdataStore
.Calls
ORACLE_MANAGER.getPrice(collateralToken, loanToken)
to getcollateralPrice
.
6. 🧾 Calculate Collateral Allocation
Calculates:
totalCollateralToLiquidator = amountWithPenalty / collateralPrice; badDebt = int256(userCollateral) - int256(totalCollateralToLiquidator);
Derives:
UserBorrowValue = userBorrowValue - amount; remainingUserCollateral = badDebt < 0 ? 0 : userCollateral - totalCollateralToLiquidator; collateralToLiquidator = badDebt < 0 ? totalCollateralToLiquidator - uint256(-badDebt) : totalCollateralToLiquidator;
7. 🧑 Update User Position
Writes updated values to
dataStore
:setUserBorrowValue
setUserCollateral
8. 💸 Execute Token Transfers
Transfers:
Loan tokens from liquidator to contract using
IERC20.safeTransferFrom
.Collateral tokens from contract to liquidator using
IERC20.safeTransfer
.
9. 📢 Emit Event
Emits CentuariEventsLib.Liquidate.
📊 Example Liquidation Scenario
🧱 Assumptions
Borrower A:
Has borrowed 500 USDC.
Has deposited 1 WBTC as collateral.
Holds 5 borrow shares out of 50 total shares in the lending pool.
Total Pool Debt:
5,000 USDC
Oracle Price:
Original WBTC price: 25,000 USDC (healthy position)
Price drops to: 800 USDC per WBTC (position becomes undercollateralized)
Liquidation Penalty: 5% (500 basis points)
Maturity: Not yet reached (liquidation subject to eligibility check)
🧮 Borrower’s Debt Calculation
Borrowed amount is determined by share:
borrowedAmount = (5 / 50) * 5,000 = 500 USDC
⚠️ Liquidation Eligibility
Collateral Value = 1 WBTC × 800 USDC = 800 USDC
Debt = 500 USDC
Collateral Ratio = 800 / 500 = 160%
If the protocol’s minimum collateral ratio is, say, 170%, then: → Borrower A is eligible for liquidation
🔥 Liquidation Triggered by Liquidator (e.g., Bob)
The liquidator calls:
liquidate(config, 500e6, maturity, borrowerA)
Where:
config
: Contains market ID and risk settingsamount
: 500 USDCuser
: Borrower Amaturity
: Active maturity timestamp
💰 Penalty and Collateral Calculation
Penalty Calculation:
penalty = 500 * 5% = 25 USDC
amountWithPenalty = 500 + 25 = 525 USDC
Oracle Price (WBTC):
collateralPrice = 800 USDC per WBTC
Collateral Transferred to Liquidator:
totalCollateralToLiquidator = 525 / 800 = 0.65625 WBTC
Remaining User Position:
remainingBorrow = 0 USDC
remainingCollateral = 1 WBTC - 0.65625 WBTC = 0.34375 WBTC
Bad Debt Calculation:
badDebt = 1 - 0.65625 = 0.34375 → no bad debt (value is still positive)
🔁 Token Transfers
Liquidator transfers 500 USDC to the protocol.
Protocol transfers 0.65625 WBTC to the liquidator.
Borrower A's position is updated:
Borrowed amount:
0
Collateral:
0.34375 WBTC
✨ Key Advantages of This Design
✅ Open Liquidation System: Anyone can act as a liquidator and claim collateral from unhealthy positions. ✅ Share-Based Accounting: Scalable and dynamic, ensuring fair debt and collateral calculations. ✅ Event Logging: Transparent on-chain event emission enables robust tracking and off-chain integrations. ✅ Market-Specific Configurations: Liquidation eligibility and parameters are determined per-market basis.
📌 Summary
The Centuari protocol’s liquidation mechanism is designed to:
Secure the protocol against bad debt
Maintain lending pool health
Reward third-party liquidators
Protect the interests of other lenders in the pool
It operates through a secure, event-driven, share-based system that balances flexibility and protocol integrity.
Last updated