President Elector

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

The`selectPresident`function lacks a length check for`s_candidateList`, which leads to revert

Summary

TheselectPresidentfunction definition lacks a length check fors_candidateList. In_selectPresidentRecursive,candidateList[0]is used directly, which will trigger an array out-of-bounds access error when the length ofcandidateListis 0, causing the transaction to fail.

function _selectPresidentRecursive(
address[] memory candidateList,
uint256 roundNumber
) internal returns (address[] memory) {
if (candidateList.length == 1) {
return candidateList;
}
………………
// @bug, if candidateList's length is 0, the candidateList[0] will cause array out-of-bounds access.
address fewestVotesCandidate = candidateList[0];
……
}

Vulnerability Details

this is the POC, add the code to the RankedChoiceTest.t.sol file, the selectPresident function will call the _selectPresidentRecursive with the parameter candidateList=[], when use the candidateList[0], the array out-of-bounds access error is triggered.

function testSelectPresidentOninit() public {
vm.warp(block.timestamp + rankedChoice.getDuration());
vm.expectRevert();
rankedChoice.selectPresident();
}

Impact

TheselectPresidentfunction will revert if it been called without settings_candidateList.

Tools Used

foundry, vscode

Recommendations

++ error RankedChoice__CandidateIsEmpty();
function selectPresident() external {
if (
block.timestamp - s_previousVoteEndTimeStamp <=
i_presidentalDuration
) {
revert RankedChoice__NotTimeToVote();
}
for (uint256 i = 0; i < VOTERS.length; i++) {
address[] memory orderedCandidates = s_rankings[VOTERS[i]][
s_voteNumber
];
for (uint256 j = 0; j < orderedCandidates.length; j++) {
if (!_isInArray(s_candidateList, orderedCandidates[j])) {
s_candidateList.push(orderedCandidates[j]);
}
}
}
++ if(s_candidateList.length == 0){
++ revert RankedChoice__CandidateIsEmpty();
++ }
address[] memory winnerList = _selectPresidentRecursive(
s_candidateList,
0
);
if (winnerList.length != 1) {
revert RankedChoice__SomethingWentWrong();
}
// Reset the election and set President
s_currentPresident = winnerList[0];
s_candidateList = new address[](0);
s_previousVoteEndTimeStamp = block.timestamp;
s_voteNumber += 1;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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