# BondingTax has invalid slippage implementation

BondingTax computes minOutput from live getAmountsOut spot price, so the slippage check always passes and treasury swaps accept any price.

- Payout: Contest reward
- Severity: medium
- Program: Virtuals Protocol
- Credited: oakcobalt
- Disclosed: 2025-08-04
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-04-virtuals-protocol#m-06
- Library page: https://bugbountylibrary.com/r/c4%3A2025-04-virtuals-protocol%3AM-06
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** BondingTax.sol swapForAsset Uniswap V2 router swap
**Root cause:** minOutput is derived from router.getAmountsOut, which reflects the same manipulable spot price used for execution, so the check is a fixed fraction of the actual result and always passes.
**Steps:**
1. Call swapForAsset which reads amountsOut = router.getAmountsOut(amount, path)
2. Compute minOutput = expectedOutput * (10000 - _slippage) / 10000 from that same spot quote
3. Execute router.swapExactTokensForTokens(amount, minOutput, path, treasury, deadline)
4. Since minOutput tracks the live price, any adverse price movement still satisfies the check
**How found:** Code review of swapForAsset noticed minOutput was computed from getAmountsOut, the same dynamic spot source used for the swap, making the slippage bound self-referential.
**Exploitation:** Treasury tax tokens are swapped at whatever the current pool price is; a price drop between quote and execution (or manipulation) is accepted, so treasury receives less than the intended oracle-based minimum.
**Insight:** When auditing slippage guards, check whether the min-output reference is an independent oracle or the same pool quote used for execution; if both come from getAmountsOut, the guard is vacuous.
