# Router liquidity on receiving chain can be double-dipped by the user

In Connext's fulfill(), both addFunds and execute catch blocks transfer toSend to receivingAddress, letting a user revert both calls and double-credit router liquidity.

- Payout: Audit contest
- Severity: high
- Program: Connext
- Found by: 0xRajeev
- Disclosed: 2021-08-30
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2021-07-connext-findings/issues/46
- Library page: https://bugbountylibrary.com/r/c4%3A2021-07-connext%3AH-03
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** TransactionManager.sol fulfill() on receiving chain
**Root cause:** Both the addFunds() and execute() catch blocks call transferAsset() to txData.receivingAddress, so a failure in each path transfers toSend twice.
**Steps:**
1. User initiates cross-chain transfer locking 100 tokenAs on chain A, setting txData.callTo to an attacker contract on chain B.
2. On chain B, fulfill() calls IFulfillHelper.addFunds(); attacker contract makes it revert, triggering catch block that transfers toSend to txData.receivingAddress.
3. fulfill() then calls IFulfillHelper.execute(); attacker contract makes it revert too, triggering the second catch block which again transfers toSend to txData.receivingAddress.
4. Attacker receives 2x toSend (minus relayer fee) on chain B while only locking 1x on chain A.
**How found:** Code review of fulfill() error-handling paths in TransactionManager.sol; noticed duplicate transferAsset() calls in both catch blocks, likely a copy-paste bug.
**Exploitation:** Attacker deploys a callTo contract on the receiving chain whose addFunds() and execute() both revert, causing both catch blocks to transfer the full toSend amount to the attacker-controlled receivingAddress, draining router liquidity at 2x the locked amount.
**Insight:** Audit every catch/fallback branch for duplicated value-transfer side effects; a revert path that pays out is a classic double-spend vector when multiple helpers can each fail independently.

