President Elector

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

Lack of Access Control in `RankedChoice::rankCandidates` Function Allows Unauthorized Voting

Summary

The `RankedChoice::rankCandidates` function does not have any access control mechanisms, allowing any user to participate in the election and rank candidates. This is a significant oversight because it undermines the integrity of the election by allowing non-voters to influence the results. Access control is essential to restrict voting to approved participants.

Vulnerability Details

The RankedChoice::rankCandidates function does not restrict who can call it, meaning anyone can rank candidates, regardless of whether they are an authorized voter. The function is missing a check to ensure that only the addresses included in the RankedChoice::VOTERS array can participate in the election. This opens the contract to potential abuse where unauthorized parties can manipulate the election by submitting rankings.

Affected Code:

function rankCandidates(address[] memory orderedCandidates) external {
_rankCandidates(orderedCandidates, msg.sender);
}

Impact

Consequences:

  • Election Manipulation: Unauthorized users can influence the election process, undermining the integrity of the ranked voting system.

  • Loss of Trust: If non-voters are allowed to participate in the election, the results could be questioned, leading to a loss of trust in the voting process.

  • Wasted Resources: Unnecessary gas expenditure by unauthorized users could congest the network or incur additional costs for the contract owner.

Tools Used

Manual review

Recommendations

  1. Add Access Control: Implement a require statement to check if the msg.sender is part of the VOTERS array. This ensures that only authorized voters can call the RankedChoice::rankCandidates function and participate in the election.

function rankCandidates(address[] memory orderedCandidates) external {
+ require(_isInArray(VOTERS, msg.sender), "RankedChoice__InvalidVoter");
_rankCandidates(orderedCandidates, msg.sender);
}
  • Benefit: This ensures that only legitimate voters can influence the election, preserving the integrity and fairness of the system.

  1. Consider Using a More Efficient Access Control Mechanism: If the list of voters is large, the linear search in the RankeChoice::_isInArray function could be inefficient. Consider using a mapping(address => bool) to store eligible voters for constant-time lookup:

+ mapping(address => bool) private eligibleVoters;
constructor(address[] memory voters) EIP712("RankedChoice", "1") {
+ for (uint256 i = 0; i < voters.length; i++) {
+ eligibleVoters[voters[i]] = true;
+ }
- VOTERS = voters;
i_presidentalDuration = 1460 days;
s_currentPresident = msg.sender;
s_voteNumber = 0;
}
function rankCandidates(address[] memory orderedCandidates) external {
+ require(eligibleVoters[msg.sender], "RankedChoice__InvalidVoter");
_rankCandidates(orderedCandidates, msg.sender);
}
  1. Emit Events: Emit events when voters successfully rank candidates to ensure transparency and provide an audit trail of legitimate voting actions:

+ event RankedCandidates(address indexed voter, address[] orderedCandidates);
function rankCandidates(address[] memory orderedCandidates) external {
require(eligibleVoters[msg.sender], "RankedChoice__InvalidVoter");
_rankCandidates(orderedCandidates, msg.sender);
+ emit RankedCandidates(msg.sender, orderedCandidates);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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