calcaultion of scaledRewardRate
will make the rewards stuck in the contract when totalStaked = 0
#134
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
duplicate-369
edited-by-warden
🤖_14_group
AI based duplicate group recommendation
unsatisfactory
does not satisfy C4 submission criteria; not eligible for awards
Lines of code
https://github.com/code-423n4/2024-02-uniswap-foundation/blob/5a2761c8277541a24bc551fbd624413b384bea94/src/UniStaker.sol#L577-L582
Vulnerability details
Impact
scaledRewardRate
is only calculated innotifyRewardAmount
without considering iftotalStaked
is 0 or not. AndscaledRewardRate
is not updated anywhere else. So iftotalStaked
= 0, this will cause the waste of reward tokens, as these tokens are considered to be already distributed during the period but they are actually not. This leads to the waste and lock of funds.Proof of Concept
scaledRewardRate
is used to represent theglobal rate at which rewards are currently being distributed to stakers
. It is updated every time there is a new reward coming in and notifying via notifyRewardAmount.The problem is that, if
totalStaked
= 0, rewardshave
been distributed according to the calculation_remainingReward = scaledRewardRate * (rewardEndTime - block.timestamp)
but they arenot rewarded
since no one is staking yet. The root cause is that rewards are still distributed even though no one is staking.Since
scaledRewardRate
can not be updated elsewhere, these reward tokens are certainlywasted
as they won't be counted in the next reward period. This leads to the waste and lock of funds.Note: Several cases will all cause
totalStaked=0
, like no one has staked before, or the onlystaker
decides to withdraw all shares.The PoC is shown below (in
UniStaker.t.sol::NotifyRewardAmount
):The log is shown below, even though there is no staker, half of the
_amount
(15 days / 30 days) is still considered to be consumed:Tools Used
Foundry
Recommended Mitigation Steps
I would suggest the following:
totalStaked
is 0, the rewarding process should not be open, and the fund could be recorded in a variablenextRoundRewards
for the next reward process.staker
quits, the rewarding process should also stop, and the remaining fund should also be recorded innextRoundRewards
.Assessed type
Math
The text was updated successfully, but these errors were encountered: