MorpheusAI

MorpheusAI
Foundry
22,500 USDC
View results
Submission Details
Severity: medium
Invalid

For low values of initial rewards it can cause loss of rewards

Summary

if the value of initial rewards if low then it can cause loss of rewards for multiple rounds which can accumulate as a bigger rewards.

Vulnerability Details

Following is the function which calculates the rewards.

function getPeriodReward(
uint256 initialAmount_,
uint256 decreaseAmount_,
uint128 payoutStart_,
uint128 interval_,
uint128 startTime_,
uint128 endTime_
) external pure returns (uint256) {
if (interval_ == 0) {
return 0;
}
// 'startTime_' can't be less than 'payoutStart_'
if (startTime_ < payoutStart_) {
startTime_ = payoutStart_;
}
uint128 maxEndTime_ = _calculateMaxEndTime(payoutStart_, interval_, initialAmount_, decreaseAmount_);
if (endTime_ > maxEndTime_) {
endTime_ = maxEndTime_;
}
// Return 0 when calculation 'startTime_' is bigger then 'endTime_'...
if (startTime_ >= endTime_) {
return 0;
}
// Calculate interval that less then 'interval_' range
uint256 timePassedBefore_ = startTime_ - payoutStart_;
if ((timePassedBefore_ / interval_) == ((endTime_ - payoutStart_) / interval_)) {
uint256 intervalsPassed_ = timePassedBefore_ / interval_;
uint256 intervalFullReward_ = initialAmount_ - intervalsPassed_ * decreaseAmount_;
return (intervalFullReward_ * (endTime_ - startTime_)) / interval_;
}
// Calculate interval that more then 'interval_' range
uint256 firstPeriodReward_ = _calculatePartPeriodReward(
payoutStart_,
startTime_,
interval_,
initialAmount_,
decreaseAmount_,
true
);
uint256 secondPeriodReward_ = _calculateFullPeriodReward(
payoutStart_,
startTime_,
endTime_,
interval_,
initialAmount_,
decreaseAmount_
);
uint256 thirdPeriodReward_ = _calculatePartPeriodReward(
payoutStart_,
endTime_,
interval_,
initialAmount_,
decreaseAmount_,
false
);
return firstPeriodReward_ + secondPeriodReward_ + thirdPeriodReward_;
}

Now lets assume payout start = 0(just for simplification )
decrease interval = 5 sec
rewards decrease = 3
initial Amount = 10
then if this function is called at 4sec i.e end time = 4sec and someone had already deposited before payout start then following will be the inputs getPeriodReward(
10, 3, 0, 5, 0,4)
now this would return 8 so 2 tokens are left as rewards for this interval
So if again the above function is called with the following inputs
getPeriodReward(
10, 3, 0, 5, 4,5) this will return 2
So 8+2 total 10 tokens have been rewarded which is the correct amount for this interval
Now if getPeriodReward(
10, 3, 0, 5, 5,9) then it will return 5 tokens so the tokens left for this interval = 2 because for the 2nd interval there is decrease of rewards by the decrease reward which is equal to 3.
now if getPeriodReward(
10, 3, 0, 5, 9,10) then it will return 1 token and the interval ends so total rewards distributed = 5 +1 = 6 which means 1 token remains undistributed.
This can happen in mutliple rounds which can cause less rewards token being transferred to the users.
Key to note is that this happens when the value of rewards to be distributed are low so this issue can be medium/low issue but certainly it is a valid issue.

Impact

Causes some rewards token to remain undistributed thus causing loss to the users.

Tools Used

Manual review

Recommendations

It is difficult to come up with a mitigation for this issue as it can cause the whole function to change.

Updates

Lead Judging Commences

inallhonesty Lead Judge
over 1 year ago
inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.