# Refunding logic with multiple deposits is first mover take all

OpenQ DepositManager computed refundable funds from contract balance minus locked, so with multiple funders the first refunder drained all remaining funds.

- Payout: Contest reward
- Severity: medium
- Program: Openq
- Credited: chaduke
- Disclosed: 2023-01-30
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-02-openq-judging/issues/257
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-02-openq%3AM-5
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** DepositManagerV1 refund logic (Solidity bounty contract)
**Root cause:** Available refundable funds are derived from the bounty contract's live balance minus locked balance rather than per-deposit accounting, so no record ties payouts to specific deposits.
**Steps:**
1. User A and User B each deposit 10,000 USDC into an Ongoing bounty (balance 20,000).
2. Bounty pays out 10,000 USDC in awards, leaving 10,000 USDC.
3. Both deposits expire; User A calls refund first.
4. Refund computes available = balance - locked = 10,000 and pays all of it to User A.
5. User B's refund yields 0.
**How found:** Code review of DepositManagerV1 refund logic noticing available funds computed from contract balance minus locked balance, then reasoning about multiple concurrent deposits and payout timing.
**Exploitation:** A depositor waits until deposits expire and calls refund before other funders; the refund function pays out the entire remaining contract balance (balance minus locked) to the first caller, forcing other funders to absorb the award payouts.
**Insight:** When refundable amount is derived from live contract balance rather than per-depositor accounting, any shared pool with multiple funders becomes first-come-first-served; check refund/withdraw paths for balance-derived math whenever deposits are commingled.
