# Cash-out from a successful buyout allows an attacker to drain Ether from the Buyout contract

Buyout.cash computes each payout from the stale initial ethBalance instead of the remaining balance, so successive cash-outs overpay and drain Ether from the contract.

- Payout: Contest reward
- Severity: high
- Program: Fractional
- Credited: berndartmueller
- Disclosed: 2022-09-27
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2022-07-fractional-findings/issues/440
- Library page: https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AH-08
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Buyout.sol cash() payout calculation in Fractional vault buyout module
**Root cause:** buyoutShare is computed as (tokenBalance * ethBalance) / (totalSupply + tokenBalance) using the original buyout ethBalance, which is never decremented after each cash-out, so the numerator stays constant while the denominator shrinks.
**Steps:**
1. Deploy vault with TOTAL_SUPPLY fractions; distribute fractions across wallets (e.g. 2000/6000/2000 or 5100 + 5x980).
2. Call `buyoutModule.start{value: 10 ether}(vault)` from a wallet holding >51% fractions; fractions and 10 ETH move into Buyout contract.
3. `vm.warp(rejectionPeriod + 1)` then call `buyoutModule.end(vault, burnProof)` to finalize the buyout.
4. Call `buyoutModule.cash(vault, burnProof)` from each fraction holder sequentially; each call burns fractions and pays `(tokenBalance * ethBalance) / (totalSupply + tokenBalance)` without reducing ethBalance.
5. Observe later cash-outs receive inflated shares (e.g. 2, 2.5, 3.3, 5, 10 ETH) totaling 22.8 ETH from a 10 ETH buyout.
**How found:** Code review of Buyout.cash: noticed buyoutShare uses buyoutInfo[_vault].ethBalance (initial balance) rather than remaining balance, and that ethBalance is never decremented after payout, implying the denominator shrinks while numerator stays fixed.
**Exploitation:** Attacker controls multiple wallets holding fractions of a self-created vault, starts a buyout with 10 ETH, waits out REJECTION_PERIOD, ends the buyout, then cashes out each wallet in sequence. Because ethBalance is never decremented, each successive cash-out yields a larger share, extracting more than the 10 ETH deposited and draining residual Ether held by the Buyout contract from other buyouts.
**Escalation:** Repeatable across multiple vaults and concurrent buyouts as long as the Buyout contract holds Ether; profit scales with number of controlled fraction wallets and available contract balance.
**Insight:** In share/payout math, check whether the pool balance used in the numerator is decremented after each withdrawal; a constant numerator with a shrinking totalSupply denominator means later withdrawers get progressively more, so model sequential cash-outs rather than a single-user calculation.
