ERC20Votes.sol 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "./draft-ERC20Permit.sol";
  4. import "../../../utils/math/Math.sol";
  5. import "../../../utils/math/SafeCast.sol";
  6. import "../../../utils/cryptography/ECDSA.sol";
  7. /**
  8. * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,
  9. * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.
  10. *
  11. * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.
  12. *
  13. * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
  14. * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
  15. * power can be queried through the public accessors {getVotes} and {getPastVotes}.
  16. *
  17. * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
  18. * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
  19. * Enabling self-delegation can easily be done by overriding the {delegates} function. Keep in mind however that this
  20. * will significantly increase the base gas cost of transfers.
  21. *
  22. * _Available since v4.2._
  23. */
  24. abstract contract ERC20Votes is ERC20Permit {
  25. struct Checkpoint {
  26. uint32 fromBlock;
  27. uint224 votes;
  28. }
  29. bytes32 private constant _DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
  30. mapping (address => address) private _delegates;
  31. mapping (address => Checkpoint[]) private _checkpoints;
  32. Checkpoint[] private _totalSupplyCheckpoints;
  33. /**
  34. * @dev Emitted when an account changes their delegate.
  35. */
  36. event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
  37. /**
  38. * @dev Emitted when a token transfer or delegate change results in changes to an account's voting power.
  39. */
  40. event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
  41. /**
  42. * @dev Get the `pos`-th checkpoint for `account`.
  43. */
  44. function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {
  45. return _checkpoints[account][pos];
  46. }
  47. /**
  48. * @dev Get number of checkpoints for `account`.
  49. */
  50. function numCheckpoints(address account) public view virtual returns (uint32) {
  51. return SafeCast.toUint32(_checkpoints[account].length);
  52. }
  53. /**
  54. * @dev Get the address `account` is currently delegating to.
  55. */
  56. function delegates(address account) public view virtual returns (address) {
  57. return _delegates[account];
  58. }
  59. /**
  60. * @dev Gets the current votes balance for `account`
  61. */
  62. function getVotes(address account) public view returns (uint256) {
  63. uint256 pos = _checkpoints[account].length;
  64. return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
  65. }
  66. /**
  67. * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.
  68. *
  69. * Requirements:
  70. *
  71. * - `blockNumber` must have been already mined
  72. */
  73. function getPastVotes(address account, uint256 blockNumber) public view returns (uint256) {
  74. require(blockNumber < block.number, "ERC20Votes: block not yet mined");
  75. return _checkpointsLookup(_checkpoints[account], blockNumber);
  76. }
  77. /**
  78. * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.
  79. * It is but NOT the sum of all the delegated votes!
  80. *
  81. * Requirements:
  82. *
  83. * - `blockNumber` must have been already mined
  84. */
  85. function getPastTotalSupply(uint256 blockNumber) public view returns (uint256) {
  86. require(blockNumber < block.number, "ERC20Votes: block not yet mined");
  87. return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
  88. }
  89. /**
  90. * @dev Lookup a value in a list of (sorted) checkpoints.
  91. */
  92. function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {
  93. // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.
  94. //
  95. // During the loop, the index of the wanted checkpoint remains in the range [low, high).
  96. // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.
  97. // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)
  98. // - If the middle checkpoint is before `blockNumber`, we look in [mid+1, high)
  99. // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not
  100. // out of bounds (in which case we're looking too far in the past and the result is 0).
  101. // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is
  102. // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out
  103. // the same.
  104. uint256 high = ckpts.length;
  105. uint256 low = 0;
  106. while (low < high) {
  107. uint256 mid = Math.average(low, high);
  108. if (ckpts[mid].fromBlock > blockNumber) {
  109. high = mid;
  110. } else {
  111. low = mid + 1;
  112. }
  113. }
  114. return high == 0 ? 0 : ckpts[high - 1].votes;
  115. }
  116. /**
  117. * @dev Delegate votes from the sender to `delegatee`.
  118. */
  119. function delegate(address delegatee) public virtual {
  120. return _delegate(_msgSender(), delegatee);
  121. }
  122. /**
  123. * @dev Delegates votes from signer to `delegatee`
  124. */
  125. function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s)
  126. public virtual
  127. {
  128. require(block.timestamp <= expiry, "ERC20Votes: signature expired");
  129. address signer = ECDSA.recover(
  130. _hashTypedDataV4(keccak256(abi.encode(
  131. _DELEGATION_TYPEHASH,
  132. delegatee,
  133. nonce,
  134. expiry
  135. ))),
  136. v, r, s
  137. );
  138. require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce");
  139. return _delegate(signer, delegatee);
  140. }
  141. /**
  142. * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).
  143. */
  144. function _maxSupply() internal view virtual returns (uint224) {
  145. return type(uint224).max;
  146. }
  147. /**
  148. * @dev Snapshots the totalSupply after it has been increased.
  149. */
  150. function _mint(address account, uint256 amount) internal virtual override {
  151. super._mint(account, amount);
  152. require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes");
  153. _writeCheckpoint(_totalSupplyCheckpoints, add, amount);
  154. }
  155. /**
  156. * @dev Snapshots the totalSupply after it has been decreased.
  157. */
  158. function _burn(address account, uint256 amount) internal virtual override {
  159. super._burn(account, amount);
  160. _writeCheckpoint(_totalSupplyCheckpoints, subtract, amount);
  161. }
  162. /**
  163. * @dev Move voting power when tokens are transferred.
  164. *
  165. * Emits a {DelegateVotesChanged} event.
  166. */
  167. function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
  168. _moveVotingPower(delegates(from), delegates(to), amount);
  169. }
  170. /**
  171. * @dev Change delegation for `delegator` to `delegatee`.
  172. *
  173. * Emits events {DelegateChanged} and {DelegateVotesChanged}.
  174. */
  175. function _delegate(address delegator, address delegatee) internal virtual {
  176. address currentDelegate = delegates(delegator);
  177. uint256 delegatorBalance = balanceOf(delegator);
  178. _delegates[delegator] = delegatee;
  179. emit DelegateChanged(delegator, currentDelegate, delegatee);
  180. _moveVotingPower(currentDelegate, delegatee, delegatorBalance);
  181. }
  182. function _moveVotingPower(address src, address dst, uint256 amount) private {
  183. if (src != dst && amount > 0) {
  184. if (src != address(0)) {
  185. (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], subtract, amount);
  186. emit DelegateVotesChanged(src, oldWeight, newWeight);
  187. }
  188. if (dst != address(0)) {
  189. (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], add, amount);
  190. emit DelegateVotesChanged(dst, oldWeight, newWeight);
  191. }
  192. }
  193. }
  194. function _writeCheckpoint(
  195. Checkpoint[] storage ckpts,
  196. function (uint256, uint256) view returns (uint256) op,
  197. uint256 delta
  198. )
  199. private returns (uint256 oldWeight, uint256 newWeight)
  200. {
  201. uint256 pos = ckpts.length;
  202. oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes;
  203. newWeight = op(oldWeight, delta);
  204. if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {
  205. ckpts[pos - 1].votes = SafeCast.toUint224(newWeight);
  206. } else {
  207. ckpts.push(Checkpoint({
  208. fromBlock: SafeCast.toUint32(block.number),
  209. votes: SafeCast.toUint224(newWeight)
  210. }));
  211. }
  212. }
  213. function add(uint256 a, uint256 b) private pure returns (uint256) {
  214. return a + b;
  215. }
  216. function subtract(uint256 a, uint256 b) private pure returns (uint256) {
  217. return a - b;
  218. }
  219. }