President Elector

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

Audit of RankedChoice Smart Contract

Summary

The audit of the RankedChoice smart contract identified a critical vulnerability in the implementation of EIP712 signature verification for off-chain vote submissions.

Vulnerability Details

Incorrect EIP712 Signature Verification with Dynamic Arrays

  • Location: rankCandidatesBySig function

  • Description: The contract attempts to verify EIP712 signatures that include a dynamic array (address[] memory orderedCandidates). However, EIP712 does not natively support dynamic arrays in the struct type definitions. The current implementation uses abi.encode with a TYPEHASH that mismatches the actual data types (uint256[] vs. address[]), leading to incorrect hash computation.

bytes32 public constant TYPEHASH = keccak256("rankCandidates(uint256[])");
function rankCandidatesBySig(
address[] memory orderedCandidates,
bytes memory signature
) external {
bytes32 structHash = keccak256(abi.encode(TYPEHASH, orderedCandidates));
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, signature);
_rankCandidates(orderedCandidates, signer);
}
  • Issue Details:

    • Type Mismatch: The TYPEHASH specifies uint256[], but orderedCandidates is an address[], causing a mismatch in the hashed data.

    • Dynamic Array Encoding: EIP712 requires special handling for dynamic arrays, typically involving hashing each element and then hashing the array. The contract does not implement this, resulting in incorrect signature hashes.

    • Potential Exploit: Since signatures will not verify correctly, voters using rankCandidatesBySig may find their votes unaccepted, leading to a denial of service for off-chain vote submissions.

Impact

  • Denial of Service: Voters attempting to submit their rankings via rankCandidatesBySig will be unable to do so due to invalid signature verification.

  • Reduced Participation: The inability to submit votes off-chain can discourage voter participation, undermining the integrity and accessibility of the election process.

  • Reputation Risk: The malfunctioning of a critical feature can damage the trust in the contract and the organization deploying it.

Recommendations

  1. Correct EIP712 Implementation:

    • Define a Struct for the Vote: Create a struct that includes all necessary fields, including the voter's address to prevent replay attacks.

    • Handle Dynamic Arrays Properly: Implement a method to hash the dynamic array according to EIP712 specifications. This often involves hashing each element and then hashing the array as a whole.

    • Update the TYPEHASH: Ensure the TYPEHASH matches the actual data types used in the struct.

  2. Include Voter Address in Signature:

    • Bind Signature to Voter: Include the voter's address in the signed data to prevent misuse of signatures and enhance security.

  3. Add Nonce for Replay Protection:

    • Implement Nonce Management: Use a nonce to prevent replay attacks where a signature could be reused to overwrite a voter's ranking unintentionally.

  4. Thorough Testing:

    • Unit Tests: Implement comprehensive unit tests for the signature verification process.

    • Integration Tests: Test the off-chain signing and on-chain verification flow end-to-end.

  5. Consult EIP712 Libraries:

    • Use Established Libraries: Consider using well-tested libraries or utilities that handle EIP712 encoding for dynamic arrays.

Updates

Lead Judging Commences

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

Typehash hashes the wrong function input.

Support

FAQs

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