# LiquidityPool::requestRedeemWithPermit transaction can be front run with the different liquidity pool

Permit signature bound only to tranche token, not liquidity pool, letting a front-runner replay it to force redemption from a different pool.

- Payout: Audit contest
- Severity: medium
- Program: Centrifuge
- Found by: alexfilippov314
- Disclosed: 2023-10-11
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2023-09-centrifuge#m-02
- Library page: https://bugbountylibrary.com/r/c4%3A2023-09-centrifuge%3AM-02
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:race-window technique:source-review vuln:business-logic vuln:signature-replay

**Target:** LiquidityPool::requestRedeemWithPermit (EIP-2612 permit)
**Root cause:** The permit signature commits only to the tranche token's domain separator and spender/amount, not to the specific liquidity pool address, so a signature valid for one pool is valid for any pool sharing that tranche token.
**Steps:**
1. User signs EIP-2612 permit over trancheToken.DOMAIN_SEPARATOR with spender=investmentManager, value=maxMint, deadline=block.timestamp and submits `lPool.requestRedeemWithPermit(maxMint, investor, block.timestamp, v, r, s)`.
2. Attacker observes tx in mempool, extracts (v,r,s), and calls `newLPool.requestRedeemWithPermit(maxMint, investor, block.timestamp, v, r, s)` on a different pool with same tranche token, paying higher gas.
3. Attacker's tx executes first, consuming the permit nonce.
4. User's original tx reverts (`vm.expectRevert()`); if not cancelled before epoch end, the malicious request executes and user must claim the other currency.
**How found:** Noticed the permit's signed payload contains no pool identifier, only the tranche token domain, and reasoned that any pool with the same tranche token accepts the same signature; validated with a Foundry PoC deploying a second pool with a different currency.
**Exploitation:** Front-run the victim's requestRedeemWithPermit in the mempool with a higher-fee call to a sibling liquidity pool sharing the tranche token, consuming the permit nonce and forcing the victim's redemption into the attacker-chosen pool/currency.
**Escalation:** Loss amplified if the forced currency depegs (e.g. USDY), turning a nuisance into significant value loss.
**Insight:** When a permit/EIP-712 signature is verified by a token but consumed by a separate contract, check whether the signed struct binds the consuming contract address; if not, any sibling contract sharing the token can replay it.

