President Elector

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

Data structure definition mismatch in TYPEHASH stVariable

Summary

The TYPEHASH data structure mismatch (uint256[] vs. address[]) could break voter`s signature verification.

Vulnerability Details

When signing a message using EIP-712 (typed structured data signing), both the signer and the verifier must agree on:

  1. What data is being signed.

  2. The exact format (data types) of the data.

If a voter signs a message off-chain with address[] (presumably correct format for candidate addresses, as the voting mechanism is tied to an address of a candidate) but the contract uses uint256[] (wrong format), the encoded data and the resulting hash will be different.

Impact

The Signature Type Mismatch in the TYPEHASH could break functionality by leading to incorrect signature verification, resulting in invalid signatures being mistakenly accepted or valid signatures being rejected. This issue occurs because the hash being signed by the voter would differ from the hash that the contract is using to recover the signer's address. Although voters have another way of casting their votes for candidates, the protocol intends to have a functionality of doing this without paying gas fees, presumably for voters that cannot pay them to the chain. These voters could also be the majority, thus depriving them of their right to vote and leaving the election process in the hands of the rich.

POC

  • Voter’s Perspective (Signing Data):

  • When a voter signs the message, they sign the hash of the structured data that includes the ordered candidate addresses (address[]).

  • Let’s say the voter wants to vote for these candidates (with example addresses): [0xABC123..., 0xDEF456..., 0xGHI789...]

  • Using EIP-712, the hash they are signing includes the encoding of this data assuming the data type address[]. The voter would sign the following data:
    keccak256(abi.encode(TYPEHASH, [0xABC123..., 0xDEF456..., 0xGHI789...]))

    where TYPEHASH = keccak256("rankCandidates(address[])").

  • Contract’s Perspective (Verifying Signature):

    • In the contract, the TYPEHASH is incorrectly set to keccak256("rankCandidates(uint256[])").

    • When the contract receives the signature, it tries to recover the signer by first hashing the orderedCandidates using abi.encode(TYPEHASH, orderedCandidates) where it expects orderedCandidates to be an array of uint256[] instead of address[].

    • This mismatch in data types (uint256[] vs address[]) will result in different byte encodings. For example:

      • address: 0xABC123... is encoded as 20 bytes (address size).

      • uint256: 0xABC123... is interpreted as a 32-byte integer and encoded differently.

    • The contract will produce a hash based on the incorrect encoding:

      `keccak256(abi.encode(keccak256("rankCandidates(uint256[])"), [0xABC123..., 0xDEF456..., 0xGHI789...]))`
  • Hash Mismatch:

    • The hash generated by the voter and the hash generated by the contract will be different due to the incorrect assumption of the data type in the TYPEHASH.

    • The voter's signature is tied to the hash of address[], while the contract uses the hash of uint256[]. As a result, the contract will recover the wrong signer address or fail to recover any address.

Tools Used

Manual review

Recommendations

Change the data definition in TYPEHASH variable to address[].

bytes32 public constant TYPEHASH = keccak256("rankCandidates(address[])");
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 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.