# Incorrect function call in BribeFactoryV3 recoverERC20AndUpdateData

BribeFactoryV3.recoverERC20AndUpdateData calls emergencyRecoverERC20 instead of the accounting-updating variant, leaving tokenRewardsPerEpoch stale and enabling reward over-distribution.

- Payout: Contest reward
- Severity: medium
- Program: Blackhole
- Credited: Egbe
- Disclosed: 2025-07-03
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-05-blackhole#m-11
- Library page: https://bugbountylibrary.com/r/c4%3A2025-05-blackhole%3AM-11
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:accounting-error vuln:reward-distribution

**Target:** BribeFactoryV3 / Bribe reward accounting contract
**Root cause:** Factory's recoverERC20AndUpdateData invokes IBribe.emergencyRecoverERC20, which transfers tokens but does not decrement tokenRewardsPerEpoch, unlike the intended recoverERC20AndUpdateData.
**Steps:**
1. Deploy BribeFactoryV3 and create a Bribe via `createBribe`
2. Mint tokens to the Bribe contract and record `tokenRewardsPerEpoch(token, epochStart)`
3. Call `bribeFactory.recoverERC20AndUpdateData([bribe],[token],[amount])` as owner
4. Observe `tokenRewardsPerEpoch` unchanged (still 0) though tokens were transferred out
**How found:** Code reading of the factory's recover function against the IBribe interface, noticing the call targets emergencyRecoverERC20 rather than the mapping-updating recoverERC20AndUpdateData.
**Exploitation:** Owner-only function; after recovery the stale tokenRewardsPerEpoch lets users claim rewards based on outdated values, potentially draining the Bribe contract's token balance.
**Insight:** When a factory wraps per-contract admin functions, diff the called selector against the sibling function that performs bookkeeping—emergency vs. accounting variants often differ only by a mapping update that silently breaks reward math.
