sherlock-audit / 2024-06-magicsea-judging

8 stars 5 forks source link

zarkk01 - ```BribeRewarder``` contract funtionality is broken with low-decimals tokens. #678

Closed sherlock-admin2 closed 4 months ago

sherlock-admin2 commented 4 months ago

zarkk01

Medium

BribeRewarder contract funtionality is broken with low-decimals tokens.

Vulnerability Detail

The duration of a VotingPeriod is 14 days which is 1209600 in seconds. Also, a user can create a BribeRewarder which whatever token he likes and these kind of issues are in-scope according to the docs. In _calculateRewards of BribeRewarder, a division is executed and we can see it here :

    function _calculateRewards(uint256 periodId) internal view returns (uint256) {
        (uint256 startTime, uint256 endTime) = IVoter(_caller).getPeriodStartEndtime(periodId);

        if (endTime == 0 || startTime > block.timestamp) {
            return 0;
        }

        uint256 duration = endTime - startTime;
@>        uint256 emissionsPerSecond = _amountPerPeriod / duration;

        uint256 lastUpdateTimestamp = _lastUpdateTimestamp;
        uint256 timestamp = block.timestamp > endTime ? endTime : block.timestamp;
        return timestamp > lastUpdateTimestamp ? (timestamp - lastUpdateTimestamp) * emissionsPerSecond : 0;
    }

Given the VotingPeriod duration of 1,209,600 seconds, any _amountPerPeriod less than 1,209,600 will result in emissionsPerSecond being 0 due to Solidity's rounding down behavior. This is particularly problematic for tokens with low decimal places, such as GUSD (Gemini Dollar), which has 2 decimals. For instance, if the _amountPerPeriod is 10,000 GUSD, the emissionsPerSecond will always be 0, preventing voters from receiving any rewards.

Impact

This vulnerability prevents the distribution of rewards to voters when using tokens with low decimal places. Consequently, the reward distribution mechanism is rendered ineffective, and voters do not receive the rewards they are entitled to for their participation.

Code Snippet

https://github.com/sherlock-audit/2024-06-magicsea/blob/main/magicsea-staking/src/rewarders/BribeRewarder.sol#L300

Tool used

Manual Review

Recommendation

To address this issue, consider implementing a check to ensure that the _amountPerPeriod is sufficient to generate a non-zero emissionsPerSecond for the given VotingPeriod duration. Additionally, consider adjusting the calculation method to accommodate tokens with low decimal places, ensuring accurate reward distribution. One potential solution is to use a higher precision for internal calculations to avoid rounding down to zero.

Duplicate of #545