# Unauthorized reallocation in NudgeCampaign::handleReallocation and reward disruption vulnerability in NudgeCampaign::invalidateParticipations

Anyone can call Li.Fi executor to trigger NudgeCampaign.handleReallocation, then invalidations permanently drain claimable rewards, disrupting legitimate users.

- Payout: Contest reward
- Severity: medium
- Program: Nudge.xyz
- Credited: roccomania
- Disclosed: 2025-04-29
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-03-nudgexyz#m-01
- Library page: https://bugbountylibrary.com/r/c4%3A2025-03-nudgexyz%3AM-01
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:accounting-error vuln:business-logic vuln:dos

**Target:** NudgeCampaign Solidity contract (handleReallocation / invalidateParticipations)
**Root cause:** SWAP_CALLER_ROLE is granted to Li.Fi's public executor, so anyone can invoke handleReallocation; invalidateParticipations only decrements pendingRewards without returning fees to the claimable pool, creating a growing accounting discrepancy.
**Steps:**
1. Deploy campaign with WETH rewards and DAI as toToken; fund with 100k WETH.
2. Attacker approves DAI to Li.Fi erc20Proxy and calls `LIFI_EXECUTOR.swapAndExecute(transactionId, swapData, DAI, attacker, toAmount)` where swapData targets `campaign.handleReallocation(RANDOM_UUID, SWAP_CALLER, DAI, toAmount, "")`.
3. Operator calls `campaign.invalidateParticipations([pID])`, which subtracts pendingRewards but does not restore fees to claimableRewards.
4. Loop while `claimableRewardAmount() > 6000e18`, incrementing pID each iteration; ~157 iterations at ~432k gas each (~$99 total).
5. Observe final claimable reward reduced to ~5558e18 from 100k initial.
**How found:** Noticed SWAP_CALLER_ROLE is assigned to Li.Fi's executor which is callable by anyone, and that invalidateParticipations only decrements pendingRewards without crediting claimableRewards, then built a Foundry mainnet-fork PoC looping reallocation+invalidation.
**Exploitation:** Attacker uses Li.Fi executor as a permissionless proxy to call handleReallocation repeatedly, creating participations that get invalidated; each invalidation permanently removes reward fees from the claimable pool, depleting campaign rewards at low gas cost.
**Insight:** When a privileged role is granted to a third-party public entrypoint (e.g. Li.Fi executor), treat it as unauthenticated; also audit invalidation/refund paths for asymmetric accounting where subtracted amounts are not returned to the pool.
