President Elector

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

Potential Stack Overflow Due to Recursive Function _selectPresidentRecursive

Summary

The _selectPresidentRecursive function uses recursion to eliminate candidates and select a president based on the Ranked Choice Voting algorithm. While the current implementation may work with a small number of candidates, there is a potential risk of a stack overflow if the number of recursive calls becomes too large. This could occur if the MAX_CANDIDATES limit is increased or if future modifications lead to deeper recursion. The issue is of low severity but could impact the contract's reliability and gas efficiency.

Vulnerability Details

  • Affected Function: _selectPresidentRecursive

  • Location in Code:

    function _selectPresidentRecursive(
    address[] memory candidateList,
    uint256 roundNumber
    ) internal returns (address[] memory) {
    if (candidateList.length == 1) {
    return candidateList;
    }
    // ... [Vote tallying and elimination logic] ...
    return _selectPresidentRecursive(newCandidateList, roundNumber + 1);
    }
  • Issue Explanation:

    • Recursive Depth: The function calls itself recursively, with each call representing a new round of candidate elimination.

    • Potential for Stack Overflow:

      • Current Limitations: With MAX_CANDIDATES set to 10, the maximum recursion depth is 9 (since candidates are eliminated one by one until one remains).

      • Risk with Increased Candidates: If MAX_CANDIDATES is increased or not enforced correctly, the recursion depth could exceed the stack size limit of the EVM.

      • Impact of Deep Recursion: The Ethereum Virtual Machine (EVM) has a limited call stack depth (typically 1024 frames). Exceeding this limit results in a runtime exception, causing the transaction to revert.

    • Gas Consumption Concerns:

      • Inefficient Execution: Recursive functions can be less gas-efficient than iterative counterparts due to the overhead of function calls.

      • Potential for Out-of-Gas Errors: Deep recursion increases the risk of exceeding the gas limit for a transaction.

Impact

Severity: Low

  • Contract Reliability: While unlikely with current limitations, a stack overflow would cause the selectPresident function to fail, preventing the election from concluding.

  • Future-Proofing: If the contract is modified in the future to allow more candidates, the risk becomes more significant.

  • Gas Efficiency: Recursion may lead to higher gas costs compared to iterative solutions, impacting the contract's usability.

Tools Used

  • Manual Code Review: Analyzed the recursive implementation and assessed potential risks associated with recursion in Solidity.

  • Understanding of EVM Limitations: Knowledge of the EVM's stack size and gas constraints.

Recommendations

  • Refactor to Iterative Implementation:

    • Convert Recursion to Loop: Replace the recursive calls with a loop that iteratively eliminates candidates until one remains.

    • Example Refactoring:

      function selectPresidentIterative() internal returns (address) {
      address[] memory candidateList = s_candidateList;
      uint256 roundNumber = 0;
      while (candidateList.length > 1) {
      // [Vote tallying logic similar to current implementation]
      // Remove the candidate with the fewest votes
      // [Elimination logic]
      // Prepare for next round
      candidateList = newCandidateList;
      roundNumber++;
      }
      return candidateList[0];
      }
  • Enforce Maximum Candidate Limit:

    • Ensure that MAX_CANDIDATES is strictly enforced when voters submit their rankings.

      if (orderedCandidates.length > MAX_CANDIDATES) {
      revert RankedChoice__TooManyCandidates();
      }
  • Add Safeguards for Recursion Depth:

    • Implement a check to prevent excessive recursion, even within the MAX_CANDIDATES limit.

      require(roundNumber < MAX_CANDIDATES, "Exceeded maximum recursion depth");
  • Optimize Gas Usage:

    • Refactoring to an iterative approach can reduce gas consumption by eliminating the overhead of multiple function calls.

  • Document Limitations:

    • Clearly document the limitations regarding the number of candidates and the potential risks of modifying MAX_CANDIDATES.

  • Test with Maximum Candidates:

    • Write unit tests that simulate the election process with the maximum allowed number of candidates to ensure the function operates correctly without exceeding stack or gas limits.

Updates

Lead Judging Commences

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

A high number of candidates could cause an OOG

Support

FAQs

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