Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit fixes #85

Merged
merged 12 commits into from
Oct 31, 2024
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The two main use-cases are:

### Pre-liquidation parameters restrictions

The PreLiquidation smart-contract enforces the following properties:
The PreLiquidation smart-contract enforces the properties:

- preLltv < LLTV;
- preLCF1 <= preLCF2;
Expand All @@ -64,6 +64,14 @@ It's possible to use the corresponding market oracle or any other oracle includi
PreLiquidation contract addresses are generated using the CREATE2 opcode, allowing for predictable address computation depending on pre-liquidation parameters.
The [`PreLiquidationAddressLib`](./src/libraries/periphery/PreLiquidationAddressLib.sol) library provides a `computePreLiquidationAddress` function, simplifying the computation of a PreLiquidation contract's address.

### Potential preLCF manipulation

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](https://arxiv.org/pdf/2106.06389), 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.

## Getting started

### Package installation
Expand All @@ -74,6 +82,10 @@ Install [Foundry](https://book.getfoundry.sh/getting-started/installation).

Run `forge test`.

## Solidity version

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.

## Audits

All audits are stored in the [`audits`](./audits) folder.
Expand Down
5 changes: 3 additions & 2 deletions src/PreLiquidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ contract PreLiquidation is IPreLiquidation, IMorphoRepayCallback {
require(borrowed > collateralQuoted.wMulDown(PRE_LLTV), ErrorsLib.NotPreLiquidatablePosition());

uint256 ltv = borrowed.wDivUp(collateralQuoted);
uint256 preLIF = (ltv - PRE_LLTV).wDivDown(LLTV - PRE_LLTV).wMulDown(PRE_LIF_2 - PRE_LIF_1) + PRE_LIF_1;
uint256 quotient = (ltv - PRE_LLTV).wDivDown(LLTV - PRE_LLTV);
uint256 preLIF = quotient.wMulDown(PRE_LIF_2 - PRE_LIF_1) + PRE_LIF_1;

if (seizedAssets > 0) {
uint256 seizedAssetsQuoted = seizedAssets.mulDivUp(collateralPrice, ORACLE_PRICE_SCALE);
Expand All @@ -165,7 +166,7 @@ contract PreLiquidation is IPreLiquidation, IMorphoRepayCallback {

// Note that the pre-liquidation close factor can be greater than WAD (100%).
// In this case the position can be fully pre-liquidated.
uint256 preLCF = (ltv - PRE_LLTV).wDivDown(LLTV - PRE_LLTV).wMulDown(PRE_LCF_2 - PRE_LCF_1) + PRE_LCF_1;
uint256 preLCF = quotient.wMulDown(PRE_LCF_2 - PRE_LCF_1) + PRE_LCF_1;

uint256 repayableShares = uint256(position.borrowShares).wMulDown(preLCF);
require(repaidShares <= repayableShares, ErrorsLib.PreLiquidationTooLarge(repaidShares, repayableShares));
Expand Down
10 changes: 5 additions & 5 deletions src/interfaces/IPreLiquidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ pragma solidity >= 0.5.0;
import {Id, IMorpho, MarketParams} from "../../lib/morpho-blue/src/interfaces/IMorpho.sol";

/// @notice The pre-liquidation parameters are:
/// - preLltv, the maximum LTV of a position before allowing pre-liquidation.
/// - preLCF1, the pre-liquidation close factor when the position LTV is equal to preLltv.
/// - preLCF2, the pre-liquidation close factor when the position LTV is equal to LLTV.
/// - preLIF1, the pre-liquidation incentive factor when the position LTV is equal to preLltv.
/// - preLIF2, the pre-liquidation incentive factor when the position LTV is equal to LLTV.
/// - preLltv, the maximum LTV of a position before allowing pre-liquidation, scaled by WAD.
/// - preLCF1, the pre-liquidation close factor when the position LTV is equal to preLltv, scaled by WAD.
/// - preLCF2, the pre-liquidation close factor when the position LTV is equal to LLTV, scaled by WAD.
/// - preLIF1, the pre-liquidation incentive factor when the position LTV is equal to preLltv, scaled by WAD.
/// - preLIF2, the pre-liquidation incentive factor when the position LTV is equal to LLTV, scaled by WAD.
/// - preLiquidationOracle, the oracle used to assess whether or not a position can be preliquidated.
struct PreLiquidationParams {
uint256 preLltv;
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/ErrorsLib.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.27;
pragma solidity ^0.8.0;

/// @title ErrorsLib
/// @author Morpho Labs
Expand Down