Update docs
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v5.1.0) (governance/utils/Votes.sol)
|
||||
// OpenZeppelin Contracts (last updated v5.2.0) (governance/utils/Votes.sol)
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {IERC5805} from "../../interfaces/IERC5805.sol";
|
||||
@ -71,6 +71,15 @@ abstract contract Votes is Context, EIP712, Nonces, IERC5805 {
|
||||
return "mode=blocknumber&from=default";
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Validate that a timepoint is in the past, and return it as a uint48.
|
||||
*/
|
||||
function _validateTimepoint(uint256 timepoint) internal view returns (uint48) {
|
||||
uint48 currentTimepoint = clock();
|
||||
if (timepoint >= currentTimepoint) revert ERC5805FutureLookup(timepoint, currentTimepoint);
|
||||
return SafeCast.toUint48(timepoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the current amount of votes that `account` has.
|
||||
*/
|
||||
@ -87,11 +96,7 @@ abstract contract Votes is Context, EIP712, Nonces, IERC5805 {
|
||||
* - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.
|
||||
*/
|
||||
function getPastVotes(address account, uint256 timepoint) public view virtual returns (uint256) {
|
||||
uint48 currentTimepoint = clock();
|
||||
if (timepoint >= currentTimepoint) {
|
||||
revert ERC5805FutureLookup(timepoint, currentTimepoint);
|
||||
}
|
||||
return _delegateCheckpoints[account].upperLookupRecent(SafeCast.toUint48(timepoint));
|
||||
return _delegateCheckpoints[account].upperLookupRecent(_validateTimepoint(timepoint));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,11 +112,7 @@ abstract contract Votes is Context, EIP712, Nonces, IERC5805 {
|
||||
* - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.
|
||||
*/
|
||||
function getPastTotalSupply(uint256 timepoint) public view virtual returns (uint256) {
|
||||
uint48 currentTimepoint = clock();
|
||||
if (timepoint >= currentTimepoint) {
|
||||
revert ERC5805FutureLookup(timepoint, currentTimepoint);
|
||||
}
|
||||
return _totalCheckpoints.upperLookupRecent(SafeCast.toUint48(timepoint));
|
||||
return _totalCheckpoints.upperLookupRecent(_validateTimepoint(timepoint));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
84
contracts/governance/utils/VotesExtended.sol
Normal file
84
contracts/governance/utils/VotesExtended.sol
Normal file
@ -0,0 +1,84 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v5.2.0) (governance/utils/VotesExtended.sol)
|
||||
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.
|
||||
*
|
||||
* WARNING: While this contract extends {Votes}, valid uses of {Votes} may not be compatible with
|
||||
* {VotesExtended} without additional considerations. This implementation of {_transferVotingUnits} must
|
||||
* run AFTER the voting weight movement is registered, such that it is reflected on {_getVotingUnits}.
|
||||
*
|
||||
* Said differently, {VotesExtended} MUST be integrated in a way that calls {_transferVotingUnits} AFTER the
|
||||
* asset transfer is registered and balances are updated:
|
||||
*
|
||||
* ```solidity
|
||||
* contract VotingToken is Token, VotesExtended {
|
||||
* function transfer(address from, address to, uint256 tokenId) public override {
|
||||
* super.transfer(from, to, tokenId); // <- Perform the transfer first ...
|
||||
* _transferVotingUnits(from, to, 1); // <- ... then call _transferVotingUnits.
|
||||
* }
|
||||
*
|
||||
* function _getVotingUnits(address account) internal view override returns (uint256) {
|
||||
* return balanceOf(account);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* {ERC20Votes} and {ERC721Votes} follow this pattern and are thus safe to use with {VotesExtended}.
|
||||
*/
|
||||
abstract contract VotesExtended is Votes {
|
||||
using Checkpoints for Checkpoints.Trace160;
|
||||
using Checkpoints for Checkpoints.Trace208;
|
||||
|
||||
mapping(address delegator => Checkpoints.Trace160) private _userDelegationCheckpoints;
|
||||
mapping(address account => Checkpoints.Trace208) private _userVotingUnitsCheckpoints;
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
return address(_userDelegationCheckpoints[account].upperLookupRecent(_validateTimepoint(timepoint)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
return _userVotingUnitsCheckpoints[account].upperLookupRecent(_validateTimepoint(timepoint));
|
||||
}
|
||||
|
||||
/// @inheritdoc Votes
|
||||
function _delegate(address account, address delegatee) internal virtual override {
|
||||
super._delegate(account, delegatee);
|
||||
|
||||
_userDelegationCheckpoints[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)) {
|
||||
_userVotingUnitsCheckpoints[from].push(clock(), SafeCast.toUint208(_getVotingUnits(from)));
|
||||
}
|
||||
if (to != address(0)) {
|
||||
_userVotingUnitsCheckpoints[to].push(clock(), SafeCast.toUint208(_getVotingUnits(to)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user