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
11 months ago
inallhonesty Lead Judge 10 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.