Description:Description\
The total accumulated reward since the last claim is calculated based on the rewardsPerEpoch variable at the end of each epoch. However, due to a math-related timing issue, the rewards per epoch used for calculating rewards is based on the first second of the next epoch instead of the end of the current epoch. This causes several problems such as incorrect reward allocation which is described bellow:
When the strategy deposits at the boundary of epochs, its deposit is counted in the current epoch's rewardsPerEpoch via notifyRewardAmount().
When calculating the reward, however, the next epoch's start is considered.
This means users who deposit at the start of a new epoch dilute the reward rate for the previous epoch but do not receive rewards for that epoch.
As a result, some rewards remain unclaimed and locked within the contract because they do not roll over to future epochs.
The math below shows that epoch_ + _WEEK is indeed the first second of the next epoch and not the last of the prior epoch:
function epochStart(uint256 timestamp) internal pure returns (uint256) {
return timestamp - (timestamp % _WEEK);
}
Outputs:
Expression
Type
Hex
Decimal
epochStart(123)
uint
0x0
0
epochStart(100000000)
uint
0x5f2b480
99792000
WEEK
uint
0x93a80
604800
epochStart(WEEK)
uint
0x93a80
604800
epochStart(1 + WEEK)
uint
0x93a80
604800
epochStart(0 + WEEK)
uint
0x93a80
604800
epochStart(WEEK - 1)
uint
0x0
0
As it is clear from the abovementioned table, the epoch_ + _WEEK shows the start of the next epoch.
Github username: @MatinR1 Twitter username: MatinRezaii1 Submission hash (on-chain): 0x251a5fcf58d7d621b1837aa5b5e9f163253e9b180d969bc516b712d0db9da98a Severity: high
Description: Description\ The total accumulated reward since the last claim is calculated based on the
rewardsPerEpoch
variable at the end of each epoch. However, due to a math-related timing issue, the rewards per epoch used for calculating rewards is based on the first second of the next epoch instead of the end of the current epoch. This causes several problems such as incorrect reward allocation which is described bellow:rewardsPerEpoch
vianotifyRewardAmount()
.The math below shows that
epoch_ + _WEEK
is indeed the first second of the next epoch and not the last of the prior epoch:Outputs:
epochStart(123)
epochStart(100000000)
WEEK
epochStart(WEEK)
epochStart(1 + WEEK)
epochStart(0 + WEEK)
epochStart(WEEK - 1)
As it is clear from the abovementioned table, the
epoch_ + _WEEK
shows the start of the next epoch.Attachments
rewardsPerEpoch
boundaries inside the_calculateRewardPerEpoch()
function: