31527 - [SC - Critical] No accounting for totalVoting in Bribesolwithdr...

Submitted on May 21st 2024 at 02:17:27 UTC by @gladiator111 for Boost | Alchemix

Report ID: #31527

Report type: Smart Contract

Report severity: Critical

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

Impacts:

  • Permanent freezing of unclaimed yield

Description

Brief/Intro

Bribe.sol::withdraw doesn't decrease totalVoting which can be exploited by a malicious user to permanently decrease yield.

Vulnerability Details

In the function, Bribe.sol::withdraw,totalVoting is not decreased and checkpointed as expected. The Withdraw function is called when a user withdraws their vote. It should decrease totalVoting but it is not.

    //Doesn't decrease TotalVoting
    function withdraw(uint256 amount, uint256 tokenId) external {
        require(msg.sender == voter);

        totalSupply -= amount;
        balanceOf[tokenId] -= amount;

        _writeCheckpoint(tokenId, balanceOf[tokenId]);
        _writeSupplyCheckpoint();

        emit Withdraw(msg.sender, tokenId, amount);
    }

This can be exploited by malicious user, as the user can call poke repeatedly (as it doesn't have same Epoch constraints) to indefinitely increase totalSupply. When totalVoting is increased the earned yield will also decrease as follows

Users will earn far less yield. The more times the poke function is called, the less the yield will become. Note - It doesn't even need a malicious user as some users will call poke after voting which will decrease yield

Impact Details

The Yield will be permanently frozen/lost.

Suggestions/ Recommendations

modify the function as follows

References

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/Bribe.sol#L319-329

Proof of Concept

Paste the following in Voting.t.sol and run using

Last updated

Was this helpful?