President Elector

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

Incorrect time validation leading to "selectPresident" to execute prematurely and bypass the initial president

Summary

The selectPresident function executes prematurely, allowing the election to be decided before the designated voting period ends. This is due to the s_previousVoteEndTimeStamp variable not being initialized correctly.

Vulnerability Details:

The issue lies in the logic of the selectPresident function, particularly in the condition that checks whether the voting duration has passed. The check:

if (block.timestamp - s_previousVoteEndTimeStamp <= i_presidentalDuration)

is meant to ensure that the function cannot be called before the specified duration of 1460 days. However, due to the way the code is structured, a malicious voter can rank themselves first in the rankCandidates function and immediately call selectPresident. Since there is no correct validation preventing voters from calling selectPresident prematurely, the malicious voter can bypass the time check and become president before the 4 years duration has passed.

Impact

A malicious voter can become president right after the deployment of the contract, rendering the 1460-day waiting period irrelevant and giving them the presidency in the first term. this could lead to undermining the integrity of the entire election mechanism.

Proof of concept

  • The contract is deployed with the uninitialized s_previousVoteEndTimeStamp variable.

  • Using Remix IDE and a test account,0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 is currently the deployer and the initial president, and selectPresident should normally execute after the 4 year term has passed.

  • Malicious Voter call rankCandidates ranking their address 1st.

  • Malicious Voter Immediately call the selectPresident function.

  • The function executes and selects the voter as president, even though the voting period has not ended.

0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2 Which is voter is now the current president and any other queued votes are discarded since the new term has started.

Tools used:

  • Remix IDE

  • Manual review

Recommendations

Ensure that s_previousVoteEndTimeStamp is initialized to the current block timestamp in the constructor.

constructor(address[] memory voters) EIP712("RankedChoice", "1") {
VOTERS = voters;
i_presidentialDuration = 1460 days;
s_currentPresident = msg.sender;
s_voteNumber = 0;
s_previousVoteEndTimeStamp = block.timestamp; //Initialize the timestamp
}

This will allow the deployer(msg.sender) to become the initial president at deployment for the specified duration (1460 days) while allowing the voters to queue up their votes for the next president.

Updates

Lead Judging Commences

inallhonesty Lead Judge 9 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.