generated from ScopeLift/foundry-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added GovernorVotesCompQuorumFraction for settable quorum
- Loading branch information
Showing
5 changed files
with
142 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// SPDX-License-Identifier: MIT | ||
// OpenZeppelin Contracts (last updated v4.9.0) | ||
// (governance/extensions/GovernorVotesQuorumFraction.sol) | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import { | ||
ERC20VotesComp, | ||
GovernorVotesComp | ||
} from "@openzeppelin/contracts/governance/extensions/GovernorVotesComp.sol"; | ||
import "@openzeppelin/contracts/utils/Checkpoints.sol"; | ||
import "@openzeppelin/contracts/utils/math/SafeCast.sol"; | ||
|
||
/** | ||
* @dev Extension of {Governor} for voting weight extraction from an {GovernorVotesComp} token and a | ||
* quorum | ||
* expressed as a fraction of the total supply. | ||
*/ | ||
abstract contract GovernorVotesCompQuorumFraction is GovernorVotesComp { | ||
using Checkpoints for Checkpoints.Trace224; | ||
|
||
uint256 private _quorumNumerator; // DEPRECATED in favor of _quorumNumeratorHistory | ||
|
||
/// @custom:oz-retyped-from Checkpoints.History | ||
Checkpoints.Trace224 private _quorumNumeratorHistory; | ||
|
||
event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator); | ||
|
||
/** | ||
* @dev Initialize quorum as a fraction of the token's total supply. | ||
* | ||
* The fraction is specified as `numerator / denominator`. By default the denominator is 100, so | ||
* quorum is pecified as a percent: a numerator of 10 corresponds to quorum being 10% of total | ||
* supply. | ||
* The denominator can be customized by overriding {quorumDenominator}. | ||
*/ | ||
constructor(uint256 quorumNumeratorValue) { | ||
_updateQuorumNumerator(quorumNumeratorValue); | ||
} | ||
|
||
/** | ||
* @dev Returns the current quorum numerator. See {quorumDenominator}. | ||
*/ | ||
function quorumNumerator() public view virtual returns (uint256) { | ||
return _quorumNumeratorHistory._checkpoints.length == 0 | ||
? _quorumNumerator | ||
: _quorumNumeratorHistory.latest(); | ||
} | ||
|
||
/** | ||
* @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}. | ||
*/ | ||
function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) { | ||
// If history is empty, fallback to old storage | ||
uint256 length = _quorumNumeratorHistory._checkpoints.length; | ||
if (length == 0) return _quorumNumerator; | ||
|
||
// Optimistic search, check the latest checkpoint | ||
Checkpoints.Checkpoint224 memory latest = _quorumNumeratorHistory._checkpoints[length - 1]; | ||
if (latest._key <= timepoint) return latest._value; | ||
|
||
// Otherwise, do the binary search | ||
return _quorumNumeratorHistory.upperLookupRecent(SafeCast.toUint32(timepoint)); | ||
} | ||
|
||
/** | ||
* @dev Returns the quorum denominator. Defaults to 100, but may be overridden. | ||
*/ | ||
function quorumDenominator() public view virtual returns (uint256) { | ||
return 100; | ||
} | ||
|
||
/** | ||
* @dev Returns the quorum for a timepoint, in terms of number of votes: | ||
* `supply * numerator / denominator`. | ||
*/ | ||
function quorum(uint256 timepoint) public view virtual override returns (uint256) { | ||
return (token.totalSupply() * quorumNumerator(timepoint)) / quorumDenominator(); | ||
} | ||
|
||
/** | ||
* @dev Changes the quorum numerator. | ||
* | ||
* Emits a {QuorumNumeratorUpdated} event. | ||
* | ||
* Requirements: | ||
* | ||
* - Must be called through a governance proposal. | ||
* - New numerator must be smaller or equal to the denominator. | ||
*/ | ||
function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance { | ||
_updateQuorumNumerator(newQuorumNumerator); | ||
} | ||
|
||
/** | ||
* @dev Changes the quorum numerator. | ||
* | ||
* Emits a {QuorumNumeratorUpdated} event. | ||
* | ||
* Requirements: | ||
* | ||
* - New numerator must be smaller or equal to the denominator. | ||
*/ | ||
function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual { | ||
require( | ||
newQuorumNumerator <= quorumDenominator(), | ||
"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator" | ||
); | ||
|
||
uint256 oldQuorumNumerator = quorumNumerator(); | ||
|
||
// Make sure we keep track of the original numerator in contracts upgraded from a version | ||
// without checkpoints. | ||
if (oldQuorumNumerator != 0 && _quorumNumeratorHistory._checkpoints.length == 0) { | ||
_quorumNumeratorHistory._checkpoints.push( | ||
Checkpoints.Checkpoint224({_key: 0, _value: SafeCast.toUint224(oldQuorumNumerator)}) | ||
); | ||
} | ||
|
||
// Set new quorum for future proposals | ||
_quorumNumeratorHistory.push(SafeCast.toUint32(clock()), SafeCast.toUint224(newQuorumNumerator)); | ||
|
||
emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters