President Elector

First Flight #24
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Invalid

Voters can vote for same address multiple times in `RankedChoice::rankCandidates`

Description

As rankCandidates does not check if the orderedCandidates array contains duplicate addresses, this allows for voters to vote for the same candidate up to 10 times.

Impact

It is possible that this is acceptable to the protocol, as a voter may only have 1 candidate that they would like to vote for as president, so they put in this address for each of their available ranked votes.

Proof of Concept

function testCanVoteForAddressMultipleTimes() public {
orderedCandidates = [candidates[0], candidates[1], candidates[0]];
vm.prank(voters[0]);
rankedChoice.rankCandidates(orderedCandidates);
assertEq(rankedChoice.getUserCurrentVote(voters[0]), orderedCandidates);
}
Output: [427488] MyTest::testCanVoteForAddressMultipleTimes() ├─ [0] VM::prank(0x0000000000000000000000000000000000000064) │ └─ ← [Return] ├─ [312448] RankedChoice::rankCandidates([0x00000000000000000000000000000000000000C8, 0x00000000000000000000000000000000000000C9, 0x00000000000000000000000000000000000000C8]) │ └─ ← [Stop] ├─ [1918] RankedChoice::getUserCurrentVote(0x0000000000000000000000000000000000000064) [staticcall] │ └─ ← [Return] [0x00000000000000000000000000000000000000C8, 0x00000000000000000000000000000000000000C9, 0x00000000000000000000000000000000000000C8] ├─ [0] VM::assertEq([0x00000000000000000000000000000000000000C8, 0x00000000000000000000000000000000000000C9, 0x00000000000000000000000000000000000000C8], [0x00000000000000000000000000000000000000C8, 0x00000000000000000000000000000000000000C9, 0x00000000000000000000000000000000000000C8]) [staticcall] │ └─ ← [Return] └─ ← [Stop]

Recommendations

Update documentation/known issues if this is acceptable behavior within the protocol, else you can add a check for duplicate addresses within the orderedCandidates array passed to _rankCandidates; also you will need to create a new error like RankedChoice__DuplicateCandidate:

+ error RankedChoice__DuplicateCandidate();
// in `_rankCandidates`
if (orderedCandidates.length > MAX_CANDIDATES) {
revert RankedChoice__InvalidInput();
}
if (!_isInArray(VOTERS, voter)) {
revert RankedChoice__InvalidVoter();
}
// Check for duplicates
+ for (uint256 i = 0; i < orderedCandidates.length; i++) {
+ for (uint256 j = i + 1; j < orderedCandidates.length; j++) {
+ if (orderedCandidates[i] == orderedCandidates[j]) {
+ revert RankedChoice__DuplicateCandidate();
+ }
+ }
+ }
// Internal Effects
s_rankings[voter][s_voteNumber] = orderedCandidates;
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

rankCandidates() allows duplicate votes inside the `orderedCandidates` array

Appeal created

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

rankCandidates() allows duplicate votes inside the `orderedCandidates` array

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.