forked from crytic/properties
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSecurityProps.sol
68 lines (58 loc) · 2.55 KB
/
SecurityProps.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
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
import {CryticERC4626PropertyBase} from "../util/ERC4626PropertyTestBase.sol";
contract CryticERC4626SecurityProps is CryticERC4626PropertyBase {
/// @notice verify `decimals()` should be larger than or equal to `asset.decimals()`
function verify_assetDecimalsLessThanVault() public {
assertGte(
vault.decimals(),
asset.decimals(),
"The vault's share token should have greater than or equal to the number of decimals as the vault's asset token."
);
}
/// @notice verify Accounting system must not be vulnerable to share price inflation attacks
function verify_sharePriceInflationAttack(
uint256 inflateAmount,
uint256 delta
) public {
// this has to be changed if there's deposit/withdraw fees
uint256 lossThreshold = 0.999 ether;
// vault is fresh
require(vault.totalAssets() == 0);
require(vault.totalSupply() == 0);
// these minimums are to prevent 1-wei rounding errors from triggering the property
require(inflateAmount > 10000);
uint256 victimDeposit = inflateAmount + delta;
address attacker = address(this);
// fund account
prepareAddressForDeposit(attacker, inflateAmount);
uint256 shares = vault.deposit(1, attacker);
// attack only works when pps=1:1 + new vault
require(shares == 1);
require(vault.totalAssets() == 1);
// inflate pps
asset.transfer(address(vault), inflateAmount - 1);
// fund victim
alice.fund(victimDeposit);
alice.approveFunds();
emit LogUint256("Amount of alice's deposit:", victimDeposit);
uint256 aliceShares = alice.depositFunds(victimDeposit);
emit LogUint256("Alice Shares:", aliceShares);
uint256 aliceWithdrawnFunds = alice.redeemShares(aliceShares);
emit LogUint256(
"Amount of tokens alice withdrew:",
aliceWithdrawnFunds
);
uint256 victimLoss = victimDeposit - aliceWithdrawnFunds;
emit LogUint256("Alice Loss:", victimLoss);
uint256 minRedeemedAmountNorm = (victimDeposit * lossThreshold) /
1 ether;
emit LogUint256("lossThreshold", lossThreshold);
emit LogUint256("minRedeemedAmountNorm", minRedeemedAmountNorm);
assertGt(
aliceWithdrawnFunds,
minRedeemedAmountNorm,
"Share inflation attack possible, victim lost an amount over lossThreshold%"
);
}
}