GovernorCountingOverridable.sol 8.5 KB

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