From c057a5071bf274bb0a755bb03e479b821a939b6c Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 18 Oct 2024 11:42:55 +0200 Subject: [PATCH 01/12] refactor: factor parameter computation --- src/PreLiquidation.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PreLiquidation.sol b/src/PreLiquidation.sol index d4e91b2..9f09718 100644 --- a/src/PreLiquidation.sol +++ b/src/PreLiquidation.sol @@ -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); @@ -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)); From 74c4faee3a3297859c29b174d299a6a5d2ef326c Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 18 Oct 2024 15:30:05 +0200 Subject: [PATCH 02/12] doc: small readme improvement --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4ca2ea..d9cd492 100644 --- a/README.md +++ b/README.md @@ -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; From 3f2d67c70977a07676b1f5adc54f9448f6bfacf1 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 18 Oct 2024 16:14:46 +0200 Subject: [PATCH 03/12] doc: prelcf exploit --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index d9cd492..d3f2045 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,11 @@ 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 pre-liquidate more than `preLCF` proportion of the position debt, however it's possible to pre-liquidate a small part of the position while keeping it pre-liquidatable before performing another pre-liquidation. This manipulation can lead to repaying more than `preLCF` of the debt. This 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). Implementing a `preLCF` linear with the health factor mitigates this. + ## Getting started ### Package installation From ef5fb17fd160aba8496f294cd3d0cf881ac263e2 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 18 Oct 2024 16:32:05 +0200 Subject: [PATCH 04/12] doc: readme improvement --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3f2045..357c552 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,10 @@ The [`PreLiquidationAddressLib`](./src/libraries/periphery/PreLiquidationAddress ### Potential preLCF manipulation -A pre-liquidation cannot pre-liquidate more than `preLCF` proportion of the position debt, however it's possible to pre-liquidate a small part of the position while keeping it pre-liquidatable before performing another pre-liquidation. This manipulation can lead to repaying more than `preLCF` of the debt. This 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). Implementing a `preLCF` linear with the health factor mitigates this. +A pre-liquidation cannot pre-liquidate more than `preLCF` of the position debt. +However it's possible to pre-liquidate a small part of the position while keeping it pre-liquidatable before performing another pre-liquidation. +This manipulation can lead to repaying more than `preLCF` of the debt and 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). +Implementing a `preLCF` linear with the health factor mitigates this. ## Getting started From 91392a7758b91d381743ed5d468660c912041d10 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 18 Oct 2024 17:31:26 +0200 Subject: [PATCH 05/12] fix: errors lib solidity version --- src/libraries/ErrorsLib.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol index 5c3393d..4b296a6 100644 --- a/src/libraries/ErrorsLib.sol +++ b/src/libraries/ErrorsLib.sol @@ -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 From f46dd4bd18ae5a1c58e0696c2fb796ccf66ced9e Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 18 Oct 2024 18:44:06 +0200 Subject: [PATCH 06/12] doc: readme --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 357c552..5b5d7bf 100644 --- a/README.md +++ b/README.md @@ -66,9 +66,8 @@ The [`PreLiquidationAddressLib`](./src/libraries/periphery/PreLiquidationAddress ### Potential preLCF manipulation -A pre-liquidation cannot pre-liquidate more than `preLCF` of the position debt. -However it's possible to pre-liquidate a small part of the position while keeping it pre-liquidatable before performing another pre-liquidation. -This manipulation can lead to repaying more than `preLCF` of the debt and 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). +A pre-liquidation cannot pre-liquidate a proportion of the position's debt greater than `preLCF`, however it's possible to pre-liquidate a fraction 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` and 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). Implementing a `preLCF` linear with the health factor mitigates this. ## Getting started From fd3ddd5a1d12fa0510f041c5411a2c887d4fda04 Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 21 Oct 2024 09:52:26 +0200 Subject: [PATCH 07/12] doc(readme): improvement --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5b5d7bf..aa8249d 100644 --- a/README.md +++ b/README.md @@ -66,9 +66,10 @@ The [`PreLiquidationAddressLib`](./src/libraries/periphery/PreLiquidationAddress ### Potential preLCF manipulation -A pre-liquidation cannot pre-liquidate a proportion of the position's debt greater than `preLCF`, however it's possible to pre-liquidate a fraction 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` and 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). -Implementing a `preLCF` linear with the health factor mitigates this. +A pre-liquidation cannot pre-liquidate 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 with the health factor can help mitigating this manipulation when choosing the right slope. ## Getting started From e530472dd799dcb94cfab33590a7b7225e54519a Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 21 Oct 2024 09:54:24 +0200 Subject: [PATCH 08/12] doc(readme): typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa8249d..b1fc9cb 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ The [`PreLiquidationAddressLib`](./src/libraries/periphery/PreLiquidationAddress A pre-liquidation cannot pre-liquidate 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 with the health factor can help mitigating this manipulation when choosing the right slope. +Implementing a `preLCF` linear in the health factor can help mitigating this manipulation when choosing the right slope. ## Getting started From ee18fc0b09eefe0599d2e74785613534e6aec0bd Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 21 Oct 2024 10:30:03 +0200 Subject: [PATCH 09/12] doc: specify wad scaling --- src/interfaces/IPreLiquidation.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/interfaces/IPreLiquidation.sol b/src/interfaces/IPreLiquidation.sol index 424271a..4f03815 100644 --- a/src/interfaces/IPreLiquidation.sol +++ b/src/interfaces/IPreLiquidation.sol @@ -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; From 3d086f183b708aec53d830d4086633635c79a564 Mon Sep 17 00:00:00 2001 From: peyha Date: Thu, 24 Oct 2024 11:09:27 +0200 Subject: [PATCH 10/12] doc(readme): improvements --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b1fc9cb..714fbe2 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,8 @@ The [`PreLiquidationAddressLib`](./src/libraries/periphery/PreLiquidationAddress ### Potential preLCF manipulation -A pre-liquidation cannot pre-liquidate 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. +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. From 30eeb671a5ea752f1177e1b58d59bef0dacecf66 Mon Sep 17 00:00:00 2001 From: peyha Date: Thu, 24 Oct 2024 11:17:26 +0200 Subject: [PATCH 11/12] doc(readme): solidity version disclaimer --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 714fbe2..49f37fc 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,11 @@ Install [Foundry](https://book.getfoundry.sh/getting-started/installation). Run `forge test`. +## Solidity version + +The main contracts (`PreLiquidation` and `PreLiquidationFactory`) are written in Solidity 0.8.27. +The bytecode of these 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 chain used for deployment. + ## Audits All audits are stored in the [`audits`](./audits) folder. From c951b5463d2934b5ec9910ceb060fd470a62b275 Mon Sep 17 00:00:00 2001 From: peyha Date: Thu, 24 Oct 2024 11:39:57 +0200 Subject: [PATCH 12/12] doc(readme): improvements --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 49f37fc..11f2392 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ The [`PreLiquidationAddressLib`](./src/libraries/periphery/PreLiquidationAddress ### 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. +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. @@ -84,8 +84,7 @@ Run `forge test`. ## Solidity version -The main contracts (`PreLiquidation` and `PreLiquidationFactory`) are written in Solidity 0.8.27. -The bytecode of these 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 chain used for deployment. +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