Skip to content

Commit

Permalink
refactor: use native import invariant statement
Browse files Browse the repository at this point in the history
  • Loading branch information
QGarchery committed Apr 15, 2024
1 parent 7b0bd6e commit 533de14
Show file tree
Hide file tree
Showing 11 changed files with 37 additions and 88 deletions.
6 changes: 1 addition & 5 deletions certora/specs/ConsistentState.spec
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ function hasSupplyCapIsNotMarkedForRemoval(MetaMorphoHarness.Id id) returns bool
invariant supplyCapIsNotMarkedForRemoval(MetaMorphoHarness.Id id)
hasSupplyCapIsNotMarkedForRemoval(id);

function hasPendingCapIsNotMarkedForRemoval(MetaMorphoHarness.Id id) returns bool {
return pendingCap_(id).validAt > 0 => config_(id).removableAt == 0;
}

// Check that a market with a pending cap cannot be marked for removal.
invariant pendingCapIsNotMarkedForRemoval(MetaMorphoHarness.Id id)
hasPendingCapIsNotMarkedForRemoval(id);
pendingCap_(id).validAt > 0 => config_(id).removableAt == 0;
6 changes: 1 addition & 5 deletions certora/specs/DistinctIdentifiers.spec
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
import "PendingValues.spec";

function hasDistinctIdentifiers(uint256 i, uint256 j) returns bool {
return i != j => withdrawQueue(i) != withdrawQueue(j);
}

// Check that there are no duplicate markets in the withdraw queue.
invariant distinctIdentifiers(uint256 i, uint256 j)
hasDistinctIdentifiers(i, j)
i != j => withdrawQueue(i) != withdrawQueue(j)
{
preserved updateWithdrawQueue(uint256[] indexes) with (env e) {
requireInvariant distinctIdentifiers(indexes[i], indexes[j]);
Expand Down
9 changes: 2 additions & 7 deletions certora/specs/Enabled.spec
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ rule inWithdrawQueueIsEnabledPreservedUpdateWithdrawQueue(env e, uint256 i, uint
uint256 j;
require isInWithdrawQueueIsEnabled(indexes[i]);

// Safe require because it is a verified invariant.
require hasDistinctIdentifiers(indexes[i], j);
requireInvariant distinctIdentifiers(indexes[i], j);

updateWithdrawQueue(e, indexes);

Expand All @@ -45,13 +44,9 @@ function isWithdrawRankCorrect(MetaMorphoHarness.Id id) returns bool {
invariant withdrawRankCorrect(MetaMorphoHarness.Id id)
isWithdrawRankCorrect(id);

function isEnabledHasPositiveRank(MetaMorphoHarness.Id id) returns bool {
return config_(id).enabled => withdrawRank(id) > 0;
}

// Checks that enabled markets have a positive withdraw rank, according to the withdrawRank ghost variable.
invariant enabledHasPositiveRank(MetaMorphoHarness.Id id)
isEnabledHasPositiveRank(id);
config_(id).enabled => withdrawRank(id) > 0;

// Check that enabled markets are in the withdraw queue.
rule enabledIsInWithdrawQueue(MetaMorphoHarness.Id id) {
Expand Down
2 changes: 1 addition & 1 deletion certora/specs/LastUpdated.spec
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function hasGuardianRole(address user) returns bool {
}

// Check that any market with positive cap is created on Morpho Blue.
// The corresponding invariant cannot be verified because it requires to check properties on MetaMorpho and on Blue at the same time:
// The corresponding invariant is difficult to verify because it requires to check properties on MetaMorpho and on Blue at the same time:
// - on MetaMorpho, that it holds when the cap is positive for the first time
// - on Blue, that a created market always has positive last update
function hasPositiveSupplyCapIsUpdated(MetaMorphoHarness.Id id) returns bool {
Expand Down
12 changes: 4 additions & 8 deletions certora/specs/Liveness.spec
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,9 @@ rule canPauseSupply() {
rule canForceRemoveMarket(MetaMorphoHarness.MarketParams marketParams) {
MetaMorphoHarness.Id id = Util.libId(marketParams);

// Safe require because it is a verified invariant.
require hasSupplyCapIsEnabled(id);
// Safe require because it is a verified invariant.
require isEnabledHasConsistentAsset(marketParams);
// Safe require because it is a verified invariant.
require hasPositiveSupplyCapIsUpdated(id);
requireInvariant supplyCapIsEnabled(id);
requireInvariant enabledHasConsistentAsset(marketParams);
requireInvarinant positiveSupplyCapIsUpdated(id);

MetaMorphoHarness.MarketConfig config = config_(id);
require config.cap > 0;
Expand All @@ -55,8 +52,7 @@ rule canForceRemoveMarket(MetaMorphoHarness.MarketParams marketParams) {
assert !lastReverted;

require e3.msg.value == 0;
// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();
// Safe require as it corresponds to some time very far into the future.
require e3.block.timestamp < 2^63;
submitMarketRemoval@withrevert(e3, marketParams);
Expand Down
6 changes: 2 additions & 4 deletions certora/specs/MarketInteractions.spec
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ function summarySupply(MetaMorphoHarness.MarketParams marketParams, uint256 asse
assert data.length == 0;

MetaMorphoHarness.Id id = Util.libId(marketParams);
// Safe require because it is a verified invariant
require hasSupplyCapIsEnabled(id);
requireInvariant supplyCapIsEnabled(id);

// Check that all markets on which MetaMorpho supplies are enabled markets.
assert config_(id).enabled;
Expand All @@ -44,8 +43,7 @@ function summaryWithdraw(MetaMorphoHarness.MarketParams marketParams, uint256 as

MetaMorphoHarness.Id id = Util.libId(marketParams);
uint256 index = lastIndexWithdraw();
// Safe require because it is a verified invariant.
require isInWithdrawQueueIsEnabled(index);
requireInvariant inWithdrawQueueIsEnabled(index);

// Check that all markets from which MetaMorpho withdraws are enabled markets.
assert config_(id).enabled;
Expand Down
21 changes: 6 additions & 15 deletions certora/specs/PendingValues.spec
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,19 @@ invariant noBadPendingTimelock()
hasNoBadPendingTimelock()
{
preserved with (env e) {
// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;
}
}

function isSmallerPendingTimelock() returns bool {
return assert_uint256(pendingTimelock_().value) < timelock();
}
// Check that the pending timelock value is always strictly smaller than the current timelock value.
invariant smallerPendingTimelock()
isSmallerPendingTimelock()
assert_uint256(pendingTimelock_().value) < timelock()
{
preserved {
// safe require as it is a verified invariant.
require isPendingTimelockInRange();
// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant pendingTimelockInRange();
requireInvariant timelockInRange();
}
}

Expand All @@ -46,8 +39,7 @@ invariant noBadPendingCap(MetaMorphoHarness.Id id)
hasNoBadPendingCap(id)
{
preserved with (env e) {
// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;
}
Expand Down Expand Up @@ -76,8 +68,7 @@ invariant noBadPendingGuardian()
hasNoBadPendingGuardian()
{
preserved with (env e) {
// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;
}
Expand Down
6 changes: 1 addition & 5 deletions certora/specs/Range.spec
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,9 @@ function isPendingTimelockInRange() returns bool {
invariant pendingTimelockInRange()
isPendingTimelockInRange();

function isTimelockInRange() returns bool {
return timelock() <= maxTimelock() && timelock() >= minTimelock();
}

// Check that the timelock is bounded by the min timelock and the max timelock.
invariant timelockInRange()
isTimelockInRange()
timelock() <= maxTimelock() && timelock() >= minTimelock()
{
preserved {
requireInvariant pendingTimelockInRange();
Expand Down
12 changes: 4 additions & 8 deletions certora/specs/Reverts.spec
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ rule submitGuardianRevertCondition(env e, address newGuardian) {
address oldGuardian = guardian();
uint64 pendingGuardianValidAt = pendingGuardian_().validAt;

// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;

Expand All @@ -107,12 +106,10 @@ rule submitCapRevertCondition(env e, MetaMorphoHarness.MarketParams marketParams
uint256 pendingCapValidAt = pendingCap_(id).validAt;
MetaMorphoHarness.MarketConfig config = config_(id);

// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;
// Safe require because it is a verified invariant.
require hasSupplyCapIsEnabled(id);
requireInvariant supplyCapIsEnabled(id);

submitCap@withrevert(e, marketParams, newSupplyCap);

Expand All @@ -135,8 +132,7 @@ rule submitMarketRemovalRevertCondition(env e, MetaMorphoHarness.MarketParams ma
uint256 pendingCapValidAt = pendingCap_(id).validAt;
MetaMorphoHarness.MarketConfig config = config_(id);

// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;

Expand Down
36 changes: 12 additions & 24 deletions certora/specs/Timelock.spec
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ rule nextGuardianUpdateTimeDoesNotRevert() {
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;

// Safe require because it is a verified invariant.
require isTimelockInRange();
// Safe require because it is a verified invariant.
require isPendingTimelockInRange();
requireInvariant timelockInRange();
requireInvariant pendingTimelockInRange();

nextGuardianUpdateTime@withrevert(e);

Expand All @@ -38,8 +36,7 @@ rule guardianUpdateTime(env e_next, method f, calldataarg args) {
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;

// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();

uint256 nextTime = nextGuardianUpdateTime(e);
address prevGuardian = guardian();
Expand Down Expand Up @@ -71,10 +68,8 @@ rule nextCapIncreaseTimeDoesNotRevert(MetaMorphoHarness.Id id) {
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;

// Safe require because it is a verified invariant.
require isTimelockInRange();
// Safe require because it is a verified invariant.
require isPendingTimelockInRange();
requireInvariant timelockInRange();
requireInvariant pendingTimelockInRange();

nextCapIncreaseTime@withrevert(e, id);

Expand All @@ -90,8 +85,7 @@ rule capIncreaseTime(env e_next, method f, calldataarg args) {

MetaMorphoHarness.Id id;

// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();

uint256 nextTime = nextCapIncreaseTime(e, id);
uint184 prevCap = config_(id).cap;
Expand Down Expand Up @@ -121,10 +115,8 @@ rule nextTimelockDecreaseTimeDoesNotRevert() {
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;

// Safe require because it is a verified invariant.
require isTimelockInRange();
// Safe require because it is a verified invariant.
require isPendingTimelockInRange();
requireInvariant timelockInRange();
requireInvariant pendingTimelockInRange();

nextTimelockDecreaseTime@withrevert(e);

Expand All @@ -138,8 +130,7 @@ rule timelockDecreaseTime(env e_next, method f, calldataarg args) {
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;

// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();

uint256 nextTime = nextTimelockDecreaseTime(e);
uint256 prevTimelock = timelock();
Expand Down Expand Up @@ -169,10 +160,8 @@ rule nextRemovableTimeDoesNotRevert(MetaMorphoHarness.Id id) {
// Safe require as it corresponds to some time very far into the future.
require e.block.timestamp < 2^63;

// Safe require because it is a verified invariant.
require isTimelockInRange();
// Safe require because it is a verified invariant.
require isPendingTimelockInRange();
requireInvariant timelockInRange();
requireInvariant pendingTimelockInRange();

nextRemovableTime@withrevert(e, id);

Expand All @@ -188,8 +177,7 @@ rule removableTime(env e_next, method f, calldataarg args) {

MetaMorphoHarness.Id id;

// Safe require because it is a verified invariant.
require isTimelockInRange();
requireInvariant timelockInRange();

uint256 nextTime = nextRemovableTime(e, id);

Expand Down
9 changes: 3 additions & 6 deletions certora/specs/Tokens.spec
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ function summarySupply(MetaMorphoHarness.MarketParams marketParams, uint256 asse
assert onBehalf == currentContract;
assert data.length == 0;

// Safe require because it is a verified invariant.
require hasSupplyCapIsEnabled(Util.libId(marketParams));
// Safe require because it is a verified invariant.
require isEnabledHasConsistentAsset(marketParams);
requireInvariant supplyCapIsEnabled(Util.libId(marketParams));
requireInvariant enabledHasConsistentAsset(marketParams);

// Summarize supply as just a transfer for the purpose of this specification file, which is sound because only the properties about tokens are verified in this file.
Util.safeTransferFrom(marketParams.loanToken, currentContract, MORPHO(), assets);
Expand All @@ -50,8 +48,7 @@ function summaryWithdraw(MetaMorphoHarness.MarketParams marketParams, uint256 as

// Safe require because it is verifed in MarketInteractions.
require config_(id).enabled;
// Safe require because it is a verified invariant.
require isEnabledHasConsistentAsset(marketParams);
requireInvariant enabledHasConsistentAsset(marketParams);

// Use effective withdrawn assets if shares are given as input.
uint256 withdrawn = Util.withdrawnAssets(MORPHO(), id, assets, shares);
Expand Down

0 comments on commit 533de14

Please sign in to comment.