Submitted by Soosh, also found by __141345__
It is possible for a user to steal the yield from other stakers by staking when the system is paused or frozen.
This is because staking is allowed while paused/frozen, but _payoutRewards() is not called during so. Staking rewards are not paid out to current stakers when a new staker stakes, so the new staker immediately gets a portion of the rewards, without having to wait for a reward period.
A test case can be included in ZZStRSR.test.ts under Add RSR / Rewards:
Note that await advanceTime(Number(config.rewardPeriod) * 5) can be before or after the pause, same result will occur.
Run with:
yarn test:p1 --grep "Audit"
Output:
The PoC demonstrates that the staker2 stole half of the rewards from staker1. staker1 staked for 5 rewardPeriod, staker2 did not have to wait at all, but still received half of the reward share.
This should fall into Theft of unclaimed yield, suggesting High risk. But the amount of RSR that can be stolen depends on the liveliness of the staking pool (how often _payoutRewards() is called). If the time window between the last stake(...)/unstake(...)/payoutRewards(...) and pause()/freezeUntil(...) is small, then no/less RSR yield can be stolen.
system-design.md rewardPeriod:
For RTokens which choose a smaller value for rewardPeriod, the risk is higher. If rewardPeriod = 86400 like recommended, then for this attack to occur, no one must have called stake(...)/unstake(...)/payoutRewards(...) for 1 day before the pause/freeze occured.
Likelihood is Low for a reasonably set rewardPeriod and lively project. Therefore submitting as Medium risk.
Im unsure of why staking is allowed when paused/frozen and the reason for the line:
The team should consider the reason for the above logic.
If the above logic is required, then I would suggest that poke() in Main.sol be called inside of pause() and freezeUntil(...) to update the state before pausing/freezing. Since distribute(...) has modifier notPausedOrFrozen, I would assume in pause/frozen state, no RSR is sent to stRSR contract (i.e. no rewards when paused/frozen) so this recommendation should be sufficient in preventing the issue.
pmckelvy1 (Reserve) confirmed
tbrent (Reserve) mitigated:
Status: Mitigation confirmed. Full details in reports from HollaDieWaldfee, 0xA5DF, and AkshaySrivastav.
