sherlock-audit / 2024-06-velocimeter-judging

11 stars 7 forks source link

bin2chen - poke() be killed gauge still has the some percentage #566

Closed sherlock-admin3 closed 3 months ago

sherlock-admin3 commented 3 months ago

bin2chen

Medium

poke() be killed gauge still has the some percentage

Summary

The poke() does not filter out the killed gauge. It still takes up a certain percentage of the votes, resulting in fewer votes and fewer rewards.

Vulnerability Detail

We can try poke() for a quick way to remember the percentage of votes.

    function poke(uint _tokenId) external onlyNewEpoch(_tokenId) {
        require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId) || msg.sender == governor);
        lastVoted[_tokenId] = block.timestamp;

        address[] memory _poolVote = poolVote[_tokenId];
        uint _poolCnt = _poolVote.length;
        uint256[] memory _weights = new uint256[](_poolCnt);

        for (uint i = 0; i < _poolCnt; i ++) {
@>          _weights[i] = votes[_tokenId][_poolVote[i]];
        }

        _vote(_tokenId, _poolVote, _weights);
    }

    function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {
        _reset(_tokenId);
        uint _poolCnt = _poolVote.length;
        uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);
        uint256 _totalVoteWeight = 0;
        uint256 _totalWeight = 0;
        uint256 _usedWeight = 0;

        for (uint i = 0; i < _poolCnt; i++) {
@>          _totalVoteWeight += _weights[i];
        }

But poke() doesn't determine if the pool is still valid, and it still has the appropriate percentage. But an invalid gauge can't get a reward.

Impact

If poke() contains a gauge that has already been killed, a portion of the reward will always be lost.

Code Snippet

https://github.com/sherlock-audit/2024-06-velocimeter/blob/main/v4-contracts/contracts/Voter.sol#L234

Tool used

Manual Review

Recommendation

    function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {
        _reset(_tokenId);
        uint _poolCnt = _poolVote.length;
        uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);
        uint256 _totalVoteWeight = 0;
        uint256 _totalWeight = 0;
        uint256 _usedWeight = 0;

        for (uint i = 0; i < _poolCnt; i++) {
+            if (isGauge[gauges[_poolVote[i]]) {
                 _totalVoteWeight += _weights[i];
+            }
        }

Duplicate of #477