The selectPresident function can be called immediately after contract deployment without any initial time lock. This allows the first voter to submit a single vote and immediately call selectPresident, effectively electing a president of their choice without participation from other voters. Consequently, the contract becomes locked for the entire presidential term, preventing a fair election process.
Affected Function: selectPresident
Location in Code:
Issue Explanation:
No Initial Time Constraint: At deployment, s_previousVoteEndTimeStamp is uninitialized (defaulting to zero). This means the condition in the if statement:
evaluates to block.timestamp - 0 <= i_presidentalDuration, which is always true for a long duration (e.g., 4 years).
Immediate Election Possible: Since the revert statement triggers when the condition is true, and given the initial state, the revert does not execute, allowing anyone to call selectPresident immediately after deployment.
First Voter Advantage: The first voter can submit their vote and call selectPresident without waiting for other voters, unilaterally deciding the president.
Contract Lock-In: After selectPresident is called, s_previousVoteEndTimeStamp is updated to the current block.timestamp, and s_voteNumber increments. However, due to the condition logic, subsequent calls to selectPresident will revert until i_presidentalDuration has passed, effectively locking the contract for that duration.
Severity: High
Unfair Election: The election process can be hijacked by a single voter, undermining the democratic intent of the voting system.
Contract Lockdown: The contract becomes unusable for the duration of the presidential term, preventing other voters from participating in future elections until the term expires.
Governance Manipulation: The first voter gains disproportionate control over the election outcome and the governance process.
Manual Code Review: Analyzed the initialization of s_previousVoteEndTimeStamp and the condition in selectPresident.
Initialize s_previousVoteEndTimeStamp to Current block.timestamp:
Set s_previousVoteEndTimeStamp to block.timestamp in the constructor to ensure the initial time lock is enforced.
Correct the Conditional Logic:
Ensure that the selectPresident function properly checks whether the presidential duration has passed before allowing a new election.
Improve Error Messaging:
Update the error message to accurately reflect the issue.
Implement a Voting Period Mechanism:
Introduce a defined voting period during which votes can be cast before selectPresident can be called.
Restrict selectPresident Access:
Limit the ability to call selectPresident to authorized entities or through a consensus mechanism to prevent unilateral action.
Require Minimum Participation:
Enforce a minimum number of votes before the president can be selected.
Prevent Contract Locking:
Allow for new elections if the previous one was invalid or did not meet certain criteria (e.g., participation threshold).
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.