12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- // SPDX-License-Identifier: MIT
- pragma solidity ^0.8.20;
- import {Checkpoints} from "../../utils/structs/Checkpoints.sol";
- import {Votes} from "./Votes.sol";
- import {SafeCast} from "../../utils/math/SafeCast.sol";
- /**
- * @dev Extension of {Votes} that adds checkpoints for delegations and balances.
- */
- abstract contract VotesExtended is Votes {
- using SafeCast for uint256;
- using Checkpoints for Checkpoints.Trace160;
- using Checkpoints for Checkpoints.Trace208;
- mapping(address delegatee => Checkpoints.Trace160) private _delegateCheckpoints;
- mapping(address account => Checkpoints.Trace208) private _balanceOfCheckpoints;
- /**
- * @dev Returns the delegate of an `account` at a specific moment in the past. If the `clock()` is
- * configured to use block numbers, this will return the value at the end of the corresponding block.
- *
- * Requirements:
- *
- * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.
- */
- function getPastDelegate(address account, uint256 timepoint) public view virtual returns (address) {
- uint48 currentTimepoint = clock();
- if (timepoint >= currentTimepoint) {
- revert ERC5805FutureLookup(timepoint, currentTimepoint);
- }
- return address(_delegateCheckpoints[account].upperLookupRecent(timepoint.toUint48()));
- }
- /**
- * @dev Returns the `balanceOf` of an `account` at a specific moment in the past. If the `clock()` is
- * configured to use block numbers, this will return the value at the end of the corresponding block.
- *
- * Requirements:
- *
- * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.
- */
- function getPastBalanceOf(address account, uint256 timepoint) public view virtual returns (uint256) {
- uint48 currentTimepoint = clock();
- if (timepoint >= currentTimepoint) {
- revert ERC5805FutureLookup(timepoint, currentTimepoint);
- }
- return _balanceOfCheckpoints[account].upperLookupRecent(timepoint.toUint48());
- }
- /// @inheritdoc Votes
- function _delegate(address account, address delegatee) internal virtual override {
- super._delegate(account, delegatee);
- _delegateCheckpoints[account].push(clock(), uint160(delegatee));
- }
- /// @inheritdoc Votes
- function _transferVotingUnits(address from, address to, uint256 amount) internal virtual override {
- super._transferVotingUnits(from, to, amount);
- if (from != to) {
- if (from != address(0)) {
- _balanceOfCheckpoints[from].push(clock(), _getVotingUnits(from).toUint208());
- }
- if (to != address(0)) {
- _balanceOfCheckpoints[to].push(clock(), _getVotingUnits(to).toUint208());
- }
- }
- }
- }
|