# Wrong slippage protection on Token -> Token trades

Vader Router.swapWithSynthsWithLimit checks slippage on token-to-token swaps using the wrong input amount, letting users receive far less than their slip limit allows.

- Payout: Audit contest
- Severity: high
- Program: Vader Protocol
- Disclosed: 2021-06-14
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-04-vader-findings/issues/209
- Library page: https://bugbountylibrary.com/r/c4%3A2021-04-vader%3AH-15
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic

**Target:** Router.swapWithSynthsWithLimit (Solidity DEX router)
**Root cause:** For the second leg (base->outputToken) the slippage check passes inputAmount from the first leg instead of the base output of the first trade, comparing an unrelated token amount against the second pair's base reserve.
**Steps:**
1. Call `Router.swapWithSynthsWithLimit` with a token->token trade (inputToken != outputToken) and a slipLimit.
2. Router performs leg 1: inputToken->base, then leg 2: base->outputToken.
3. Leg 2 check: `require(iUTILS(UTILS()).calcSwapSlip(inputAmount, iPOOLS(POOLS).getBaseAmount(outputToken)) <= slipLimit)` uses inputAmount (leg-1 token amount) rather than leg-1 base output.
4. Result: check is meaningless; trade either reverts when it should pass or executes with slippage exceeding the user's limit.
**How found:** Code review of the two-leg swap path: noticed the second require reuses inputAmount from the first trade instead of the intermediate base amount, mismatching units against getBaseAmount(outputToken).
**Exploitation:** Not a theft primitive by itself; a user submitting a token-to-token swap can be filled at worse-than-specified slippage (or blocked) because the second-leg guard compares the wrong quantity, so MEV/sandwich or thin liquidity can extract value beyond the user's stated protection.
**Insight:** In multi-hop swap routers, verify each hop's slippage/min-out check consumes the previous hop's output, not the original input; unit mismatch between token amount and base reserve silently voids the guard.

