# Failed proposal can be committed again

Migration.commit can be replayed after a failed buyout because the 7-day commit window exceeds the 4-day buyout period, letting an attacker drain ETH from the migration contract.

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

**Target:** Migration.sol commit function / buyout contract
**Root cause:** Commit window (7 days from start) is longer than the buyout period (4 days), so commit can be called again on the same failed proposal. The contract also assumes it receives back the same fraction/ETH amounts it sent, not accounting for trading against the buyout.
**Steps:**
1. Create a vault and immediately migrate it, starting the migration timer.
2. Sell fractions to yourself to extract ETH while keeping fraction count under 51% so buyout cannot succeed.
3. Wait for the 4-day buyout period to fail; current time is still <7 days from start.
4. Call `commit` again on the same proposal; contract sends its current fraction balance (now inflated) and the proposal's ETH value.
5. Repeat to drain ETH from the migration contract, including ETH deposited for other proposals.
**How found:** Compared the 7-day commit window in Migration.sol against the 4-day buyout period, noticing the overlap allows replay; combined with the observation that the contract doesn't track actual returned fraction/ETH amounts from failed buyouts.
**Exploitation:** Attacker creates and migrates a vault, self-trades fractions to pull ETH out while staying below 51% to force buyout failure, then replays commit to send more ETH than originally supplied, netting profit and draining the shared migration contract balance.
**Escalation:** Repeated replay of commit drains all ETH held by the migration contract, including funds for other users' proposals.
**Insight:** When a state machine has a commit/execute window and a separate timeout, check whether the windows overlap so a failed action can be re-triggered; also check whether contracts assume 1:1 return of assets from external buyout/trade flows.
