# The time constraint of selling fractions can be bypassed by directly transferring fraction tokens to the buyout contract

Buyout.end counts any fraction tokens held by the contract, so an attacker can start a cheap buyout then transfer tokens in to pass the 51% threshold and seize NFTs at half price.

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

**Target:** Buyout contract (ERC1155 fraction vault buyout)
**Root cause:** end() uses IERC1155.balanceOf(address(this), id) to decide success, which counts tokens transferred directly as well as those deposited via sellFractions, but only sellFractions is constrained by PROPOSAL_PERIOD.
**Steps:**
1. Attacker (or fresh account with 0 fraction balance) calls buyout start depositing 0 fraction tokens and 1 wei, setting fractionPrice to 0.01 wei.
2. No one can reject because no fraction tokens are locked in the Buyout contract.
3. In a single transaction, attacker calls `IERC1155(token).safeTransferFrom(attacker, buyout, id, 51, "")` to push >50% of fractions into the contract.
4. Attacker calls `end()`; balanceOf(address(this), id) now exceeds 50%, so buyout is treated as successful.
5. Attacker receives the vault NFTs having paid only ~51% of value; other holders' fractions are worthless.
**How found:** Code reading: noticed end() relies on balanceOf rather than a tracked deposit counter, and that only sellFractions enforces PROPOSAL_PERIOD, so direct transfers bypass the time constraint.
**Exploitation:** Attacker acquires 51 of 100 fraction tokens, starts a buyout with 0 tokens and 1 wei to set a near-zero fractionPrice, then in one tx transfers the 51 tokens directly to the Buyout contract and calls end(), passing the balance check and claiming the NFTs for roughly half their market value.
**Insight:** When a contract gates an action on token balanceOf, check whether tokens can be pushed in via safeTransferFrom outside the intended deposit path; balance-based thresholds are bypassable by direct transfers, especially when combined with a same-tx deposit+finalize.
