Add Governor signature nonces (#4378)

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Co-authored-by: Francisco <fg@frang.io>
Co-authored-by: Sergei Tikhomirov <sergey.s.tikhomirov@gmail.com>
Co-authored-by: Renan Souza <renan.rodrigues.souza1@gmail.com>
This commit is contained in:
Ernesto García
2023-07-03 14:29:30 -06:00
committed by GitHub
parent bb64458928
commit 6e21422737
9 changed files with 264 additions and 73 deletions

View File

@ -12,6 +12,7 @@ import {SafeCast} from "../utils/math/SafeCast.sol";
import {DoubleEndedQueue} from "../utils/structs/DoubleEndedQueue.sol";
import {Address} from "../utils/Address.sol";
import {Context} from "../utils/Context.sol";
import {Nonces} from "../utils/Nonces.sol";
import {IGovernor, IERC6372} from "./IGovernor.sol";
/**
@ -25,12 +26,15 @@ import {IGovernor, IERC6372} from "./IGovernor.sol";
*
* _Available since v4.3._
*/
abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {
abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC721Receiver, IERC1155Receiver {
using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
bytes32 public constant BALLOT_TYPEHASH =
keccak256("Ballot(uint256 proposalId,uint8 support,address voter,uint256 nonce)");
bytes32 public constant EXTENDED_BALLOT_TYPEHASH =
keccak256("ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)");
keccak256(
"ExtendedBallot(uint256 proposalId,uint8 support,address voter,uint256 nonce,string reason,bytes params)"
);
// solhint-disable var-name-mixedcase
struct ProposalCore {
@ -514,17 +518,23 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receive
function castVoteBySig(
uint256 proposalId,
uint8 support,
address voter,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override returns (uint256) {
address voter = ECDSA.recover(
_hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),
address signer = ECDSA.recover(
_hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support, voter, _useNonce(voter)))),
v,
r,
s
);
return _castVote(proposalId, voter, support, "");
if (voter != signer) {
revert GovernorInvalidSigner(signer, voter);
}
return _castVote(proposalId, signer, support, "");
}
/**
@ -533,19 +543,22 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receive
function castVoteWithReasonAndParamsBySig(
uint256 proposalId,
uint8 support,
address voter,
string calldata reason,
bytes memory params,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override returns (uint256) {
address voter = ECDSA.recover(
address signer = ECDSA.recover(
_hashTypedDataV4(
keccak256(
abi.encode(
EXTENDED_BALLOT_TYPEHASH,
proposalId,
support,
voter,
_useNonce(voter),
keccak256(bytes(reason)),
keccak256(params)
)
@ -556,7 +569,11 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receive
s
);
return _castVote(proposalId, voter, support, reason, params);
if (voter != signer) {
revert GovernorInvalidSigner(signer, voter);
}
return _castVote(proposalId, signer, support, reason, params);
}
/**

View File

@ -80,6 +80,11 @@ abstract contract IGovernor is IERC165, IERC6372 {
*/
error GovernorInvalidVoteType();
/**
* @dev The `voter` doesn't match with the recovered `signer`.
*/
error GovernorInvalidSigner(address signer, address voter);
/**
* @dev Emitted when a proposal is created.
*/
@ -355,6 +360,7 @@ abstract contract IGovernor is IERC165, IERC6372 {
function castVoteBySig(
uint256 proposalId,
uint8 support,
address voter,
uint8 v,
bytes32 r,
bytes32 s
@ -368,6 +374,7 @@ abstract contract IGovernor is IERC165, IERC6372 {
function castVoteWithReasonAndParamsBySig(
uint256 proposalId,
uint8 support,
address voter,
string calldata reason,
bytes memory params,
uint8 v,