forked from crytic/properties
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBadAllowanceUpdate.sol
85 lines (62 loc) · 2.8 KB
/
BadAllowanceUpdate.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
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
import {ERC20} from "solmate/src/tokens/ERC20.sol";
import {ERC4626} from "solmate/src/mixins/ERC4626.sol";
import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol";
import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {CryticERC4626PropertyTests} from "../../ERC4626PropertyTests.sol";
import {TestERC20Token} from "../../util/TestERC20Token.sol";
import {CryticERC4626RedeemUsingApproval} from "../../properties/RedeemUsingApprovalProps.sol";
contract BadAllowanceUpdate is ERC4626 {
using FixedPointMathLib for uint256;
using SafeTransferLib for ERC20;
uint256 private _totalAssets;
constructor(ERC20 _asset) ERC4626(_asset, "Test Vault", _asset.symbol()) {}
function totalAssets() public view virtual override returns (uint256) {
return _totalAssets;
}
function beforeWithdraw(uint256 assets, uint256) internal override {
_totalAssets = _totalAssets - assets;
}
function afterDeposit(uint256 assets, uint256) internal override {
_totalAssets = _totalAssets + assets;
}
function withdraw(
uint256 assets,
address receiver,
address owner
) public override returns (uint256 shares) {
shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up.
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
// if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
function redeem(
uint256 shares,
address receiver,
address owner
) public override returns (uint256 assets) {
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
// if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
// Check for rounding error since we round down in previewRedeem.
require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS");
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
}
contract TestHarness is CryticERC4626RedeemUsingApproval {
constructor() {
TestERC20Token _asset = new TestERC20Token("Test Token", "TT", 18);
ERC4626 _vault = new BadAllowanceUpdate(ERC20(address(_asset)));
initialize(address(_vault), address(_asset), false);
}
}