Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions certora/specs/LiquidationProfitability.spec

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reference for why we made this change ? I feel like it would be useful if we come back to this to have the rationale (only got it informally)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ definition WAD() returns uint256 = 10 ^ 18;

definition ORACLE_PRICE_SCALE() returns uint256 = 10 ^ 36;

definition TIME_TO_MAX_LIF() returns uint256 = 900; // 15 min
definition TIME_TO_MAX_LIF() returns uint256 = 3600; // 60 min

persistent ghost summaryPrice(address) returns uint256;

Expand Down Expand Up @@ -67,7 +67,7 @@ function summaryMulDivUp(uint256 a, uint256 b, uint256 d) returns uint256 {

/// LIF CHARACTERIZATION ///

/// For repaidUnits input: lif >= WAD (solvency), and lif == maxLif when in normal mode or when the call is >= 15 min post-maturity (profitability).
/// For repaidUnits input: lif >= WAD (solvency), and lif == maxLif when in normal mode or when the call is >= 60 min post-maturity (profitability).
rule liquidationLifRepaidUnits(env e, Midnight.Market market, uint256 collateralIndex, uint256 repaidUnits, address borrower, address receiver, address callback, bytes data, bool postMaturityMode) {
uint256 maxLif = market.collateralParams[collateralIndex].maxLif;
require maxLif >= WAD(), "see the rule maxLifIsAtLeastWad";
Expand All @@ -83,11 +83,11 @@ rule liquidationLifRepaidUnits(env e, Midnight.Market market, uint256 collateral
// lif >= WAD: liquidator receives collateral worth at least the repaid debt (up to 1 unit floor rounding on seizedAssets) at the oracle price.
assert (seizedResult + 1) * price >= repaidResult * ORACLE_PRICE_SCALE();

// lif == maxLif when in normal mode or when >= 15 min post-maturity: full liquidation incentive factor applies.
// lif == maxLif when in normal mode or when >= 60 min post-maturity: full liquidation incentive factor applies.
assert maxLifReached => (seizedResult + 1) * price * WAD() + ORACLE_PRICE_SCALE() * WAD() > repaidResult * maxLif * ORACLE_PRICE_SCALE();
}

/// For seizedAssets input: lif >= WAD (solvency), and lif == maxLif when in normal mode or when the call is >= 15 min post-maturity (profitability).
/// For seizedAssets input: lif >= WAD (solvency), and lif == maxLif when in normal mode or when the call is >= 60 min post-maturity (profitability).
rule liquidationLifSeizedAssets(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, address borrower, address receiver, address callback, bytes data, bool postMaturityMode) {
uint256 maxLif = market.collateralParams[collateralIndex].maxLif;
require maxLif >= WAD(), "see the rule maxLifIsAtLeastWad";
Expand All @@ -103,6 +103,6 @@ rule liquidationLifSeizedAssets(env e, Midnight.Market market, uint256 collatera
// lif >= WAD: liquidator receives collateral worth at least the repaid debt (up to 1 unit ceil rounding on repaidUnits) at the oracle price.
assert seizedResult * price > (repaidResult - 1) * ORACLE_PRICE_SCALE();

// lif == maxLif when in normal mode or when >= 15 min post-maturity: full liquidation incentive factor applies.
// lif == maxLif when in normal mode or when >= 60 min post-maturity: full liquidation incentive factor applies.
assert maxLifReached => seizedResult * price * WAD() + ORACLE_PRICE_SCALE() * WAD() > (repaidResult - 1) * maxLif * ORACLE_PRICE_SCALE();
}
2 changes: 1 addition & 1 deletion certora/specs/NoDivisionByZero.spec
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// All other Solidity divisions in the codebase use non-zero denominators:
// - settlementFee: divides by (end - start), always a positive constant from the breakpoint table.
// - setMarketSettlementFee / setDefaultSettlementFee: divide by CBP (1e12).
// - liquidate: divides by TIME_TO_MAX_LIF (15 minutes = 900).
// - liquidate: divides by TIME_TO_MAX_LIF (60 minutes = 3600).
// - tickToPrice: divides by 5e12 or a value greater than 1e18.
// - wExp, used in tickToPrice: divides by non-zero constants.
// Therefore, we only look for division by zero in mulDivDown and mulDivUp in this file.
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/ConstantsLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ uint256 constant MAX_SETTLEMENT_FEE_90_DAYS = 0.00125e18;
uint256 constant MAX_SETTLEMENT_FEE_180_DAYS = 0.0025e18;
uint256 constant MAX_SETTLEMENT_FEE_360_DAYS = 0.005e18;
uint32 constant MAX_CONTINUOUS_FEE = uint32(uint256(0.01e18) / uint256(365 days));
uint256 constant TIME_TO_MAX_LIF = 15 minutes;
uint256 constant TIME_TO_MAX_LIF = 60 minutes;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Suggested change
uint256 constant TIME_TO_MAX_LIF = 60 minutes;
uint256 constant TIME_TO_MAX_LIF = 1 hours;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like minutes is better here because it's more natural for this kind of duration (if i want to use 40 minutes for a test, there's less change) but no big deal

uint256 constant MAX_COLLATERALS = 128;
uint256 constant MAX_COLLATERALS_PER_BORROWER = 16;
uint256 constant LIQUIDATION_CURSOR_LOW = 0.25e18;
Expand Down
4 changes: 4 additions & 0 deletions test/LiquidationTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ contract LiquidationTest is BaseTest {
deal(address(loanToken), address(this), type(uint256).max);
}

function testTimeToMaxLifIs60Minutes() public pure {
assertEq(TIME_TO_MAX_LIF, 60 minutes);
}

function testLiquidateInvalidCollateralIndex() public {
uint256 units = 100e18;
collateralize(market, borrower, units);
Expand Down