RSR holders could get less staked stRSR than expected #186
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
edited-by-warden
🤖_15_group
AI based duplicate group recommendation
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L502
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L621
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L230
Vulnerability details
Impact
The
stake()
function allowsRSR
holders to stake theirRSR
token forstRSR
token at an exchange rate of that current time. However, the lack of slippage protection can result in users receiving less than expected when stakingRSR
tokens. This occurs because thestakeRate
(i.e.exchangeRate
) is updated within thestake
functions by the_payoutRewards
function. However, users typically check theexchangeRate
using theexchangeRate()
function before staking to understand the expected amount they will receive. Since theexchangeRate()
function does not trigger_payoutRewards
, it returns a value that may change if a newstakeRate
is claculated (based on new added rewards), which leads to changes in the exchange rate when the actual staking occurs. This lack of a slippage protection mechanism can result in users receiving fewerstRSR
tokens than anticipated.Proof of Concept
stakeRSR
) and updates thestakeRate
.https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L593-L627
exchangeRate()
function to calculate the expectedstRSR
:https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L502
However, the
exchangeRate
function does not call the_payoutRewards
function, which updates thestakeRate
to a new value (in case of new addedRSR
rewards).RSR
tokens, thestake()
function calls_payoutRewards
before minting newstRSR
tokens:https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L227
This can change the
stakeRate
after the user has checked theexchangeRate
, leading to them receiving fewerstRSR
tokens than expected.stakeRate
is set asFIX_ONE
(i.e.1e18 - 1:1
),totalStakes
= 500 andstakeRSR
= 500RSR
, callsexchangeRate()
function to get the exchange rate betweenRSR
andStRSR
(note:exchangeRate()
returnsFIX_ONE
i.e.1e18
therefore, 50RSR
= 50StRSR
).stake()
function. Assume there are new reward to distribute in the contract (200RSR
), the_payoutRewards()
function re-calculates a newstakeRate
. newstakeRate
=(totalStakes(500) * FIX_ONE_256(1e18) + (stakeRSR(700) - 1)) / stakeRSR(700)
=7.14285714285714E+17
(note: now less than initialstakeRate
ofFIX_ONE
(1e18
))stakeRate
, Alice now getsStRSR
amount of =stakeRate(7.14285714285714E+17) * stakeAmount(50) = ~ 35 StRSR
(i.e. 15StRSR
less than expected)Tools Used
Manual, Foundry
Recommended Mitigation Steps
Either implement a slippage protection mechanism in the
stake
function or update theexchangeRate
function to call_payoutRewards
Reference
code-423n4/2023-12-revolutionprotocol-findings#397 (comment)
Assessed type
Other
The text was updated successfully, but these errors were encountered: