The clawback function in ERC20Incentive.sol allows the contract owner to reclaim a portion or all of the reward tokens. While this might seem reasonable for other incentive strategies, it becomes problematic when the strategy is set to RAFFLE.
Vulnerability Detail
The issue is that the condition claims > 0 only checks if there have been any claims, not specifically if there are active raffle entries. If someone has claimed a "ticket" for the raffle, claims will be greater than 0, even though the raffle hasn't been drawn yet. This allows the owner to claw back the entire reward even after users have entered the raffle.
if (strategy == Strategy.RAFFLE) {
// Ensure the amount is the full reward and there are no raffle entries, then reset the limit
if (amount != reward || claims > 0) revert BoostError.ClaimFailed(msg.sender, abi.encode(claim_));
limit = 0;
}
// ... rest of the function ...
Attack Scenario:
Deploy or Identify a Contract: The attacker either deploys their own ERC20Incentive contract with the RAFFLE strategy or identifies an existing one with a significant reward.
Promote the Raffle: The attacker might actively promote the raffle to attract participants and encourage them to make entries (claim their "tickets").
Clawback the Reward: Once a few users have entered the raffle (increasing the claims counter), the attacker (as the contract owner) calls the clawback function, setting the amount to the full reward value.
Reward Drained: The clawback function's condition (amount != reward || claims > 0) is met because claims is now greater than 0. The owner successfully reclaims the entire reward, leaving nothing for the raffle participants.
Raffle Becomes Pointless: When the drawRaffle function is eventually called, there's no reward to distribute, leaving the participants with nothing despite their entries.
Impact
Unfair Raffle: Participants could be misled into entering a raffle where the owner has already reclaimed the entire reward, making their participation pointless. This undermines the fairness and trust in the incentive mechanism.
By checking entries.length > 0, the clawback function will revert if there are any participants in the raffle, ensuring that the reward cannot be reclaimed after users have entered.
Let's say Alice deploys an ERC20Incentive contract with a 1000 token reward and the RAFFLE strategy. Bob and Carol both call the claim function to enter the raffle. Now, claims is 2, and entries contains both Bob and Carol's addresses.
Without the mitigation: Alice could call clawback and reclaim all 1000 tokens, even though Bob and Carol have entered the raffle.
With the mitigation: Alice's attempt to call clawback would revert because entries.length is 2 (greater than 0), preventing her from reclaiming the reward.
pwning_dev
Medium
Reward Depletion in clawback (RAFFLE strategy)
Summary
The clawback function in ERC20Incentive.sol allows the contract owner to reclaim a portion or all of the reward tokens. While this might seem reasonable for other incentive strategies, it becomes problematic when the strategy is set to RAFFLE.
Vulnerability Detail
The issue is that the condition claims > 0 only checks if there have been any claims, not specifically if there are active raffle entries. If someone has claimed a "ticket" for the raffle, claims will be greater than 0, even though the raffle hasn't been drawn yet. This allows the owner to claw back the entire reward even after users have entered the raffle.
Attack Scenario:
Deploy or Identify a Contract: The attacker either deploys their own ERC20Incentive contract with the RAFFLE strategy or identifies an existing one with a significant reward.
Promote the Raffle: The attacker might actively promote the raffle to attract participants and encourage them to make entries (claim their "tickets").
Clawback the Reward: Once a few users have entered the raffle (increasing the claims counter), the attacker (as the contract owner) calls the clawback function, setting the amount to the full reward value.
Reward Drained: The clawback function's condition (amount != reward || claims > 0) is met because claims is now greater than 0. The owner successfully reclaims the entire reward, leaving nothing for the raffle participants.
Raffle Becomes Pointless: When the drawRaffle function is eventually called, there's no reward to distribute, leaving the participants with nothing despite their entries.
Impact
Unfair Raffle: Participants could be misled into entering a raffle where the owner has already reclaimed the entire reward, making their participation pointless. This undermines the fairness and trust in the incentive mechanism.
Code Snippet
https://github.com/sherlock-audit/2024-06-boost-aa-wallet/blob/78930f2ed6570f30e356b5529bd4bcbe5194eb8b/boost-protocol/packages/evm/contracts/incentives/ERC20Incentive.sol#L97C5-L111C1
Tool used
Manual Review
Recommendation
By checking entries.length > 0, the clawback function will revert if there are any participants in the raffle, ensuring that the reward cannot be reclaimed after users have entered. Let's say Alice deploys an ERC20Incentive contract with a 1000 token reward and the RAFFLE strategy. Bob and Carol both call the claim function to enter the raffle. Now, claims is 2, and entries contains both Bob and Carol's addresses.