1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- // SPDX-License-Identifier: MIT
- // OpenZeppelin Contracts (last updated v5.1.0-rc.0) (token/ERC20/extensions/ERC20Votes.sol)
- pragma solidity ^0.8.20;
- import {ERC20} from "../ERC20.sol";
- import {Votes} from "../../../governance/utils/Votes.sol";
- import {Checkpoints} from "../../../utils/structs/Checkpoints.sol";
- /**
- * @dev Extension of ERC-20 to support Compound-like voting and delegation. This version is more generic than Compound's,
- * and supports token supply up to 2^208^ - 1, while COMP is limited to 2^96^ - 1.
- *
- * NOTE: This contract does not provide interface compatibility with Compound's COMP token.
- *
- * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
- * by calling the {Votes-delegate} function directly, or by providing a signature to be used with {Votes-delegateBySig}. Voting
- * power can be queried through the public accessors {Votes-getVotes} and {Votes-getPastVotes}.
- *
- * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
- * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
- */
- abstract contract ERC20Votes is ERC20, Votes {
- /**
- * @dev Total supply cap has been exceeded, introducing a risk of votes overflowing.
- */
- error ERC20ExceededSafeSupply(uint256 increasedSupply, uint256 cap);
- /**
- * @dev Maximum token supply. Defaults to `type(uint208).max` (2^208^ - 1).
- *
- * This maximum is enforced in {_update}. It limits the total supply of the token, which is otherwise a uint256,
- * so that checkpoints can be stored in the Trace208 structure used by {Votes}. Increasing this value will not
- * remove the underlying limitation, and will cause {_update} to fail because of a math overflow in
- * {Votes-_transferVotingUnits}. An override could be used to further restrict the total supply (to a lower value) if
- * additional logic requires it. When resolving override conflicts on this function, the minimum should be
- * returned.
- */
- function _maxSupply() internal view virtual returns (uint256) {
- return type(uint208).max;
- }
- /**
- * @dev Move voting power when tokens are transferred.
- *
- * Emits a {IVotes-DelegateVotesChanged} event.
- */
- function _update(address from, address to, uint256 value) internal virtual override {
- super._update(from, to, value);
- if (from == address(0)) {
- uint256 supply = totalSupply();
- uint256 cap = _maxSupply();
- if (supply > cap) {
- revert ERC20ExceededSafeSupply(supply, cap);
- }
- }
- _transferVotingUnits(from, to, value);
- }
- /**
- * @dev Returns the voting units of an `account`.
- *
- * WARNING: Overriding this function may compromise the internal vote accounting.
- * `ERC20Votes` assumes tokens map to voting units 1:1 and this is not easy to change.
- */
- function _getVotingUnits(address account) internal view virtual override returns (uint256) {
- return balanceOf(account);
- }
- /**
- * @dev Get number of checkpoints for `account`.
- */
- function numCheckpoints(address account) public view virtual returns (uint32) {
- return _numCheckpoints(account);
- }
- /**
- * @dev Get the `pos`-th checkpoint for `account`.
- */
- function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoints.Checkpoint208 memory) {
- return _checkpoints(account, pos);
- }
- }
|