30860 - [SC - Critical] Wrong timestamp for totalVoting

Submitted on May 7th 2024 at 04:17:29 UTC by @cryptoticky for Boost | Alchemix

Report ID: #30860

Report type: Smart Contract

Report severity: Critical

Target: https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/Bribe.sol

Impacts:

  • Theft of unclaimed yield

  • Manipulation of governance voting result deviating from voted outcome and resulting in a direct change from intended effect of original results

Description

Brief/Intro

The attacker can change totalVoting at the first second of a new epoch and steal all reward for an epoch.

Vulnerability Details

    /// @inheritdoc IBribe
    function earned(address token, uint256 tokenId) public view returns (uint256) {
        ...
        Checkpoint memory cp = checkpoints[tokenId][_endIndex];
        uint256 _lastEpochStart = _bribeStart(cp.timestamp);
        uint256 _lastEpochEnd = _lastEpochStart + DURATION;
        uint256 _priorSupply = votingCheckpoints[getPriorVotingIndex(_lastEpochEnd)].votes;

        // Prevent divide by zero
        if (_priorSupply == 0) {
            _priorSupply = 1;
        }

        if (block.timestamp > _lastEpochEnd) {
            reward += (cp.balanceOf * tokenRewardsPerEpoch[token][_lastEpochStart]) / _priorSupply;
        }

        return reward;
    }

If an attacker call Voter.distribute at _lastEpochStart + DURATION, then Bribe.resetVoting function is triggered and totalVoting is updated to 0. And then if the attacker call Voter.vote function the same params (or tokenId with less votingPower), then Bribe._writeVotingCheckpoint is triggered and votingCheckpoints[getPriorVotingIndex(_lastEpochEnd)].votes is updated with the new votes. And the attacker claim the reward at the next block before other users claim. The smaller the new vote amount, the more rewards the attacker can steal.

Impact Details

The attacker can steal reward and other users can't claim the reward.

Recommandation

Bribe.sol: 268 line

to

Proof of Concept

Last updated

Was this helpful?