Malicious user can split the vote in QVBaseStrategy to get more votes.
Incorrect calculation of voiceCreditsCastToRecipient in _qv_allocate of QVBaseStrategy, resulting in more votes than intended.
Vulnerability Detail
The _qv_allocate is performed as follows.
Gets the current credit spent by the sender on _recipientId and the current vote count for _recipientId.
// get the previous values
uint256 creditsCastToRecipient = _allocator.voiceCreditsCastToRecipient[_recipientId];
uint256 votesCastToRecipient = _allocator.votesCastToRecipient[_recipientId];
Add the credit already used for _recipientId and the credit to be used this time and store it in totalCredits, and sqrt the result in voteResult.
// get the total credits and calculate the vote result
uint256 totalCredits = _voiceCreditsToAllocate + creditsCastToRecipient;
uint256 voteResult = _sqrt(totalCredits * 1e18);
Subtract the amount of votes already cast by the sender from voteResult to get the votes for this credit. Add this to totalRecipientVotes, _recipient.totalVotesReceived
The vulnerability exists in #4, where totalCredits is the sum of the previously used credit and the credit to be used, as seen in #2. Since _allocator.voiceCreditsCastToRecipient already stores the value of the previously used credit, the result is that the previously used credit is added twice.
pengun
high
Malicious user can split the vote in QVBaseStrategy to get more votes.
Incorrect calculation of
voiceCreditsCastToRecipient
in_qv_allocate
ofQVBaseStrategy
, resulting in more votes than intended.Vulnerability Detail
The
_qv_allocate
is performed as follows.sender
on_recipientId
and the current vote count for_recipientId
._recipientId
and the credit to be used this time and store it intotalCredits
, and sqrt the result invoteResult
.voteResult
to get the votes for this credit. Add this tototalRecipientVotes
,_recipient.totalVotesReceived
totalCredits
to_allocator.voiceCreditsCastToRecipient
andvoteResult
to_allocator.votesCastToRecipient
.The vulnerability exists in #4, where
totalCredits
is the sum of the previously used credit and the credit to be used, as seen in #2. Since_allocator.voiceCreditsCastToRecipient
already stores the value of the previously used credit, the result is that the previously used credit is added twice.POC:
Normal case:
If user allocated 100 at once
Test code:
Result:
Impact
This can be exploited to manipulate voting by allowing much more votes to be cast for the same amount of credits.
Code Snippet
https://github.com/sherlock-audit/2023-09-Gitcoin/blob/6430c8004017e96ae2f5aac365bdefd0b6eeea72/allo-v2/contracts/strategies/qv-base/QVBaseStrategy.sol#L529
Tool used
Manual Review
Recommendation
Change like below
Duplicate of #48