# reLPContract.reLP() is susceptible to sandwich attack due to user control over bond()

Dopex bond() lets users indirectly trigger reLP()'s UniswapV2 remove/swap/add sequence, enabling a flash-loan sandwich that skims ~2.5% of pool TVL.

- Payout: Contest reward
- Severity: medium
- Program: Dopex
- Credited: peakbolt
- Disclosed: 2023-12-29
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-08-dopex-findings/issues/976
- Library page: https://bugbountylibrary.com/r/c4%3A2023-08-dopex%3AM-08
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:chained vuln:business-logic vuln:flash-loan vuln:oracle-manipulation

**Target:** RdpxV2Core.bond() / reLPContract.reLP() UniswapV2 rDPX/ETH pool
**Root cause:** bond() calls reLP() which performs removeLiquidity, swapExactTokensForTokens and addLiquidity on the rDPX/ETH UniV2 pool, and the user controls the bond amount, so they control the timing and size of these pool transactions without needing a mempool frontrun.
**Steps:**
1. Flash loan ETH (e.g. 1500 ETH).
2. Swap ETH->rDPX on UniV2 rDPX/ETH pool to pump rDPX price.
3. Call `rdpxV2Core.bond(amount, rdpxBondId, to)` with isReLPActive, indirectly invoking `reLPContract.reLP(amount)`.
4. reLP() calls removeLiquidity() at manipulated price, then swapExactTokensForTokens() ETH->rDPX, then addLiquidity().
5. Swap rDPX back to ETH, repay flash loan; repeat bond() iterations while WETH collateral remains in PerpetualAtlanticVault.
**How found:** Code reading of bond() showing it ends with `IReLP(...).reLP(_amount)`; recognized the user-controlled bond amount gives indirect control over the UniV2 remove/swap/add sequence, removing the need for mempool frontrunning and letting the attacker size the trade.
**Exploitation:** Attacker flash-loans WETH, imbalances the UniV2 pool, triggers bond() to force reLP()'s remove/swap/add at skewed prices, then reverses the swap. POC on Arb mainnet fork: ~800 ETH TVL pool, 1500 ETH flash loan, 5 bond() iterations yields ~22 ETH profit (~20.65 ETH net of 0.09% flash fee), ~2.58% of TVL; repeatable until vault WETH collateral exhausted.
**Escalation:** Repeat bond() iterations to compound profit; scale with larger bond amounts to increase LP removed per call; wait for more WETH deposits to vault to continue.
**Insight:** When a user-callable function internally performs AMM liquidity removal/swap/add, the caller effectively owns the 'button' to force pool rebalancing at a chosen size and moment — check whether slippage/oracle guards actually bound the loss versus fair LP valuation, and whether the trigger amount is user-controlled.
