In the SecurityCouncilNomineeElectionGovernor and SecurityCouncilMemberElectionGovernor contracts, users can provide a signature to allow someone else to vote on their behalf using the castVoteWithReasonAndParamsBySig() function, which is in Openzeppelin’s GovernorUpgradeable:
GovernorUpgradeable.sol#L480-L495
address voter = ECDSAUpgradeable.recover(
_hashTypedDataV4(
keccak256(
abi.encode(
EXTENDED_BALLOT_TYPEHASH,
proposalId,
support,
keccak256(bytes(reason)),
keccak256(params)
)
)
),
v,
r,
s
);
As seen from above, the signature provided does not include a nonce. This becomes an issue in nominee and member elections, as users can choose not to use all of their votes in a single call, allowing them split their voting power amongst contenders/nominees:
Nominee Election Specification
> A single delegate can split their vote across multiple candidates.
> Additionally, delegates can cast votes for more than one nominee:
>
> * Split voting. delegates can split their tokens across multiple nominees, with 1 token representing 1 vote.
Due to the lack of a nonce, castVoteWithReasonAndParamsBySig() can be called multiple times with the same signature.
Therefore, if a user provides a signature to use a portion of his votes, an attacker can repeatedly call castVoteWithReasonAndParamsBySig() with the same signature to use up more votes than the user originally intended.
Due to the lack of signature replay protection in castVoteWithReasonAndParamsBySig(), during nominee or member elections, an attacker can force a voter to use more votes on a contender/nominee than intended by replaying his signature multiple times.
Assume that a nominee election is currently ongoing:
In the scenario above, Alice has managed to allocate all of Bob’s votes to contender A against his will. Note that this can also occur in member elections, where split voting is also allowed.
Consider adding some form of signature replay protection in the SecurityCouncilNomineeElectionGovernor and SecurityCouncilMemberElectionGovernor contracts.
One way of achieving this is to override the castVoteWithReasonAndParamsBySig() function to include a nonce in the signature, which would protect against signature replay.
Other
The text was updated successfully, but these errors were encountered:
All reactions