Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
_bribes and _tokens length are not checked to be equal in Voter.sol::claimBribes which can lead to problems as discussed below
Vulnerability Details
In Voter.sol::claimBribes, _bribes and _tokens length are not checked to be equal.
// @audit No check for _bribes.length == _tokens.length/// @inheritdoc IVoterfunctionclaimBribes(address[] memory_bribes,address[][] memory_tokens,uint256_tokenId) external {require(IVotingEscrow(veALCX).isApprovedOrOwner(msg.sender, _tokenId));for (uint256 i =0; i < _bribes.length; i++) {IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]); } }
Similar length equal checks are there in all other parts of the protocol but is absent in this function.
// Similar checks are there in other functionsfunctionvote(uint256_tokenId,address[] calldata_poolVote,uint256[] calldata_weights,uint256_boost ) externalonlyNewEpoch(_tokenId) {require(IVotingEscrow(veALCX).isApprovedOrOwner(msg.sender, _tokenId),"not approved or owner");@>require(_poolVote.length == _weights.length,"pool vote and weights mismatch");require(_poolVote.length >0,"no pools voted for");@>require(_poolVote.length <= pools.length,"invalid pools");require(IVotingEscrow(veALCX).claimableFlux(_tokenId) +IFluxToken(FLUX).getUnclaimedFlux(_tokenId) >= _boost,"insufficient FLUX to boost" );require( (IVotingEscrow(veALCX).balanceOfToken(_tokenId) + _boost) <=maxVotingPower(_tokenId),"cannot exceed max boost" );require(block.timestamp <IVotingEscrow(veALCX).lockEnd(_tokenId),"cannot vote with expired token");_vote(_tokenId, _poolVote, _weights, _boost); }
This can create problem in a scenerio where _bribes length is less than _tokens length as the user will lose on the funds on the bribe which is not set in the array. Such checks are essential in order to validate that valid transactions are going through and there is no discrepancy between bribes and tokens.
Note - Although the contract should check for these things in order to not procure any loss to users but it is also the responsibility of the user hence this is a low issue and not any medium or higher severity issue
Impact Details
Lack of this validation can result in user putting wrong lengths of bribes and tokens. This can create problem in a scenerio where _bribes length is less than _tokens length as the user will lose on the funds on the bribe which is not set in the array.
Suggestion/ Recommendation
Modify the function as follows
function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint256 _tokenId) external { + require(_bribes.length == _tokens.length, "token and bribes are not the same length"); require(IVotingEscrow(veALCX).isApprovedOrOwner(msg.sender, _tokenId)); for (uint256 i = 0; i < _bribes.length; i++) { IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]); } }
In the following POC we have given vote through 2 bribe Address but at the time of claimBribe only one bribe address is (unintentionally) given and 2 token arrays are given but the transaction still goes through resulting in user losing out on bribe from the second bribe address. Paste the following code in Voting.t.sol and run with the following command