# liquidatePosition() liquidator can construct malicious data to steal the borrower's profit

Liquidator-controlled swap `data` in Particle's liquidatePosition lets attacker route swap through malicious pool/router and pocket the borrower's residual collateral profit.

- Payout: Contest reward
- Severity: high
- Program: Particle Protocol
- Credited: bin2chen
- Disclosed: 2024-01-26
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2023-12-particle-findings/issues/26
- Library page: https://bugbountylibrary.com/r/c4%3A2023-12-particle%3AH-03
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:business-logic vuln:liquidation

**Target:** ParticlePositionManager.liquidatePosition() swap routing via Base.swap(params.data)
**Root cause:** liquidatePosition passes liquidator-supplied `data` straight into Base.swap, so the liquidator fully controls the DEX/pool/router and only needs amountReceived >= repay minimum; any excess collateral+premium is diverted.
**Steps:**
1. Open a long position, add premium, warp past expiry and set RenewalCutoffTime so liquidatePosition is callable.
2. Deploy fakeErc20 and create a Uniswap V3 pool WETH/fakeErc20, initialize and mint liquidity.
3. Compute amountSwap = collateral + tokenPremium - amountToAdd - tokenOwed - liquidationReward.
4. Build `data` = exactInputSingle(tokenIn=WETH, tokenOut=fakeErc20, recipient=attacker, amountIn=amountSwap, amountOutMinimum=0).
5. In fakeErc20.transfer() reentrancy, transfer just enough USDC (payUsdcToLp) to ParticlePositionManager to satisfy repayment.
6. Call `particlePositionManager.liquidatePosition(ClosePositionParams(lienId, amountSwap, data), borrower)`; swap drains WETH to fake pool, attacker keeps collateral - repay.
**How found:** Code-read of liquidatePosition -> _closePosition -> Base.swap(params.data): noticed `data` is fully attacker-controlled and only amountReceived is validated, so the swap destination/pool is unconstrained.
**Exploitation:** Liquidator supplies malicious swap `data` pointing at attacker-controlled pool/token; during the swap callback the fake token transfers the minimum USDC repayment to the position manager, satisfying the check while the attacker retains the difference between full collateral+premium and the minimum repay (PoC: ~1118 USDC profit).
**Escalation:** Judge noted the same primitive applies to 1inch AggregationRouterV4/V5 (attacker-controlled `caller`/executor) and Uniswap SwapRouter path control, making it exploitable with normal ERC20s, not just malicious tokens.
**Insight:** When a contract forwards user-supplied calldata to an external router/aggregator, the router's own arbitrary-call or path parameters (1inch `caller`, Uniswap `path`) let the caller redirect the swap and skim the surplus; check whether only a minimum-return is enforced rather than the actual recipient/pool.
