President Elector

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

Missing Vote Redistribution Logic After Candidate Elimination

Summary

In the _selectPresidentRecursive function, when a candidate is eliminated, their votes are not redistributed to the voters' next preferred candidates. This deviates from the standard Ranked Choice Voting algorithm and can result in incorrect election outcomes.

Vulnerability Details

  • Affected Function: _selectPresidentRecursive

  • Issue Explanation:

    • No Redistribution: After eliminating the candidate with the fewest votes, the function does not reallocate those votes to the next available choices on each affected ballot.

    • Algorithm Deviation: Proper Ranked Choice Voting requires that when a voter's top choice is eliminated, their vote transfers to their next preferred candidate who is still in the race.

    • Impact on Results: Without redistribution, the election may not accurately reflect voters' preferences, leading to potentially incorrect or unfair outcomes.

Impact

Severity: High

  • Incorrect Election Results: The winner may not be the candidate who would have won under proper Ranked Choice Voting.

  • Voter Disenfranchisement: Voters whose top choices are eliminated effectively lose their votes.

Tools Used

  • Manual Code Review: Identified missing logic for vote redistribution after candidate elimination.

  • Comparison with RCV Algorithm: Noted discrepancies between the implemented logic and standard RCV procedures.

Recommendations

  • Implement Vote Redistribution Logic:

    • After eliminating the candidate with the fewest votes, update the vote counts by transferring votes to the next preferred candidate on each affected ballot.

    • Example Implementation:

      function _redistributeVotes(
      address eliminatedCandidate,
      address[] memory remainingCandidates,
      uint256 roundNumber
      ) internal {
      // Reset vote counts for remaining candidates
      for (uint256 i = 0; i < remainingCandidates.length; i++) {
      s_candidateVotesByRound[remainingCandidates[i]][s_voteNumber][roundNumber] = 0;
      }
      // Re-tally votes
      for (uint256 i = 0; i < VOTERS.length; i++) {
      address[] memory rankings = s_rankings[VOTERS[i]][s_voteNumber];
      for (uint256 j = 0; j < rankings.length; j++) {
      address candidate = rankings[j];
      if (candidate == eliminatedCandidate) {
      continue; // Skip eliminated candidate
      }
      if (_isInArray(remainingCandidates, candidate)) {
      s_candidateVotesByRound[candidate][s_voteNumber][roundNumber] += 1;
      break;
      }
      }
      }
      }
      • Call _redistributeVotes after each elimination.

  • Test Thoroughly:

    • Ensure the updated function correctly follows the RCV algorithm by writing comprehensive unit tests.

  • Optimize for Gas Efficiency:

    • Since redistribution can be gas-intensive, consider optimizing data structures and loops.

Updates

Lead Judging Commences

inallhonesty Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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