President Elector

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

It is possible to select the first president before presidentalDuration(4 years)

Description
In the first time when the RankedChoice::selectPresident function is called s_previousVoteEndTimeStamp variable is equal to zero, so we can simplify the condition/requirement to block.timestamp <= i_presidentalDuratio and block.timestamp never will be lower than presidentalDuration (4 year) unless we go back to the beginning of human origin.

The contract needs a way to define the previous president selection time to compare the next president selection time with previous one.

Impact

It is possible call RankedChoice::selectPresident function with success before the presidentalDuration.

Proof of Concepts

Add this line of code in the RankedChoiceTest::setUp to simulate that the time at the moment of the deployment is 2024 10:19:49 PM and assuming that the deployment timestamp is the time of the previous president selection.

function setUp() public {
//Setting timestamp to Monday, September 16, 2024 10:19:49 PM => 1726525189
++ vm.warp(1726525189);
for (uint256 i = 0; i < MAX_VOTERS; i++) {
voters.push(address(uint160(i + VOTERS_ADDRESS_MODIFIER)));
}
rankedChoice = new RankedChoice(voters);
for (uint256 i = 0; i < MAX_CANDIDATES; i++) {
candidates.push(address(uint160(i + CANDIDATES_ADDRESS_MODIFIER)));
}
}

Then paste the below snipped code into the RankedChoiceTest.t.sol file

function testSelectPresidentBeforePresidentalDuration() public {
assert(rankedChoice.getCurrentPresident() != candidates[0]);
orderedCandidates = [candidates[0], candidates[1], candidates[2]];
uint256 startingIndex = 0;
uint256 endingIndex = 60;
for (uint256 i = startingIndex; i < endingIndex; i++) {
vm.prank(voters[i]);
rankedChoice.rankCandidates(orderedCandidates);
}
startingIndex = endingIndex + 1;
endingIndex = 100;
orderedCandidates = [candidates[3], candidates[1], candidates[4]];
for (uint256 i = startingIndex; i < endingIndex; i++) {
vm.prank(voters[i]);
rankedChoice.rankCandidates(orderedCandidates);
}
rankedChoice.selectPresident();
assertEq(rankedChoice.getCurrentPresident(), candidates[0]);
}

The test will pass with without passing 4 years before the previous president selection.

Recommended mitigation

The contract needs a way to define the previous president selection time to compare the next president selection time with previous one. A good place to do it could be in the deployment

+ constructor(address[] memory voters, uint256 previousPresidentSelection) EIP712("RankedChoice", "1") {
- constructor(address[] memory voters) EIP712("RankedChoice", "1") {
VOTERS = voters;
i_presidentalDuration = 1460 days;
s_currentPresident = msg.sender;
s_voteNumber = 0;
+ s_previousVoteEndTimeStamp = previousPresidentSelection;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Validated
Assigned finding tags:

`s_previousVoteEndTimeStamp` variable not being initialized correctly

Support

FAQs

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