# minTokenAmounts_ is useless in new configuration and doesn't provide any real slippage protection

BLVaultLido.withdraw skims oracle-arb wstETH to treasury after pool slippage checks, so minTokenAmounts_ never bounds what the user actually receives.

- Payout: Contest reward
- Severity: high
- Program: Olympus
- Credited: 0x52
- Disclosed: 2023-03-16
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-03-olympus-judging/issues/3
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-2
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** BLVaultLido.withdraw (Boosted Liquidity vault, Balancer pool exit)
**Root cause:** withdraw applies minTokenAmounts_ only to the Balancer pool exit, then skims any wstETH above the oracle-expected amount to the treasury before returning the remainder to the user, so the user-facing amount is never bounded by the slippage parameter.
**Steps:**
1. Call `BLVaultLido.withdraw(lpAmount_, minTokenAmounts_)` with minTokenAmounts_ set to the user's desired minimum wstETH out.
2. `_exitBalancerPool` enforces minTokenAmounts_ against pool output only.
3. Contract computes `expectedWstethAmountOut = ohmAmountOut * wstethOhmPrice / _OHM_DECIMALS` from the oracle.
4. If `wstethAmountOut > expectedWstethAmountOut`, the excess is transferred to `TRSRY()` (treasury).
5. User receives only `wstethToReturn` (min of actual and oracle-expected), which can be below minTokenAmounts_.
**How found:** Code reading of withdraw flow: noticed minTokenAmounts_ is passed only to `_exitBalancerPool`, while the treasury skim and final transfer happen afterward, so the parameter cannot bound the user's received amount.
**Exploitation:** When the pool price diverges from the oracle price in the user's favor, the arb portion is skimmed to the treasury after the pool slippage check, so the user's realized wstETH is less than minTokenAmounts_ without any revert; no external attacker needed, loss arises from oracle/pool mismatch.
**Insight:** When a function has a user-supplied slippage/min-out parameter, trace every transfer after the guarded call: any post-check skim, fee, or oracle-based adjustment silently voids the guarantee.
