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.