31295 - [SC - High] Newly created gauge may missed out on its rewards

Submitted on May 16th 2024 at 17:25:04 UTC by @Lin511 for Boost | Alchemix

Report ID: #31295

Report type: Smart Contract

Report severity: High

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

Impacts:

  • Contract fails to deliver promised returns, but doesn't lose value

Description

Brief/Intro

Newly created gauge may missed out on its rewards when the first distribute took place, due to the incorrect use of memory variables.

Vulnerability Details

In Voter._distribute(), claimable[_gauge] is assigned to a memory variable _claimable, then claimable[_gauge] is reset to zero.

    function _distribute(address _gauge) internal {
        // Distribute once after epoch has ended
        require(
            block.timestamp >= IMinter(minter).activePeriod() + IMinter(minter).DURATION(),
            "can only distribute after period end"
        );

        uint256 _claimable = claimable[_gauge];

        // Reset claimable amount
        claimable[_gauge] = 0;

        _updateFor(_gauge);

        if (_claimable > 0) {
            IBaseGauge(_gauge).notifyRewardAmount(_claimable);
        }

        ...
    }

After that claimable[_gauge] is updated in _updateFor(_gauge).

At last, if _claimable is greater than zero, reward will be send to gauge. There is a problem with that _claimable is a memory variable, when claimable[_gauge] be updated, _claimable is not along with it, so there is a scenario that gauge won't receive it's reward on it's first distribute: 1, createGauge() called, gauge A created. 2, some one vote for it. 3, minter called notifyRewardAmount(). 4, some one call distribute(), it's the first distribute of gauge A, when contracts runs to distribute(guage A), claimable[_gauge] is greater than zero but _claimable is equal to zero, so gauge A missed out on it's reward this time.

Impact Details

Contracts may not work as intended, in the worst-case scenario, if the distribute() function is called only once, newly created guage could lose its rewards.

References

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/Voter.sol#L366-L375 https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/Voter.sol#L481

Proof of Concept

Last updated

Was this helpful?