# Adversary can permanently break reward distribution for percentage tier bounties by funding bounty then refunding after competition closes

Refunding a deposit after closeCompetition snapshots funding totals leaves TieredPercentageBounty short of funds, permanently bricking winner payouts when native MATIC is used.

- Payout: Contest reward
- Severity: high
- Program: Openq
- Credited: 8olidity
- Disclosed: 2023-01-30
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-02-openq-judging/issues/266
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-02-openq%3AH-5
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** TieredPercentageBountyV1 bounty contract (closeCompetition/refund flow)
**Root cause:** closeCompetition snapshots current token balance into fundingTotals for payout math, but deposits remain refundable afterward, so the balance can drop below the snapshotted total.
**Steps:**
1. Create a TieredPercentageBounty with a token whose current balance is zero.
2. Deposit 100 of that token (or native MATIC) with `_expiration` of 1 second.
3. Wait for competition to close; `closeCompetition` records fundingTotals from the current balance.
4. Call refund on the deposit after close, draining the token from the contract.
5. Winners call claim; payout reverts because contract lacks the snapshotted funds. For native MATIC, receive() is disabled so the contract cannot be re-funded, making it permanent.
**How found:** Code review of closeCompetition: noticed it snapshots balance into fundingTotals while refunds remain callable post-close, creating a mismatch between recorded and actual funds.
**Exploitation:** Attacker funds the bounty with a 1-second-expiration deposit, lets the competition close so fundingTotals snapshot includes their deposit, then refunds it. Payouts now exceed actual balance and every claim reverts. Using native MATIC (receive disabled) makes the break permanent; with ERC20 a donor could restore funds.
**Escalation:** Combined with refund-breaking methods to lock user funds permanently.
**Insight:** When a contract snapshots balance for later distribution, check whether any outflow path (refund, withdraw) stays open after the snapshot; native-token bounties with disabled receive() turn a temporary shortfall into a permanent DoS.
