Open hats-bug-reporter[bot] opened 5 months ago
The 500 tokens you deem "stuck" are not stuck, they are tokens that have been distributed to stakers.
The issue is that those 500 tokens are stuck if nobody stakes for that period, which is a dupe of #66.
@0xmahdirostami
I respectfully disagree with the assertion that Issue #123 is a duplicate of Issue #66. While both issues pertain to the setRewards()
function, they address fundamentally different aspects:
setRewards()
during zero total supply lead to rewards being locked and not distributed, highlighting a precise condition (zero total supply) and its specific impact on reward distribution.
The unique focus and the specific conditions highlighted in Issue#123 are not covered in Issue#66, making them distinct issues. Therefore, As I demonstrated in the Proof of Concept, which is available for anyone to test, Issue#123 should be considered independently to address its unique implications on the protocol.Yes @MatinR1 I agree that this is a different usecase, but this still is based on the assumption that the reward should be fully available in the next reward period. If we assume that the distribution of funds in the first half is done (even if 50% of the funds didnt reach anyone) then your claim doesnt hold up anymore
Github username: @MatinR1 Twitter username: MatinRezaii1 Submission hash (on-chain): 0x397e9f1417ce4ae30974d1f722a3b3e4e9dd1f65ec8e5dc30262e578b963d6a0 Severity: high
Description: Description\
The rewards cannot be fully distributed and are ultimately locked in the contract.
The function
setRewards()
calls_setRewards()
:This means that for the cases where the
block.timestamp < rewardsEnd
or in other words, the rewardsEnd is not reached, the remainings reward is calculated, and the result is added to therewardRate
. There is a vulnerability in the_setRewards()
function, to be specific inside the_calculateRewardValue()
function, when the total supply is zero. The mentioned function first checks for a zero total supply and then updates the reward rate:This tells us that if the
totalSupply()
is zero, then the reward value does not change and it returns the previous reward value. This itself is not an issue, however, if considered thereaminingRewards
calculations ofsetRewards()
, it becomes an issue. Consider this situation:totalSupply = 0, rewardsEnd = 0, duration = 100
setRewards(1000, 100)
at time 0:rewardPerToken = 0, rewardRate = 1000 / 100 = 10, rewardsEnd = 0 + 100 = 100
setRewards(1000, 100)
at time 50:rewardPerToken = 0, leftover = (100 - 50) * 10 = 500, reward = 1000 + 500 = 1500, rewardRate = 1500 / 100 = 15
_calculateRewardValue()
. TherewardRate
should have been2000 / duration = 2000 / 100 = 20
instead of the current15
.Attack Scenario\ POC is provided for this type of vulnerability.
Attachments
Make
_calculateRewardValue()
functionpublic
and add this test toLM_PC_Staking_v1Test
:Output:
The last call to
rewardRate()
must be20
instead of15
. This test shows the significant reward loss when the total supply is zero.In
_setRewards()
, if_calculateRewardValue()
returns 0, consider all previously accumulated tokens inside theremainingRewards
.