# Users Can Frontrun Calls to updateRewardsMetadata() And Claim Tokens Twice

Admin's updateRewardsMetadata() resets claim tracking via new merkle root; users frontrun the update to claim under both old and new roots, double-claiming rewards.

- Payout: Audit contest
- Severity: medium
- Program: Redacted Cartel
- Found by: leastwood
- Disclosed: 2022-05-11
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2022-02-redacted-cartel#m-12
- Library page: http://bugbountylibrary.com/r/c4%3A2022-02-redacted-cartel%3AM-12
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:race-window vuln:business-logic vuln:race-condition

**Target:** RewardDistributor / BribeVault merkle reward claims
**Root cause:** updateRewardsMetadata() increments reward.updateCount to reset the claimed tracker and installs a new merkle root built from current claim state; claims made between root generation and on-chain update are not reflected, so a user can claim under both roots.
**Steps:**
1. Admin computes new merkle root off-chain reflecting current claimers, then submits `updateRewardsMetadata()` with distributions.
2. Attacker observes the pending tx in mempool and frontruns it, calling claim() against the old merkle root to receive reward.
3. Admin tx lands, incrementing `reward.updateCount` and resetting claimed tracker with the new root.
4. Attacker claims again under the new root, which was built assuming they had not yet claimed, receiving reward twice.
**How found:** Code review of RewardDistributor's updateRewardsMetadata() and claim flow; noticed updateCount reset allows previously-claimed users to claim again, and that the off-chain root generation window creates a frontrun opportunity.
**Exploitation:** Mempool observation of the admin's updateRewardsMetadata() tx; frontrun claim() under the stale root, then claim again under the freshly installed root. Value extracted is a duplicate reward payout (or loss to other claimers if metadata fully replaces the list).
**Insight:** When a merkle distributor's root is regenerated from off-chain claim state, any claim landing between snapshot and root update is invisible to the new root; check whether claim tracking resets on metadata updates and whether the admin tx is frontrunnable.

