RawPrice is the price of collateral from PriceFeed and LTV is Loan to Ratio.
If a position's value of lockedCollateral(lockedCollateralAmount * PriceWithSafetyMargin) goes below the debtValue(DebtShare * debtAccumulatedRate), the position is considered unsafe/underwater and will be subject to liquidation process. The liquidator bot monitors the health of each position in the Fathom protocol.
Once a position is underwater and spotted by the liquidator bot, the bot can call the liquidate function in the LiquidationEngine contract.
functionliquidate(bytes32_collateralPoolId,// the collateralPoolId of the position that is to be liquidatedaddress_positionAddress,// the positionHandler's address of a position that is to be liquidateduint256_debtShareToBeLiquidated,// a param to set how much of debtShare will be liquidated from a positionuint256_maxDebtShareToBeLiquidated,// the ceiling for the debtShare that can be liquidatedaddress_collateralRecipient,// the recipient of the collateral once the liquidation process endsbytescalldata_data// is used when the liquidation process includes FlashLendingCallee) external;
Or the bot can call the batchLiquidate function if it spots multiple underwater positions.
If a bot calls liquidate or batchLiquidate functions to LiquidationEngine without using the _data param, the liquidator bot needs to have enough balance of FXD token available and should have approved FixedSpreadLiquidationStrategy as a spender. This is because the process of depositing FXD to liquidate and receive collateral is done in the execute function in FixedSpreadLiquidationStrategy.
If a bot calls liquidate or batchLiquidate functions and has the _data param filled with encoded data that can be used for flashLendingCalle's address, the liquidator bot doesn't necessarily need to have an FXD token available.
Once liquidation functions are called, the liquidation process starts from the internal function _liquidate.
The execute function in FixedSpeadLiquidationStrategy starts by verifying if the caller has the LIQUIDATION_ENGINE_ROLE from the AccessControlConfig associated with the BookKeeper. This ensures that only authorized entities can initiate the liquidation process.
The function then validates the input parameters, such as the debt share, collateral amount, and position address. It checks for zero values and valid price feeds to ensure the integrity of the liquidation data.
Then, it calculates the liquidation information based on the current market price, debt share, and collateral amount. This step involves determining the actual debt value to be liquidated, the collateral amount that will be seized, and any applicable treasury fees.
LiquidationInfo memory info =_calculateLiquidationInfo( _collateralPoolId, _debtShareToBeLiquidated,getFeedPrice(_collateralPoolId), _positionCollateralAmount, _positionDebtShare);
The function then calls confiscatePosition on the BookKeeper, adjusting the collateral and debt share of the position in question.
Treasury fees are moved from the liquidation contract to the SystemDebtEngine if any treasury fees are due.
if (info.treasuryFees >0) { bookKeeper.moveCollateral(_collateralPoolId,address(this),address(systemDebtEngine), info.treasuryFees);}
If flash lending is enabled and valid, the contract facilitates flash lending calls. This step is optional and based on the encoded data provided.
if (info.treasuryFees >0) { bookKeeper.moveCollateral(_collateralPoolId,address(this),address(systemDebtEngine), info.treasuryFees);}
Without flash lending, the contract withdraws the collateral to the liquidator and transfers the required FXD amount to cover the debt. The FXD is then deposited in the BookKeeper to clear the debt.
After the execute function of the FixedSpreadLiquidationStrategy completes, the remaining liquidation process in the LiquidationEngine is verification of successful liquidation and recording of systemBadDebt if needed.