GovernorCountingOverridable.sol 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorCountingOverridable.sol)
  3. pragma solidity ^0.8.20;
  4. import {SignatureChecker} from "../../utils/cryptography/SignatureChecker.sol";
  5. import {SafeCast} from "../../utils/math/SafeCast.sol";
  6. import {VotesExtended} from "../utils/VotesExtended.sol";
  7. import {GovernorVotes} from "./GovernorVotes.sol";
  8. import {IGovernor, Governor} from "../Governor.sol";
  9. /**
  10. * @dev Extension of {Governor} which enables delegators to override the vote of their delegates. This module requires a
  11. * token that inherits {VotesExtended}.
  12. */
  13. abstract contract GovernorCountingOverridable is GovernorVotes {
  14. bytes32 public constant OVERRIDE_BALLOT_TYPEHASH =
  15. keccak256("OverrideBallot(uint256 proposalId,uint8 support,address voter,uint256 nonce,string reason)");
  16. /**
  17. * @dev Supported vote types. Matches Governor Bravo ordering.
  18. */
  19. enum VoteType {
  20. Against,
  21. For,
  22. Abstain
  23. }
  24. struct VoteReceipt {
  25. uint8 casted; // 0 if vote was not casted. Otherwise: support + 1
  26. bool hasOverridden;
  27. uint208 overriddenWeight;
  28. }
  29. struct ProposalVote {
  30. uint256[3] votes;
  31. mapping(address voter => VoteReceipt) voteReceipt;
  32. }
  33. /// @dev The votes casted by `delegate` were reduced by `weight` after an override vote was casted by the original token holder
  34. event VoteReduced(address indexed delegate, uint256 proposalId, uint8 support, uint256 weight);
  35. /// @dev A delegated vote on `proposalId` was overridden by `weight`
  36. event OverrideVoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);
  37. error GovernorAlreadyOverriddenVote(address account);
  38. mapping(uint256 proposalId => ProposalVote) private _proposalVotes;
  39. /// @inheritdoc IGovernor
  40. // solhint-disable-next-line func-name-mixedcase
  41. function COUNTING_MODE() public pure virtual override returns (string memory) {
  42. return "support=bravo,override&quorum=for,abstain&overridable=true";
  43. }
  44. /**
  45. * @dev See {IGovernor-hasVoted}.
  46. *
  47. * NOTE: Calling {castVote} (or similar) casts a vote using the voting power that is delegated to the voter.
  48. * Conversely, calling {castOverrideVote} (or similar) uses the voting power of the account itself, from its asset
  49. * balances. Casting an "override vote" does not count as voting and won't be reflected by this getter. Consider
  50. * using {hasVotedOverride} to check if an account has casted an "override vote" for a given proposal id.
  51. */
  52. function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
  53. return _proposalVotes[proposalId].voteReceipt[account].casted != 0;
  54. }
  55. /**
  56. * @dev Check if an `account` has overridden their delegate for a proposal.
  57. */
  58. function hasVotedOverride(uint256 proposalId, address account) public view virtual returns (bool) {
  59. return _proposalVotes[proposalId].voteReceipt[account].hasOverridden;
  60. }
  61. /**
  62. * @dev Accessor to the internal vote counts.
  63. */
  64. function proposalVotes(
  65. uint256 proposalId
  66. ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) {
  67. uint256[3] storage votes = _proposalVotes[proposalId].votes;
  68. return (votes[uint8(VoteType.Against)], votes[uint8(VoteType.For)], votes[uint8(VoteType.Abstain)]);
  69. }
  70. /// @inheritdoc Governor
  71. function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
  72. uint256[3] storage votes = _proposalVotes[proposalId].votes;
  73. return quorum(proposalSnapshot(proposalId)) <= votes[uint8(VoteType.For)] + votes[uint8(VoteType.Abstain)];
  74. }
  75. /**
  76. * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
  77. */
  78. function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
  79. uint256[3] storage votes = _proposalVotes[proposalId].votes;
  80. return votes[uint8(VoteType.For)] > votes[uint8(VoteType.Against)];
  81. }
  82. /**
  83. * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
  84. *
  85. * NOTE: called by {Governor-_castVote} which emits the {IGovernor-VoteCast} (or {IGovernor-VoteCastWithParams})
  86. * event.
  87. */
  88. function _countVote(
  89. uint256 proposalId,
  90. address account,
  91. uint8 support,
  92. uint256 totalWeight,
  93. bytes memory /*params*/
  94. ) internal virtual override returns (uint256) {
  95. ProposalVote storage proposalVote = _proposalVotes[proposalId];
  96. if (support > uint8(VoteType.Abstain)) {
  97. revert GovernorInvalidVoteType();
  98. }
  99. if (proposalVote.voteReceipt[account].casted != 0) {
  100. revert GovernorAlreadyCastVote(account);
  101. }
  102. totalWeight -= proposalVote.voteReceipt[account].overriddenWeight;
  103. proposalVote.votes[support] += totalWeight;
  104. proposalVote.voteReceipt[account].casted = support + 1;
  105. return totalWeight;
  106. }
  107. /**
  108. * @dev Variant of {Governor-_countVote} that deals with vote overrides.
  109. *
  110. * NOTE: See {hasVoted} for more details about the difference between {castVote} and {castOverrideVote}.
  111. */
  112. function _countOverride(uint256 proposalId, address account, uint8 support) internal virtual returns (uint256) {
  113. ProposalVote storage proposalVote = _proposalVotes[proposalId];
  114. if (support > uint8(VoteType.Abstain)) {
  115. revert GovernorInvalidVoteType();
  116. }
  117. if (proposalVote.voteReceipt[account].hasOverridden) {
  118. revert GovernorAlreadyOverriddenVote(account);
  119. }
  120. uint256 snapshot = proposalSnapshot(proposalId);
  121. uint256 overriddenWeight = VotesExtended(address(token())).getPastBalanceOf(account, snapshot);
  122. address delegate = VotesExtended(address(token())).getPastDelegate(account, snapshot);
  123. uint8 delegateCasted = proposalVote.voteReceipt[delegate].casted;
  124. proposalVote.voteReceipt[account].hasOverridden = true;
  125. proposalVote.votes[support] += overriddenWeight;
  126. if (delegateCasted == 0) {
  127. proposalVote.voteReceipt[delegate].overriddenWeight += SafeCast.toUint208(overriddenWeight);
  128. } else {
  129. uint8 delegateSupport = delegateCasted - 1;
  130. proposalVote.votes[delegateSupport] -= overriddenWeight;
  131. emit VoteReduced(delegate, proposalId, delegateSupport, overriddenWeight);
  132. }
  133. return overriddenWeight;
  134. }
  135. /// @dev Variant of {Governor-_castVote} that deals with vote overrides. Returns the overridden weight.
  136. function _castOverride(
  137. uint256 proposalId,
  138. address account,
  139. uint8 support,
  140. string calldata reason
  141. ) internal virtual returns (uint256) {
  142. _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Active));
  143. uint256 overriddenWeight = _countOverride(proposalId, account, support);
  144. emit OverrideVoteCast(account, proposalId, support, overriddenWeight, reason);
  145. _tallyUpdated(proposalId);
  146. return overriddenWeight;
  147. }
  148. /// @dev Public function for casting an override vote. Returns the overridden weight.
  149. function castOverrideVote(
  150. uint256 proposalId,
  151. uint8 support,
  152. string calldata reason
  153. ) public virtual returns (uint256) {
  154. address voter = _msgSender();
  155. return _castOverride(proposalId, voter, support, reason);
  156. }
  157. /// @dev Public function for casting an override vote using a voter's signature. Returns the overridden weight.
  158. function castOverrideVoteBySig(
  159. uint256 proposalId,
  160. uint8 support,
  161. address voter,
  162. string calldata reason,
  163. bytes calldata signature
  164. ) public virtual returns (uint256) {
  165. bool valid = SignatureChecker.isValidSignatureNow(
  166. voter,
  167. _hashTypedDataV4(
  168. keccak256(
  169. abi.encode(
  170. OVERRIDE_BALLOT_TYPEHASH,
  171. proposalId,
  172. support,
  173. voter,
  174. _useNonce(voter),
  175. keccak256(bytes(reason))
  176. )
  177. )
  178. ),
  179. signature
  180. );
  181. if (!valid) {
  182. revert GovernorInvalidSignature(voter);
  183. }
  184. return _castOverride(proposalId, voter, support, reason);
  185. }
  186. }