# VaderRouter.calculateOutGivenIn calculates wrong swap

VaderRouter.calculateOutGivenIn swapped reserves across pool0 and pool1 in the wrong order for 3-hop paths, returning incorrect swap quotes.

- Payout: Audit contest
- Severity: high
- Program: Vader Protocol
- Found by: cmichel
- Disclosed: 2022-02-10
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-11-vader-findings/issues/162
- Library page: https://bugbountylibrary.com/r/c4%3A2021-11-vader%3AH-16
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** VaderRouter.calculateOutGivenIn (Solidity router/view function)
**Root cause:** The nested VaderMath.calculateSwap calls pass pool1 reserves to the inner swap and pool0 reserves to the outer swap, reversing the intended foreign->native->foreign hop order and mismatching amountIn token with reserveIn.
**Steps:**
1. Read VaderRouter.calculateOutGivenIn 3-path branch.
2. Observe inner calculateSwap(amountIn, nativeReserve1, foreignReserve1) uses pool1 reserves though amountIn is a foreign token.
3. Observe outer calculateSwap uses foreignReserve0/nativeReserve0, i.e. pool0 applied second.
4. Compare to intended order: inner should be (amountIn, foreignReserve0, nativeReserve0), outer (result, nativeReserve1, foreignReserve1).
**How found:** Code review of the router's view function; noticed the inner swap's reserveIn did not correspond to the same token as amountIn, revealing the pool ordering was inverted relative to the documented foreign->native->foreign path.
**Insight:** In multi-hop quote functions, verify that the token of amountIn matches reserveIn of the first swap and that each hop's output token matches the next hop's input reserve; nested swap calls are a common place for pool/reserve ordering bugs.
