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

[Certora] Verif expected reverts #37

Merged
merged 30 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
70c7e69
Merge branch 'colin@verif/setup' into colin@verif/expected-reverts
colin-morpho Sep 27, 2024
2dfbba9
feat: check non-liquidatable reverts
colin-morpho Sep 27, 2024
c410c15
fix: summarize oracle
colin-morpho Sep 29, 2024
42ea66e
Merge branch 'main' into colin@verif/expected-reverts
colin-morpho Sep 30, 2024
ec4d910
feat: check pre-liquidate revers
colin-morpho Sep 30, 2024
a42149d
fix: remove useless summary
colin-morpho Sep 30, 2024
68bcaf6
Revert "fix: remove useless summary"
colin-morpho Sep 30, 2024
65fc7f4
fix: fix division by zero
colin-morpho Oct 1, 2024
4b0a112
feat: check excessive liquidation revert
colin-morpho Oct 1, 2024
983863c
fix: change spec
colin-morpho Oct 1, 2024
bf45cb6
Merge branch 'main' into colin@verif/expected-reverts
colin-morpho Oct 3, 2024
177a959
Merge branch 'main' into colin@verif/expected-reverts
colin-morpho Oct 7, 2024
67b036c
feat: check revert conditions
colin-morpho Oct 7, 2024
b06ebdb
fix: improve spec
colin-morpho Oct 7, 2024
98c5060
fix: revert fix spec
colin-morpho Oct 7, 2024
3ce9331
fix: summarize maths
colin-morpho Oct 7, 2024
07d2269
feat: remove marketExists
colin-morpho Oct 7, 2024
7f5e1c6
fix: avoid unexpected havocs
colin-morpho Oct 7, 2024
5ab47a5
feat: ensure market exists
colin-morpho Oct 9, 2024
4b1dc0a
fix: externalize invariants, revert on liquidatable, severa minor fixes
colin-morpho Oct 10, 2024
44492dd
feat: add invariant checks to the CI
colin-morpho Oct 10, 2024
c6055d7
fix: invariant timeout
colin-morpho Oct 10, 2024
ebdaff6
refactor: externalize summaries, minor fixes
colin-morpho Oct 25, 2024
cabfbf6
fix: avoid breaking other specs
colin-morpho Oct 25, 2024
51112e9
fix: formatting
colin-morpho Oct 25, 2024
3500204
fix: add getter and hashOfMarketParams invariant
colin-morpho Oct 27, 2024
66e34b8
fix: fix failing ci
colin-morpho Oct 28, 2024
8c4110a
fix: use getters for the morpho-blue project
colin-morpho Oct 28, 2024
59320f8
fix: update morpho-blue
colin-morpho Oct 28, 2024
3d95811
fix: improve comments
colin-morpho Oct 28, 2024
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
3 changes: 3 additions & 0 deletions .github/workflows/certora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ jobs:

matrix:
conf:
- ConsistentInstantiation
- Immutability
- MarketExists
- Liveness
- Reentrancy
- Reverts

steps:
- uses: actions/checkout@v4
Expand Down
11 changes: 11 additions & 0 deletions certora/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ This is checked in [`Reentrancy.spec`](specs/Reentrancy.spec).

This is checked in [`Immutability.spec`](specs/Immutability.spec).

## Reverts

This is checked in [`Reverts.spec`](specs/Reverts.spec) and [`MarketExists.spec`](specs/MarketExists.spec)

# Consitent Instantiation

This is checked in [`ConsistentInstantiation.spec`](specs/ConsistentInstantiation.spec).

### Liveness properties

This is checked in [`Liveness.spec`](specs/Liveness.spec).
Expand All @@ -41,6 +49,9 @@ The [`certora/specs`](specs) folder contains the following files:
- [`Liveness.spec`](specs/Liveness.spec) ensure that expected computations will always be performed.
For instance, pre-liquidations will always trigger a repay operation.
We also check that pre-liquidation can successfully be performed by passing shares to be repaid instead of the collateral ammount to be seized.
- [`Reverts.spec`](specs/Reverts.spec) checks the conditions for reverts and that inputs are correctly validated.
- [`ConsistentInstantiation.spec`](specs/ConsistentInstantiation.spec) checks the conditions for reverts are met in PreLiquidation constructor.
- [`MarketExists.spec`](specs/MarketExists.spec) checks that PreLiquidations can be instanciated only if the target market exists.

The [`certora/confs`](confs) folder contains a configuration file for each corresponding specification file.

Expand Down
29 changes: 29 additions & 0 deletions certora/confs/ConsistentInstantiation.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"files": [
"src/PreLiquidation.sol",
"lib/morpho-blue/certora/harness/MorphoHarness.sol",
"lib/morpho-blue/certora/harness/Util.sol",
],
"link": [
"PreLiquidation:MORPHO=MorphoHarness",
],
"parametric_contracts" : ["PreLiquidation"],
"solc_optimize" : "99999",
"solc_via_ir" : true,
"solc_map": {
"MorphoHarness": "solc-0.8.19",
"Util": "solc-0.8.19",
"PreLiquidation": "solc-0.8.27",
},
"verify": "PreLiquidation:certora/specs/ConsistentInstantiation.spec",
"prover_args": [
"-depth 5",
"-mediumTimeout 5",
"-timeout 3600",
"-smt_nonLinearArithmetic true",
"-solvers [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:lia2]",
],
"rule_sanity": "basic",
"server": "production",
"msg": "PreLiquidation ConsistentInstantiation",
}
25 changes: 25 additions & 0 deletions certora/confs/MarketExists.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"files": [
"src/PreLiquidation.sol",
"lib/morpho-blue/src/Morpho.sol",
],
"link": [
"PreLiquidation:MORPHO=Morpho"
],
"parametric_contracts" : ["Morpho"],
"solc_optimize" : "99999",
"solc_via_ir" : true,
"solc_map": {
"Morpho": "solc-0.8.19",
"PreLiquidation": "solc-0.8.27",
},
"verify": "PreLiquidation:certora/specs/MarketExists.spec",
"prover_args": [
"-depth 3",
"-mediumTimeout 20",
"-timeout 120"
],
"rule_sanity": "basic",
"server": "production",
"msg": "PreLiquidation MarketExists"
}
30 changes: 30 additions & 0 deletions certora/confs/Reverts.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"files": [
"src/PreLiquidation.sol",
"lib/morpho-blue/certora/harness/MorphoHarness.sol",
"lib/morpho-blue/certora/harness/Util.sol",
],
"link": [
"PreLiquidation:MORPHO=MorphoHarness",
],
"parametric_contracts" : ["PreLiquidation"],
"solc_optimize" : "99999",
"solc_via_ir" : true,
"solc_map": {
"PreLiquidation": "solc-0.8.27",
"MorphoHarness": "solc-0.8.19",
"Util": "solc-0.8.19",
},
"verify": "PreLiquidation:certora/specs/Reverts.spec",
"prover_args": [
"-depth 5",
"-mediumTimeout 40",
"-timeout 3600",
"-smt_nonLinearArithmetic true",
"-solvers [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:lia2]",

],
"rule_sanity": "basic",
"server": "production",
"msg": "PreLiquidation Reverts",
}
66 changes: 66 additions & 0 deletions certora/specs/ConsistentInstantiation.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0-or-later

import "SummaryLib.spec";

methods {
function _.market(PreLiquidation.Id) external => DISPATCHER(true);

function Util.libId(PreLiquidation.MarketParams) external
returns PreLiquidation.Id envfree;
}

//Ensure constructor requirements.

// Base case for mutually dependent invariants.
// Ensure that in a successfully deployed contract the preLLTV value is not zero.
invariant lltvNotZero()
0 < currentContract.LLTV
{
preserved {
requireInvariant preLIFNotZero();
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
}
}

// Ensure that a successfully deployed contract has a consistent preLLTV value.
invariant preLltvConsistent()
currentContract.PRE_LLTV < currentContract.LLTV
{
preserved {
requireInvariant preLIFNotZero();
}
}

// Ensure that a successfully deployed contract has a consistent preLCF values.
invariant preLCFConsistent()
currentContract.PRE_LCF_1 <= currentContract.PRE_LCF_2
&& currentContract.PRE_LCF_1 <= WAD()
{
preserved {
requireInvariant preLIFNotZero();
}
}

// Base case for mutually dependent invariants.
// Ensure that in a successfully deployed contract the preLIF value is not zero.
invariant preLIFNotZero()
0 < currentContract.PRE_LIF_1;

// Ensure that a successfully deployed contract has a consistent preLIF values.
invariant preLIFConsistent()
WAD() < currentContract.PRE_LIF_1
&& currentContract.PRE_LIF_1 <= currentContract.PRE_LIF_2
&& currentContract.PRE_LIF_2 <= summaryWDivDown(WAD(),currentContract.LLTV)
{
preserved {
requireInvariant lltvNotZero();
}
}

// Ensure that ID equals idToMarketParams(marketParams()).
invariant hashOfMarketParamsOf()
Util.libId(summaryMarketParams()) == currentContract.ID
{
preserved {
requireInvariant preLIFNotZero();
}
}
31 changes: 31 additions & 0 deletions certora/specs/MarketExists.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later

using Morpho as MORPHO;

methods {
function _.market(PreLiquidation.Id) external => DISPATCHER(true);
function MORPHO.market(PreLiquidation.Id) external
returns (uint128, uint128, uint128,uint128, uint128, uint128) envfree;
function _.price() external => NONDET;
}

persistent ghost uint256 lastTimestamp;

hook TIMESTAMP uint newTimestamp {
// Safe require because timestamps are guaranteed to be increasing.
require newTimestamp >= lastTimestamp;
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
// Safe require as it corresponds to some time very far into the future.
require newTimestamp < 2^63;
lastTimestamp = newTimestamp;
}

function lastUpdateIsNotNil(PreLiquidation.Id id) returns bool {
mathint lastUpdate;
(_,_,_,_,lastUpdate,_) = MORPHO.market(id);
return lastUpdate != 0;
}

// Ensure that the pre-liquidation contract interacts with a created market.

invariant marketExists()
lastUpdateIsNotNil(currentContract.ID);
Loading