The StabilityPool
contract's reward distribution mechanism is vulnerable to sandwich attacks, allowing attackers to steal RAAC rewards from legitimate users through deposit/withdrawal manipulation.
The vulnerability exists in the StabilityPool::calculateRaacRewards()
function where rewards are calculated based on the current snapshot of deposits rather than accumulated rewards over time:
The calculation only considers the current state of deposits and total rewards, ignoring the duration of user deposits. This allows an attacker to:
Monitor pending withdrawal transactions
Front-run with a large deposit
Capture a share of accumulated rewards
Back-run by withdrawing immediately
The vulnerability has severe economic impact:
Users lose rightfully earned RAAC rewards to attackers
Early depositors are disincentivized as their rewards can be stolen
Protocol's reward distribution becomes unfair and manipulatable
MEV bots can continuously exploit this for profit
For example, if User A deposits 100 tokens for 2 hours earning 200 RAAC, an attacker can front-run their withdrawal with a 100 token deposit and steal 100 RAAC (50% of rewards) despite having funds in the pool for mere seconds.
Manual review
Add the following test case to the test/e2e/protocols-tests.js
file:
Implement an accumulated rewards per share mechanism:
Track a global accumulator that increases as rewards are added
Store user's last-seen accumulator value when they deposit
Calculate rewards based on the difference in accumulator values
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.