# BathPair.sol#rebalancePair() can be front run to steal the pending rebalancing amount

BathToken share price jumps when strategist calls rebalancePair; attacker front-runs with a large deposit, then withdraws to steal half the pending rebalancing yield.

- Payout: Contest reward
- Severity: high
- Program: Rubicon
- Credited: WatchPug
- Disclosed: 2022-08-01
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-05-rubicon-findings/issues/337
- Library page: https://bugbountylibrary.com/r/c4%3A2022-05-rubicon%3AH-09
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:race-window technique:source-review vuln:accounting-error vuln:business-logic

**Target:** BathToken/BathPair vault share accounting (Solidity)
**Root cause:** underlyingBalance() only counts current token balance plus outstandingAmount, ignoring pending rebalancing amount, so pricePerShare surges abruptly when rebalancePair transfers underlying tokens in.
**Steps:**
1. Observe strategist's pending `rebalancePair()` tx in mempool; underlyingBalance=100,000 USDC, pending rebalance=1000 USDC
2. Submit `deposit(100,000 USDC)` with higher gas price to acquire ~50% of shares
3. After rebalancePair mines, call `withdraw()` to redeem ~100,500 USDC
**How found:** Code reading of BathToken.underlyingBalance()/removeFilledTradeAmount: noticed filled non-underlying assets awaiting rebalancing are excluded from share price, so each rebalancePair causes a sudden pricePerShare surge — a classic deposit-front-run-sandwich on vault share price.
**Exploitation:** Attacker watches mempool for strategist rebalancePair, deposits large amount just before it to capture a large share at the pre-surge price, then withdraws immediately after the underlying tokens land, pocketing a proportional cut of the pending rebalancing amount in ~1 block.
**Insight:** In vault-style share accounting, any external action that suddenly injects value (rebalance, harvest, fee claim) creates a deposit/withdraw sandwich; check whether pending-but-unrealized value is excluded from underlyingBalance()/pricePerShare.
