Skip to content

Commit 0448402

Browse files
Merge pull request #689 from morpho-org/certora/improve-assets-accounting
[Certora] Improve assets accounting specification
2 parents 8e35224 + 9f1fe6d commit 0448402

File tree

2 files changed

+18
-13
lines changed

2 files changed

+18
-13
lines changed

certora/specs/AssetsAccounting.spec

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ methods {
55
function supplyShares(MorphoHarness.Id, address) external returns uint256 envfree;
66
function borrowShares(MorphoHarness.Id, address) external returns uint256 envfree;
77
function collateral(MorphoHarness.Id, address) external returns uint256 envfree;
8+
function totalSupplyShares(MorphoHarness.Id) external returns uint256 envfree;
9+
function totalBorrowShares(MorphoHarness.Id) external returns uint256 envfree;
810
function virtualTotalSupplyAssets(MorphoHarness.Id) external returns uint256 envfree;
911
function virtualTotalSupplyShares(MorphoHarness.Id) external returns uint256 envfree;
1012
function virtualTotalBorrowAssets(MorphoHarness.Id) external returns uint256 envfree;
@@ -32,21 +34,23 @@ function expectedBorrowAssets(MorphoHarness.Id id, address user) returns uint256
3234
return libMulDivUp(userShares, totalBorrowAssets, totalBorrowShares);
3335
}
3436

35-
// Check that the assets supplied are greater than the assets owned in the end.
37+
// Check that the assets supplied are greater than the increase in owned assets.
3638
rule supplyAssetsAccounting(env e, MorphoHarness.MarketParams marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) {
3739
MorphoHarness.Id id = libId(marketParams);
3840

3941
// Assume no interest as it would increase the total supply assets.
4042
require lastUpdate(id) == e.block.timestamp;
41-
// Assume no supply position to begin with.
42-
require supplyShares(id, onBehalf) == 0;
43+
// Safe require because of the sumSupplySharesCorrect invariant.
44+
require supplyShares(id, onBehalf) <= totalSupplyShares(id);
45+
46+
uint256 ownedAssetsBefore = expectedSupplyAssets(id, onBehalf);
4347

4448
uint256 suppliedAssets;
4549
suppliedAssets, _ = supply(e, marketParams, assets, shares, onBehalf, data);
4650

4751
uint256 ownedAssets = expectedSupplyAssets(id, onBehalf);
4852

49-
assert suppliedAssets >= ownedAssets;
53+
assert ownedAssetsBefore + suppliedAssets >= to_mathint(ownedAssets);
5054
}
5155

5256
// Check that the assets withdrawn are less than the assets owned initially.
@@ -64,22 +68,24 @@ rule withdrawAssetsAccounting(env e, MorphoHarness.MarketParams marketParams, ui
6468
assert withdrawnAssets <= ownedAssets;
6569
}
6670

67-
// Check that the assets borrowed are less than the assets owed in the end.
71+
// Check that the increase of owed assets are greater than the borrowed assets.
6872
rule borrowAssetsAccounting(env e, MorphoHarness.MarketParams marketParams, uint256 shares, address onBehalf, address receiver) {
6973
MorphoHarness.Id id = libId(marketParams);
7074

7175
// Assume no interest as it would increase the total borrowed assets.
7276
require lastUpdate(id) == e.block.timestamp;
73-
// Assume no outstanding debt to begin with.
74-
require borrowShares(id, onBehalf) == 0;
77+
// Safe require because of the sumBorrowSharesCorrect invariant.
78+
require borrowShares(id, onBehalf) <= totalBorrowShares(id);
79+
80+
uint256 owedAssetsBefore = expectedBorrowAssets(id, onBehalf);
7581

7682
// The borrow call is restricted to shares as input to make it easier on the prover.
7783
uint256 borrowedAssets;
7884
borrowedAssets, _ = borrow(e, marketParams, 0, shares, onBehalf, receiver);
7985

8086
uint256 owedAssets = expectedBorrowAssets(id, onBehalf);
8187

82-
assert borrowedAssets <= owedAssets;
88+
assert owedAssetsBefore + borrowedAssets <= to_mathint(owedAssets);
8389
}
8490

8591
// Check that the assets repaid are greater than the assets owed initially.
@@ -100,18 +106,17 @@ rule repayAssetsAccounting(env e, MorphoHarness.MarketParams marketParams, uint2
100106
assert repaidAssets >= owedAssets;
101107
}
102108

103-
// Check that the collateral assets supplied are greater than the assets owned in the end.
109+
// Check that the collateral assets supplied are equal to the increase of owned assets.
104110
rule supplyCollateralAssetsAccounting(env e, MorphoHarness.MarketParams marketParams, uint256 suppliedAssets, address onBehalf, bytes data) {
105111
MorphoHarness.Id id = libId(marketParams);
106112

107-
// Assume no collateral to begin with.
108-
require collateral(id, onBehalf) == 0;
113+
uint256 ownedAssetsBefore = collateral(id, onBehalf);
109114

110115
supplyCollateral(e, marketParams, suppliedAssets, onBehalf, data);
111116

112117
uint256 ownedAssets = collateral(id, onBehalf);
113118

114-
assert suppliedAssets == ownedAssets;
119+
assert ownedAssetsBefore + suppliedAssets == to_mathint(ownedAssets);
115120
}
116121

117122
// Check that the collateral assets withdrawn are less than the assets owned initially.

certora/specs/ExactMath.spec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ rule repayAllResetsBorrowExchangeRate(env e, MorphoHarness.MarketParams marketPa
5555
mathint sharesAfter = virtualTotalBorrowShares(id);
5656

5757
assert assetsAfter == 1;
58-
// There are at least as many shares as virtual shares.
58+
// There are at least as many shares as virtual shares, by definition of virtualTotalBorrowShares.
5959
}
6060

6161
// There should be no profit from supply followed immediately by withdraw.

0 commit comments

Comments
 (0)