Stakers who stake RSR can have their tokens seized by the protocol. To prevent RSR stakers from bypassing slashing, users must wait until the withdrawal delay period is over before they can withdraw their staked RSR. When users unstake their RSR, it is moved to rsrdraft. The problem arises when there is an ongoing slashing: RSR in staked.rsr is seized first. A user who is aware of the ongoing slashing and has their RSR in rsrdraft can potentially bypass the slashing.
Lines of code
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L424
Vulnerability details
Stakers who stake RSR can have their tokens seized by the protocol. To prevent RSR stakers from bypassing slashing, users must wait until the withdrawal delay period is over before they can withdraw their staked RSR. When users unstake their RSR, it is moved to
rsrdraft
. The problem arises when there is an ongoing slashing: RSR instaked.rsr
is seized first. A user who is aware of the ongoing slashing and has their RSR inrsrdraft
can potentially bypass the slashing.proof of concept
a staker who already called the unstake sees stakers who are in stakedrsr being slashed https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L259
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L441
when the contract is done seizing stakedrsr, the staker calls the cancel unstake function to move his rsr from draftrsr back to staked rsr
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L346
protocol seizes the rsr in the draftsrsr and the user avoids getting slashed succesfully if the stake rsr rate is still safe
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L446
impact rsr stakers who were meant to be slashed can bypass slashing
mitigation
seize the total rsr amount at once totalRSR = stakeRSR + draftRSR + rsrWithdrawal;
Assessed type
Context