# BalancerStrategy.sol: _withdraw withdraws insufficient tokens

BalancerStrategy._withdraw scales the withdrawal amount by pricePerShare before passing to Balancer's EXACT_TOKENS_OUT exit, withdrawing too few WETH and reverting.

- Payout: Contest reward
- Severity: high
- Program: Tapioca DAO
- Credited: carrotsmuggler
- Disclosed: 2023-11-16
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-07-tapioca-findings/issues/978
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-40
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** BalancerStrategy.sol _withdraw / _vaultWithdraw (Balancer pool exit)
**Root cause:** _withdraw divides the needed amount by pool.getRate() (pricePerShare) before calling _vaultWithdraw, but Balancer exit kind 2 (EXACT_TOKENS_OUT) treats minAmountsOut as the exact token amount, so the scaled-down value withdraws fewer tokens than required.
**Steps:**
1. Call withdraw on BalancerStrategy with amount > queued.
2. Observe _withdraw computes toWithdraw = (amount - queued) * 10**decimals / pricePerShare.
3. _vaultWithdraw encodes userData = abi.encode(2, minAmountsOut, pool.balanceOf(this)) — kind 2 = exact tokens out.
4. Balancer returns exactly minAmountsOut tokens (PoC: 500 wei WETH on Optimism weth-reth pool via Tenderly).
5. require(amount <= wrappedNative.balanceOf(this)) reverts with 'BalancerStrategy: not enough' when no spare balance exists.
**How found:** Code reading of _withdraw: noticed the amount passed to _vaultWithdraw was scaled by pricePerShare, then verified via Tenderly that Balancer exit kind 2 withdraws exactly minAmountsOut, confirming the mismatch.
**Exploitation:** Not an attack; a functional bug causing user withdrawals to revert (DoS on withdraw path) when the contract lacks spare WETH.
**Insight:** Balancer exit kind 2 (EXACT_TOKENS_OUT) interprets minAmountsOut as the exact amount out, not a minimum — don't pre-scale by share price; verify exit-kind semantics against actual pool behavior on a fork.
