ERC20Votes.sol 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Votes.sol)
  3. pragma solidity ^0.8.19;
  4. import {ERC20} from "../ERC20.sol";
  5. import {Votes} from "../../../governance/utils/Votes.sol";
  6. import {SafeCast} from "../../../utils/math/SafeCast.sol";
  7. import {Checkpoints} from "../../../utils/structs/Checkpoints.sol";
  8. /**
  9. * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,
  10. * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.
  11. *
  12. * NOTE: This contract does not provide interface compatibility with Compound's COMP token.
  13. *
  14. * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
  15. * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
  16. * power can be queried through the public accessors {getVotes} and {getPastVotes}.
  17. *
  18. * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
  19. * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
  20. *
  21. * _Available since v4.2._
  22. */
  23. abstract contract ERC20Votes is ERC20, Votes {
  24. /**
  25. * @dev Total supply cap has been exceeded, introducing a risk of votes overflowing.
  26. */
  27. error ERC20ExceededSafeSupply(uint256 increasedSupply, uint256 cap);
  28. /**
  29. * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).
  30. */
  31. function _maxSupply() internal view virtual returns (uint224) {
  32. return type(uint224).max;
  33. }
  34. /**
  35. * @dev Move voting power when tokens are transferred.
  36. *
  37. * Emits a {IVotes-DelegateVotesChanged} event.
  38. */
  39. function _update(address from, address to, uint256 value) internal virtual override {
  40. super._update(from, to, value);
  41. if (from == address(0)) {
  42. uint256 supply = totalSupply();
  43. uint256 cap = _maxSupply();
  44. if (supply > cap) {
  45. revert ERC20ExceededSafeSupply(supply, cap);
  46. }
  47. }
  48. _transferVotingUnits(from, to, value);
  49. }
  50. /**
  51. * @dev Returns the voting units of an `account`.
  52. *
  53. * WARNING: Overriding this function may compromise the internal vote accounting.
  54. * `ERC20Votes` assumes tokens map to voting units 1:1 and this is not easy to change.
  55. */
  56. function _getVotingUnits(address account) internal view virtual override returns (uint256) {
  57. return balanceOf(account);
  58. }
  59. /**
  60. * @dev Get number of checkpoints for `account`.
  61. */
  62. function numCheckpoints(address account) public view virtual returns (uint32) {
  63. return _numCheckpoints(account);
  64. }
  65. /**
  66. * @dev Get the `pos`-th checkpoint for `account`.
  67. */
  68. function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoints.Checkpoint224 memory) {
  69. return _checkpoints(account, pos);
  70. }
  71. }