# Wrong calculation in function LBRouter._getAmountsIn make user lose a lot of tokens when swap through JoePair (most of them will gifted to JoePair freely)

LBRouter._getAmountsIn mis-parenthesized the JoePair amountIn formula, overcharging users who swap exact-output through legacy JoePair pools.

- Payout: Contest reward
- Severity: high
- Program: Trader Joe
- Credited: KIntern\_NA
- Disclosed: 2022-12-22
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2022-10-traderjoe-findings/issues/400
- Library page: https://bugbountylibrary.com/r/c4%3A2022-10-traderjoe%3AH-04
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:regression technique:source-review vuln:accounting-error vuln:business-logic

**Target:** LBRouter._getAmountsIn / swapTokensForExactTokens on JoePair (Uniswap V2 style) pools
**Root cause:** Denominator written as `_reserveOut - amountOut_ * 997` instead of `(_reserveOut - amountOut_) * 997`, breaking the constant-product inverse formula for exact-output swaps.
**Steps:**
1. Call `swapTokensForExactTokens` with a path routed through a JoePair (`_binStep == 0`).
2. `_getAmountsIn` computes `amountsIn[i-1] = (_reserveIn * amountOut_ * 1_000) / (_reserveOut - amountOut_ * 997) + 1`.
3. Router transfers this inflated `amountsIn[0]` to the pair via `safeTransferFrom`.
4. `_swapTokensForExactTokens` sets `amountOut = amountsIn[i+1]` (user's desired out) and calls `IJoePair.swap()`, returning only the exact desired output.
5. Excess tokenIn remains in the pair; user loses the difference.
6. PoC: `forge test --match-test testBugSwapJoeV1PairWithLBRouter --fork-url https://rpc.ankr.com/avalanche --fork-block-number 21437560 -vv`.
**How found:** Code review of the JoePair branch in `_getAmountsIn`; noticed the rounding formula diverged from Uniswap V2's `getAmountsIn`, derived the correct constant-product inverse by hand, and confirmed with a Foundry fork test showing revert with `LBRouter__MaxAmountInExceeded` and massive overpayment.
**Exploitation:** Any user performing an exact-output swap through a legacy JoePair via LBRouter overpays tokenIn; the surplus is effectively gifted to the pair/LPs. No attacker capital needed—loss occurs on normal router usage.
**Insight:** When a router reimplements Uniswap V2 `getAmountsIn`, diff the parenthesization against the canonical `(reserveOut - amountOut) * 997` form; a single misplaced bracket silently inflates required input and is invisible unless you fork-test exact-output swaps against real reserves.
