# FlywheelCore.setBooster() can be used to steal unclaimed rewards

FlywheelCore.setBooster lets an authorized user swap in a malicious booster returning inflated boostedBalanceOf values, then claimRewards drains other users' unclaimed rewards.

- Payout: Audit contest
- Severity: medium
- Program: Tribe
- Found by: IllIllI
- Disclosed: 2022-07-14
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2022-04-xtribe#m-06
- Library page: http://bugbountylibrary.com/r/c4%3A2022-04-xtribe%3AM-06
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity vuln:access-control vuln:business-logic vuln:reward-distribution

**Target:** FlywheelCore reward accounting contract (Solidity)
**Root cause:** setBooster is callable by any authorized address with no timelock or restriction, and boostedBalanceOf from the booster directly determines reward accrual while reward tokens are custodied globally in flywheelRewards rather than per-user.
**Steps:**
1. Authorized attacker calls `setBooster(maliciousBooster)` where maliciousBooster.boostedBalanceOf returns 0 for other users and arbitrary large values for attacker-controlled addresses.
2. Attacker calls `accrue(strategy, attacker)` so supplierTokens = inflated boostedBalanceOf, computing supplierDelta = (supplierTokens * deltaIndex) / ONE and storing into rewardsAccrued[attacker].
3. Attacker calls `claimRewards(attacker)`; FlywheelCore transfers accrued amount via `rewardToken.safeTransferFrom(address(flywheelRewards), attacker, accrued)`.
4. Attacker can unset the booster in the same block after accruing, since BaseFlywheelRewards pre-approved max allowance to the core.
**How found:** Code review of setBooster's requiresAuth-only guard combined with the accrue path reading boostedBalanceOf from an externally swappable booster, and observing that reward tokens are held globally by flywheelRewards with infinite approval to the core.
**Exploitation:** A privileged/authorized address sets a malicious booster, accrues inflated rewards for itself, claims them from the shared flywheelRewards custody balance, and resets the booster — all in one block — extracting other users' unclaimed reward tokens.
**Insight:** When reward accrual reads balances from a swappable external contract (booster) and payouts come from a shared custody address with max approval, any privileged setter becomes a rug vector; check whether accrual inputs are attacker-influenceable and whether custody is per-user or pooled.

