Improve documentation of various governance aspects (#3161)

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
(cherry picked from commit 85566faeb2)
This commit is contained in:
Francisco Giordano
2022-02-02 13:36:45 -03:00
parent ac8c53612a
commit a8a08bef58
5 changed files with 53 additions and 10 deletions

View File

@ -41,8 +41,9 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
mapping(uint256 => ProposalCore) private _proposals;
/**
* @dev Restrict access to governor executing address. Some module might override the _executor function to make
* sure this modifier is consistant with the execution model.
* @dev Restrict access of functions to the governance executor, which may be the Governor itself or a timelock
* contract, as specified by {_executor}. This generally means that function with this modifier must be voted on and
* executed through the governance protocol.
*/
modifier onlyGovernance() {
require(_msgSender() == _executor(), "Governor: onlyGovernance");

View File

@ -224,14 +224,16 @@ abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
/**
* @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
* must be proposed, scheduled and executed using the {Governor} workflow.
* must be proposed, scheduled, and executed through governance proposals.
*
* For security reason, the timelock must be handed over to another admin before setting up a new one. The two
* For security reasons, the timelock must be handed over to another admin before setting up a new one. The two
* operations (hand over the timelock) and do the update can be batched in a single proposal.
*
* Note that if the timelock admin has been handed over in a previous operation, we refuse updates made through the
* timelock if admin of the timelock has already been accepted and the operation is executed outside the scope of
* governance.
* CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
*/
function updateTimelock(ICompoundTimelock newTimelock) external virtual onlyGovernance {
_updateTimelock(newTimelock);

View File

@ -16,9 +16,10 @@ import "../TimelockController.sol";
* the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
* inaccessible.
*
* WARNING: Setting up the TimelockController to have additional proposers besides the governor introduces the risk that
* approved governance proposals could be blocked by the other proposers, effectively executing a Denial of Service attack,
* and therefore blocking access to governance-controlled assets.
* WARNING: Setting up the TimelockController to have additional proposers besides the governor is very risky, as it
* grants them powers that they must be trusted or known not to use: 1) {onlyGovernance} functions like {relay} are
* available to them through the timelock, and 2) approved governance proposals can be blocked by them, effectively
* executing a Denial of Service attack. This risk will be mitigated in a future release.
*
* _Available since v4.3._
*/
@ -147,7 +148,9 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
/**
* @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
* must be proposed, scheduled and executed using the {Governor} workflow.
* must be proposed, scheduled, and executed through governance proposals.
*
* CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
*/
function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance {
_updateTimelock(newTimelock);

View File

@ -16,26 +16,61 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
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
* specified 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 _quorumNumerator;
}
/**
* @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 block number, in terms of number of votes: `supply * numerator / denominator`.
*/
function quorum(uint256 blockNumber) public view virtual override returns (uint256) {
return (token.getPastTotalSupply(blockNumber) * quorumNumerator()) / 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(),