StakingRewards
reward rate can be dragged out and diluted
#183
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
sponsor disputed
Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue
Lines of code
https://github.com/code-423n4/2022-02-concur/blob/72b5216bfeaa7c52983060ebfc56e72e0aa8e3b0/contracts/StakingRewards.sol#L161
Vulnerability details
Impact
The
StakingRewards.notifyRewardAmount
function receives areward
amount and extends the current reward end time tonow + rewardsDuration
.It rebases the currently remaining rewards + the new rewards (
reward + leftover
) over this newrewardsDuration
period.This can lead to a dilution of the reward rate and rewards being dragged out forever by malicious new reward deposits.
POC
Imagine the current rewardRate is
1000 rewards / rewardsDuration
.20% of the
rewardsDuration
passed, i.e.,now = lastUpdateTime + 20% * rewardsDuration
.A malicious actor notifies the contract with a reward of
0
:notifyRewardAmount(0)
.Then the new
rewardRate = (reward + leftover) / rewardsDuration = (0 + 800) / rewardsDuration = 800 / rewardsDuration
.The
rewardRate
just dropped by 20%.This can be repeated infinitely.
After another 20% of reward time passed, they trigger
notifyRewardAmount(0)
to reduce it by another 20% again:rewardRate = (0 + 640) / rewardsDuration = 640 / rewardsDuration
.Recommended Mitigation Steps
Imo, the
rewardRate
should never decrease by anotifyRewardAmount
call.Consider not extending the reward payouts by
rewardsDuration
on every call.periodFinish
probably shouldn't change at all, therewardRate
should just increase byrewardRate += reward / (periodFinish - block.timestamp)
.Alternatively, consider keeping the
rewardRate
constant but extendperiodFinish
time by+= reward / rewardRate
.The text was updated successfully, but these errors were encountered: