This repository puts together different contracts to carry out liquidations on Morpho with specific parameters chosen by the borrower. We call these user-defined Morpho Blue transactions pre-liquidations. Borrowers can set custom pre-liquidation parameters, allowing them to specify pre-liquidation incentive factors and pre-liquidation close factors. Pre-liquidation incentive factors determine incentives given to liquidators and pre-liquidation close factors limit the proportion of the position that can be closed during a liquidation.
The PreLiquidation contract serves as the endpoint for pre-liquidations using parameters chosen by borrowers.
Note that pre-liquidation must be authorized on Morpho.
Liquidators may perform pre-liquidations on a position using the preLiquidate entry point on a deployed PreLiquidation contract.
The PreLiquidationFactory factory contract simplifies the deployment and indexing of pre-liquidation contracts.
The set of pre-liquidation parameters is composed of
- a Morpho market (
id); - a pre-liquidation loan-to-value (
preLltv); - two pre-liquidation close factor parameters (
preLCF1andpreLCF2); - two pre-liquidation incentive factor parameters (
preLIF1andpreLIF2); - a pre-liquidation oracle (
preLiquidationOracle).
The pre-liquidation close factor and the pre-liquidation incentive factor evolve linearly with the user's LTV:
- the pre-liquidation close factor is
preLCF1when the position LTV is equal topreLltvandpreLCF2when the LTV is equal toLLTV; - the pre-liquidation incentive factor is
preLIF1when the position LTV equalspreLltvandpreLIF2when the LTV is equal toLLTV.
These functions are illustrated in the following figure:
The two main use-cases are:
- Using normal fixed parameters when
preLIF1 = preLIF2andpreLCF1 = preLCF2. - Using health dependent liquidation when either
preLIF1 < preLIF2orpreLCF1 < preLCF2, similar to a Quasi Dutch Auction (as in Euler liquidations).
The PreLiquidation smart-contract enforces the properties:
preLltv < LLTV;preLCF1 <= preLCF2;preLFC1 <= 1;1 <= preLIF1 <= preLIF2 <= 1 / LLTV.
Note: A pre-liquidation close factor higher than 100% means that the whole position is pre-liquidatable, so using preLCF2 > 1 allows to make the position entirely pre-liquidatable at a LTV between preLltv and LLTV.
The property preLIF2 <= 1 / LLTV and the fact that pre-liquidations are only allowed for LTV <= LLTV ensure that pre-liquidations can't worsen the health of the position.
By calling preLiquidate with a smart contract that implements the IPreLiquidationCallback interface, the liquidator can be called back.
More precisely, the onPreLiquidate function of the liquidator's smart contract will be called after the collateral withdrawal and before the debt repayment.
This mechanism eliminates the need for a flashloan.
The PreLiquidationParams struct includes a preLiquidationOracle attribute, allowing pre-liquidation using any compatible oracle.
This oracle should implement Morpho's IOracle interface and adhere to the behavior specified in the documentation.
It's possible to use the corresponding market oracle or any other oracle including OEV solutions.
PreLiquidation contract addresses are generated using the CREATE2 opcode, allowing for predictable address computation depending on pre-liquidation parameters.
The PreLiquidationAddressLib library provides a computePreLiquidationAddress function, simplifying the computation of a PreLiquidation contract's address.
A pre-liquidation cannot repay a proportion of the position's debt greater than preLCF.
However, it's possible to pre-liquidate a proportion of the position while keeping it pre-liquidatable before performing another pre-liquidation.
This manipulation can lead to repaying a proportion of the position's debt higher than preLCF.
It has been studied in the part 5.2 of An Empirical Study of DeFi Liquidations:Incentives, Risks, and Instabilities, in the case of a constant liquidation close factor.
Implementing a preLCF linear in the health factor can help mitigating this manipulation when choosing the right slope.
Note
PreLiquidationFactory has been deployed on Ethereum and Base with the metadata hash included, which appear at two places in the bytecode as it is a factory.
Install Foundry.
Run forge test.
As a consequence of using Solidity 0.8.27, the bytecode of the contracts could contain new opcodes (e.g., PUSH0, MCOPY, TSTORE, TLOAD) so one should make sure that the contract bytecode can be handled by the target chain for deployment.
All audits are stored in the audits folder.
Files in this repository are publicly available under license GPL-2.0-or-later, see LICENSE.