The Stability Pool's calculateRaacRewards()
function is vulnerable to a vampire attack, where a whale can front-run reward distribution by executing an atomic deposit and withdrawal to drain the available raacToken
rewards. Since the function distributes rewards proportionally based on deposit size at the time of calculation, a large temporary deposit can capture an unfair share of the rewards without maintaining long-term participation.
The function currently calculates RAAC rewards as follows:
This logic allows for an exploitable scenario:
Step 1. Monitor RAAC reward deposits: An attacker tracks the Stability Pool's balance for newly added rewards, totalRewards = raacToken.balanceOf(address(this))
.
Step 2. Front-run deposit: Upon detecting a sizable reward, the attacker deposits a massive amount of rToken
, temporarily becoming the dominant depositor, as reflected by userDeposits
.
Step 3. Claim rewards: The attacker claims a disproportionate share of raacToken
rewards based on their large deposit.
Step 4. Withdraw instantly: The attacker exits the pool right after claiming rewards, leaving long-term depositors with little to no rewards.
Since the function does not account for deposit duration or time-weighted staking, this exploit allows RAAC rewards to be drained unfairly, incentivizing short-term participation instead of long-term stability.
Example Attack Scenario
The Stability Pool holds 100,000 RAAC
tokens in rewards.
A long-term user has 50,000 rToken
deposited, expecting 100% of the rewards (assuming this user is the only depositor where totalDeposits == userDeposit
for simplicity).
An attacker deposits 500,000 rToken
right before claiming rewards, increasing total deposits to 550,000 rToken
.
The attacker's proportional share increases to 90.9%, allowing them to claim 90,900 RAAC
tokens.
The attacker immediately withdraws the deposit, leaving the original user with only 9,100 RAAC
tokens, instead of the expected 100,000.
Unfair reward distribution: Long-term depositors lose a significant share of RAAC rewards.
Discourages stable participation: Encourages speculative deposit behavior rather than sustainable staking.
Potential RAAC depletion: Attackers can repeatedly drain RAAC reserves via rapid deposits and withdrawals.
Possible reputational damage: The protocol may be perceived as exploitable or unfairly structured.
Manual
To mitigate this vulnerability, the following solutions should be considered to refactor calculateRaacRewards()
:
Require Minimum Deposit Duration
Implement a minimum staking period before rewards can be claimed.
Users withdrawing before the required duration forfeit rewards.
Time-Weighted Reward Scaling
Scale rewards based on how long a user has been staked.
New deposits receive gradually increasing eligibility for rewards over time.
Epoch-Based Reward Distribution
Implement an epoch-based system, where rewards are distributed at fixed intervals.
Prevents users from claiming rewards in the same block they deposit.
Penalty on Instant Withdrawals
Introduce a withdrawal fee for users who exit the pool immediately after depositing.
Fees can be redistributed to long-term stakers.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.