forked from crytic/properties
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRoundingProps.sol
141 lines (127 loc) · 5.72 KB
/
RoundingProps.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
import {CryticERC4626PropertyBase} from "../util/ERC4626PropertyTestBase.sol";
import {CryticERC4626VaultProxy} from "./VaultProxy.sol";
contract CryticERC4626Rounding is
CryticERC4626PropertyBase,
CryticERC4626VaultProxy
{
/// @notice verifies shares may never be minted for free using previewDeposit()
function verify_previewDepositRoundingDirection() public {
require(supportsInternalTestingIface);
uint256 sharesMinted = vault.previewDeposit(0);
assertEq(
sharesMinted,
0,
"previewDeposit() must not mint shares at no cost"
);
}
/// @notice verifies shares may never be minted for free using previewMint()
function verify_previewMintRoundingDirection(uint256 shares) public {
require(supportsInternalTestingIface);
require(shares > 0);
uint256 tokensConsumed = vault.previewMint(shares);
assertGt(
tokensConsumed,
0,
"previewMint() must never mint shares at no cost"
);
}
/// @notice verifies shares may never be minted for free using convertToShares()
function verify_convertToSharesRoundingDirection() public {
require(supportsInternalTestingIface);
// note: the correctness of this property can't be tested using solmate as a reference impl. 0/n=0. best case scenario, some other property gets set off.
uint256 tokensWithdrawn = vault.convertToShares(0);
assertEq(
tokensWithdrawn,
0,
"convertToShares() must not allow shares to be minted at no cost"
);
}
/// @notice verifies tokens may never be withdrawn for free using previewRedeem()
function verify_previewRedeemRoundingDirection() public {
require(supportsInternalTestingIface);
uint256 tokensWithdrawn = vault.previewRedeem(0);
assertEq(
tokensWithdrawn,
0,
"previewRedeem() must not allow assets to be withdrawn at no cost"
);
}
/// @notice verifies tokens may never be withdrawn for free using previewWithdraw()
function verify_previewWithdrawRoundingDirection(uint256 tokens) public {
require(supportsInternalTestingIface);
require(tokens > 0);
uint256 sharesRedeemed = vault.previewWithdraw(tokens);
assertGt(
sharesRedeemed,
0,
"previewWithdraw() must not allow assets to be withdrawn at no cost"
);
}
/// @notice verifies tokens may never be withdrawn for free using convertToAssets()
function verify_convertToAssetsRoundingDirection() public {
require(supportsInternalTestingIface);
// note: the correctness of this property can't be tested using solmate as a reference impl. 0/n=0. best case scenario, some other property gets set off.
uint256 tokensWithdrawn = vault.convertToAssets(0);
assertEq(
tokensWithdrawn,
0,
"convertToAssets() must not allow assets to be withdrawn at no cost"
);
}
/// @notice Indirectly verifies the rounding direction of convertToShares/convertToAssets is correct by attempting to
/// create an arbitrage by depositing, then withdrawing
function verify_convertRoundTrip(uint256 amount) public {
require(supportsInternalTestingIface);
uint256 sharesMinted = vault.convertToShares(amount);
uint256 tokensWithdrawn = vault.convertToAssets(sharesMinted);
assertGte(
amount,
tokensWithdrawn,
"A profit was extractable from a convertTo round trip (deposit, then withdraw)"
);
}
/// @notice Indirectly verifies the rounding direction of convertToShares/convertToAssets is correct by attempting to
/// create an arbitrage by withdrawing, then depositing
function verify_convertRoundTrip2(uint256 amount) public {
require(supportsInternalTestingIface);
uint256 tokensWithdrawn = vault.convertToAssets(amount);
uint256 sharesMinted = vault.convertToShares(tokensWithdrawn);
assertGte(
amount,
sharesMinted,
"A profit was extractable from a convertTo round trip (withdraw, then deposit)"
);
}
/// @notice verifies Shares may never be minted for free using deposit()
function verify_depositRoundingDirection() public {
require(supportsInternalTestingIface);
uint256 shares = vault.deposit(0, address(this));
assertEq(shares, 0, "Shares must not be minted for free");
}
/// @notice verifies Shares may never be minted for free using mint()
function verify_mintRoundingDirection(uint256 shares) public {
require(supportsInternalTestingIface);
require(shares > 0);
uint256 tokensDeposited = vault.mint(shares, address(this));
assertGt(tokensDeposited, 0, "Shares must not be minted for free");
}
/// @notice verifies tokens may never be withdrawn for free using withdraw()
function verify_withdrawRoundingDirection(uint256 tokens) public {
require(supportsInternalTestingIface);
require(tokens > 0);
uint256 sharesRedeemed = vault.withdraw(
tokens,
address(this),
address(this)
);
assertGt(sharesRedeemed, 0, "Token must not be withdrawn for free");
}
/// @notice verifies tokens may never be withdrawn for free using redeem()
function verify_redeemRoundingDirection() public {
require(supportsInternalTestingIface);
uint256 tokensWithdrawn = vault.redeem(0, address(this), address(this));
assertEq(tokensWithdrawn, 0, "Tokens must not be withdrawn for free");
}
}