Improve Governor (#2794)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
This commit is contained in:
committed by
GitHub
parent
f782943099
commit
4b152bd8ce
@ -136,26 +136,6 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
|
||||
return _proposals[proposalId].voteEnd.getDeadline();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {IGovernor-votingDelay}
|
||||
*/
|
||||
function votingDelay() public view virtual override returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev See {IGovernor-votingPeriod}
|
||||
*/
|
||||
function votingPeriod() public view virtual override returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev See {IGovernor-quorum}
|
||||
*/
|
||||
function quorum(uint256 blockNumber) public view virtual override returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev See {IGovernor-getVotes}
|
||||
*/
|
||||
function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Amount of votes already casted passes the threshold limit.
|
||||
*/
|
||||
|
||||
@ -9,7 +9,7 @@ import "../utils/introspection/ERC165.sol";
|
||||
*
|
||||
* _Available since v4.3._
|
||||
*/
|
||||
interface IGovernor is IERC165 {
|
||||
abstract contract IGovernor is IERC165 {
|
||||
enum ProposalState {
|
||||
Pending,
|
||||
Active,
|
||||
@ -57,13 +57,13 @@ interface IGovernor is IERC165 {
|
||||
* @notice module:core
|
||||
* @dev Name of the governor instance (used in building the ERC712 domain separator).
|
||||
*/
|
||||
function name() external view returns (string memory);
|
||||
function name() public view virtual returns (string memory);
|
||||
|
||||
/**
|
||||
* @notice module:core
|
||||
* @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1"
|
||||
*/
|
||||
function version() external view returns (string memory);
|
||||
function version() public view virtual returns (string memory);
|
||||
|
||||
/**
|
||||
* @notice module:voting
|
||||
@ -82,7 +82,7 @@ interface IGovernor is IERC165 {
|
||||
* JavaScript class.
|
||||
*/
|
||||
// solhint-disable-next-line func-name-mixedcase
|
||||
function COUNTING_MODE() external pure returns (string memory);
|
||||
function COUNTING_MODE() public pure virtual returns (string memory);
|
||||
|
||||
/**
|
||||
* @notice module:core
|
||||
@ -93,32 +93,32 @@ interface IGovernor is IERC165 {
|
||||
uint256[] calldata values,
|
||||
bytes[] calldata calldatas,
|
||||
bytes32 descriptionHash
|
||||
) external pure returns (uint256);
|
||||
) public pure virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @notice module:core
|
||||
* @dev Current state of a proposal, following Compound's convention
|
||||
*/
|
||||
function state(uint256 proposalId) external view returns (ProposalState);
|
||||
function state(uint256 proposalId) public view virtual returns (ProposalState);
|
||||
|
||||
/**
|
||||
* @notice module:core
|
||||
* @dev block number used to retrieve user's votes and quorum.
|
||||
*/
|
||||
function proposalSnapshot(uint256 proposalId) external view returns (uint256);
|
||||
function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @notice module:core
|
||||
* @dev timestamp at which votes close.
|
||||
*/
|
||||
function proposalDeadline(uint256 proposalId) external view returns (uint256);
|
||||
function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @notice module:user-config
|
||||
* @dev delay, in number of block, between the proposal is created and the vote starts. This can be increassed to
|
||||
* leave time for users to buy voting power, of delegate it, before the voting of a proposal starts.
|
||||
*/
|
||||
function votingDelay() external view returns (uint256);
|
||||
function votingDelay() public view virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @notice module:user-config
|
||||
@ -127,7 +127,7 @@ interface IGovernor is IERC165 {
|
||||
* Note: the {votingDelay} can delay the start of the vote. This must be considered when setting the voting
|
||||
* duration compared to the voting delay.
|
||||
*/
|
||||
function votingPeriod() external view returns (uint256);
|
||||
function votingPeriod() public view virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @notice module:user-config
|
||||
@ -136,7 +136,7 @@ interface IGovernor is IERC165 {
|
||||
* Note: The `blockNumber` parameter corresponds to the snaphot used for counting vote. This allows to scale the
|
||||
* quroum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).
|
||||
*/
|
||||
function quorum(uint256 blockNumber) external view returns (uint256);
|
||||
function quorum(uint256 blockNumber) public view virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @notice module:reputation
|
||||
@ -145,13 +145,13 @@ interface IGovernor is IERC165 {
|
||||
* Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
|
||||
* multiple), {ERC20Votes} tokens.
|
||||
*/
|
||||
function getVotes(address account, uint256 blockNumber) external view returns (uint256);
|
||||
function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @notice module:voting
|
||||
* @dev Returns weither `account` has casted a vote on `proposalId`.
|
||||
*/
|
||||
function hasVoted(uint256 proposalId, address account) external view returns (bool);
|
||||
function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);
|
||||
|
||||
/**
|
||||
* @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends
|
||||
@ -164,7 +164,7 @@ interface IGovernor is IERC165 {
|
||||
uint256[] memory values,
|
||||
bytes[] memory calldatas,
|
||||
string memory description
|
||||
) external returns (uint256 proposalId);
|
||||
) public virtual returns (uint256 proposalId);
|
||||
|
||||
/**
|
||||
* @dev Execute a successful proposal. This requiers the quorum to be reached, the vote to be successful, and the
|
||||
@ -179,14 +179,14 @@ interface IGovernor is IERC165 {
|
||||
uint256[] memory values,
|
||||
bytes[] memory calldatas,
|
||||
bytes32 descriptionHash
|
||||
) external payable returns (uint256 proposalId);
|
||||
) public payable virtual returns (uint256 proposalId);
|
||||
|
||||
/**
|
||||
* @dev Cast a vote
|
||||
*
|
||||
* Emits a {VoteCast} event.
|
||||
*/
|
||||
function castVote(uint256 proposalId, uint8 support) external returns (uint256 balance);
|
||||
function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);
|
||||
|
||||
/**
|
||||
* @dev Cast a with a reason
|
||||
@ -197,7 +197,7 @@ interface IGovernor is IERC165 {
|
||||
uint256 proposalId,
|
||||
uint8 support,
|
||||
string calldata reason
|
||||
) external returns (uint256 balance);
|
||||
) public virtual returns (uint256 balance);
|
||||
|
||||
/**
|
||||
* @dev Cast a vote using the user cryptographic signature.
|
||||
@ -210,5 +210,5 @@ interface IGovernor is IERC165 {
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) external returns (uint256 balance);
|
||||
) public virtual returns (uint256 balance);
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ pragma solidity ^0.8.0;
|
||||
import "../../utils/Counters.sol";
|
||||
import "../../utils/math/SafeCast.sol";
|
||||
import "../extensions/IGovernorTimelock.sol";
|
||||
import "../extensions/GovernorProposalThreshold.sol";
|
||||
import "../Governor.sol";
|
||||
import "./IGovernorCompatibilityBravo.sol";
|
||||
|
||||
@ -16,7 +17,12 @@ import "./IGovernorCompatibilityBravo.sol";
|
||||
*
|
||||
* _Available since v4.3._
|
||||
*/
|
||||
abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorCompatibilityBravo, Governor {
|
||||
abstract contract GovernorCompatibilityBravo is
|
||||
IGovernorTimelock,
|
||||
IGovernorCompatibilityBravo,
|
||||
Governor,
|
||||
GovernorProposalThreshold
|
||||
{
|
||||
using Counters for Counters.Counter;
|
||||
using Timers for Timers.BlockNumber;
|
||||
|
||||
@ -41,20 +47,6 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
|
||||
|
||||
mapping(uint256 => ProposalDetails) private _proposalDetails;
|
||||
|
||||
// public for hooking
|
||||
function proposalThreshold() public view virtual override returns (uint256);
|
||||
|
||||
// public for hooking
|
||||
function proposalEta(uint256 proposalId) public view virtual override returns (uint256);
|
||||
|
||||
// public for hooking
|
||||
function queue(
|
||||
address[] memory targets,
|
||||
uint256[] memory values,
|
||||
bytes[] memory calldatas,
|
||||
bytes32 descriptionHash
|
||||
) public virtual override returns (uint256);
|
||||
|
||||
// solhint-disable-next-line func-name-mixedcase
|
||||
function COUNTING_MODE() public pure virtual override returns (string memory) {
|
||||
return "support=bravo&quorum=bravo";
|
||||
@ -69,8 +61,9 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
|
||||
uint256[] memory values,
|
||||
bytes[] memory calldatas,
|
||||
string memory description
|
||||
) public virtual override(IGovernor, Governor) returns (uint256) {
|
||||
return propose(targets, values, new string[](calldatas.length), calldatas, description);
|
||||
) public virtual override(IGovernor, Governor, GovernorProposalThreshold) returns (uint256) {
|
||||
_storeProposal(_msgSender(), targets, values, new string[](calldatas.length), calldatas, description);
|
||||
return super.propose(targets, values, calldatas, description);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,14 +76,8 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
|
||||
bytes[] memory calldatas,
|
||||
string memory description
|
||||
) public virtual override returns (uint256) {
|
||||
require(
|
||||
getVotes(msg.sender, block.number - 1) >= proposalThreshold(),
|
||||
"GovernorCompatibilityBravo: proposer votes below proposal threshold"
|
||||
);
|
||||
|
||||
uint256 proposalId = super.propose(targets, values, _encodeCalldata(signatures, calldatas), description);
|
||||
_storeProposal(proposalId, _msgSender(), targets, values, signatures, calldatas, description);
|
||||
return proposalId;
|
||||
_storeProposal(_msgSender(), targets, values, signatures, calldatas, description);
|
||||
return propose(targets, values, _encodeCalldata(signatures, calldatas), description);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,6 +106,22 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
|
||||
);
|
||||
}
|
||||
|
||||
function cancel(uint256 proposalId) public virtual override {
|
||||
ProposalDetails storage details = _proposalDetails[proposalId];
|
||||
|
||||
require(
|
||||
_msgSender() == details.proposer || getVotes(details.proposer, block.number - 1) < proposalThreshold(),
|
||||
"GovernorBravo: proposer above threshold"
|
||||
);
|
||||
|
||||
_cancel(
|
||||
details.targets,
|
||||
details.values,
|
||||
_encodeCalldata(details.signatures, details.calldatas),
|
||||
details.descriptionHash
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Encodes calldatas with optional function signature.
|
||||
*/
|
||||
@ -132,7 +135,7 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
|
||||
for (uint256 i = 0; i < signatures.length; ++i) {
|
||||
fullcalldatas[i] = bytes(signatures[i]).length == 0
|
||||
? calldatas[i]
|
||||
: abi.encodePacked(bytes4(keccak256(bytes(signatures[i]))), calldatas[i]);
|
||||
: abi.encodeWithSignature(signatures[i], calldatas[i]);
|
||||
}
|
||||
|
||||
return fullcalldatas;
|
||||
@ -142,7 +145,6 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
|
||||
* @dev Store proposal metadata for later lookup
|
||||
*/
|
||||
function _storeProposal(
|
||||
uint256 proposalId,
|
||||
address proposer,
|
||||
address[] memory targets,
|
||||
uint256[] memory values,
|
||||
@ -150,17 +152,31 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
|
||||
bytes[] memory calldatas,
|
||||
string memory description
|
||||
) private {
|
||||
ProposalDetails storage details = _proposalDetails[proposalId];
|
||||
bytes32 descriptionHash = keccak256(bytes(description));
|
||||
uint256 proposalId = hashProposal(targets, values, _encodeCalldata(signatures, calldatas), descriptionHash);
|
||||
|
||||
details.proposer = proposer;
|
||||
details.targets = targets;
|
||||
details.values = values;
|
||||
details.signatures = signatures;
|
||||
details.calldatas = calldatas;
|
||||
details.descriptionHash = keccak256(bytes(description));
|
||||
ProposalDetails storage details = _proposalDetails[proposalId];
|
||||
if (details.descriptionHash == bytes32(0)) {
|
||||
details.proposer = proposer;
|
||||
details.targets = targets;
|
||||
details.values = values;
|
||||
details.signatures = signatures;
|
||||
details.calldatas = calldatas;
|
||||
details.descriptionHash = descriptionHash;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================================================== Views =====================================================
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
|
||||
*/
|
||||
function proposalThreshold()
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override(IGovernorCompatibilityBravo, GovernorProposalThreshold)
|
||||
returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev See {IGovernorCompatibilityBravo-proposals}.
|
||||
*/
|
||||
|
||||
@ -9,7 +9,7 @@ import "../IGovernor.sol";
|
||||
*
|
||||
* _Available since v4.3._
|
||||
*/
|
||||
interface IGovernorCompatibilityBravo is IGovernor {
|
||||
abstract contract IGovernorCompatibilityBravo is IGovernor {
|
||||
/**
|
||||
* @dev Proposal structure from Compound Governor Bravo. Not actually used by the compatibility layer, as
|
||||
* {{proposal}} returns a very different structure.
|
||||
@ -44,14 +44,15 @@ interface IGovernorCompatibilityBravo is IGovernor {
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface.
|
||||
*/
|
||||
function quorumVotes() external view returns (uint256);
|
||||
function quorumVotes() public view virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface: _"The official record of all proposals ever proposed"_.
|
||||
*/
|
||||
function proposals(uint256)
|
||||
external
|
||||
public
|
||||
view
|
||||
virtual
|
||||
returns (
|
||||
uint256 id,
|
||||
address proposer,
|
||||
@ -74,24 +75,30 @@ interface IGovernorCompatibilityBravo is IGovernor {
|
||||
string[] memory signatures,
|
||||
bytes[] memory calldatas,
|
||||
string memory description
|
||||
) external returns (uint256);
|
||||
) public virtual returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface: _"Queues a proposal of state succeeded"_.
|
||||
*/
|
||||
function queue(uint256 proposalId) external;
|
||||
function queue(uint256 proposalId) public virtual;
|
||||
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface: _"Executes a queued proposal if eta has passed"_.
|
||||
*/
|
||||
function execute(uint256 proposalId) external payable;
|
||||
function execute(uint256 proposalId) public payable virtual;
|
||||
|
||||
/**
|
||||
* @dev Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold.
|
||||
*/
|
||||
function cancel(uint256 proposalId) public virtual;
|
||||
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface: _"Gets actions of a proposal"_.
|
||||
*/
|
||||
function getActions(uint256 proposalId)
|
||||
external
|
||||
public
|
||||
view
|
||||
virtual
|
||||
returns (
|
||||
address[] memory targets,
|
||||
uint256[] memory values,
|
||||
@ -102,10 +109,10 @@ interface IGovernorCompatibilityBravo is IGovernor {
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface: _"Gets the receipt for a voter on a given proposal"_.
|
||||
*/
|
||||
function getReceipt(uint256 proposalId, address voter) external view returns (Receipt memory);
|
||||
function getReceipt(uint256 proposalId, address voter) public view virtual returns (Receipt memory);
|
||||
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
|
||||
*/
|
||||
function proposalThreshold() external view returns (uint256);
|
||||
function proposalThreshold() public view virtual returns (uint256);
|
||||
}
|
||||
|
||||
@ -66,9 +66,7 @@ abstract contract GovernorCountingSimple is Governor {
|
||||
function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
|
||||
ProposalVote storage proposalvote = _proposalVotes[proposalId];
|
||||
|
||||
return
|
||||
quorum(proposalSnapshot(proposalId)) <=
|
||||
proposalvote.againstVotes + proposalvote.forVotes + proposalvote.abstainVotes;
|
||||
return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "../Governor.sol";
|
||||
|
||||
/**
|
||||
* @dev Extension of {Governor} for proposal restriction to token holders with a minimum balance.
|
||||
*
|
||||
* _Available since v4.3._
|
||||
*/
|
||||
abstract contract GovernorProposalThreshold is Governor {
|
||||
/**
|
||||
* @dev See {IGovernor-propose}.
|
||||
*/
|
||||
function propose(
|
||||
address[] memory targets,
|
||||
uint256[] memory values,
|
||||
bytes[] memory calldatas,
|
||||
string memory description
|
||||
) public virtual override returns (uint256) {
|
||||
require(
|
||||
getVotes(msg.sender, block.number - 1) >= proposalThreshold(),
|
||||
"GovernorCompatibilityBravo: proposer votes below proposal threshold"
|
||||
);
|
||||
|
||||
return super.propose(targets, values, calldatas, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
|
||||
*/
|
||||
function proposalThreshold() public view virtual returns (uint256);
|
||||
}
|
||||
@ -9,17 +9,17 @@ import "../IGovernor.sol";
|
||||
*
|
||||
* _Available since v4.3._
|
||||
*/
|
||||
interface IGovernorTimelock is IGovernor {
|
||||
abstract contract IGovernorTimelock is IGovernor {
|
||||
event ProposalQueued(uint256 proposalId, uint256 eta);
|
||||
|
||||
function timelock() external view returns (address);
|
||||
function timelock() public view virtual returns (address);
|
||||
|
||||
function proposalEta(uint256 proposalId) external view returns (uint256);
|
||||
function proposalEta(uint256 proposalId) public view virtual returns (uint256);
|
||||
|
||||
function queue(
|
||||
address[] calldata targets,
|
||||
uint256[] calldata values,
|
||||
bytes[] calldata calldatas,
|
||||
address[] memory targets,
|
||||
uint256[] memory values,
|
||||
bytes[] memory calldatas,
|
||||
bytes32 descriptionHash
|
||||
) external returns (uint256 proposalId);
|
||||
) public virtual returns (uint256 proposalId);
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ contract GovernorCompMock is Governor, GovernorVotesComp, GovernorCountingSimple
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override(Governor, GovernorVotesComp)
|
||||
override(IGovernor, GovernorVotesComp)
|
||||
returns (uint256)
|
||||
{
|
||||
return super.getVotes(account, blockNumber);
|
||||
|
||||
@ -34,11 +34,11 @@ contract GovernorCompatibilityBravoMock is GovernorCompatibilityBravo, GovernorT
|
||||
return super.supportsInterface(interfaceId);
|
||||
}
|
||||
|
||||
function votingDelay() public view override(IGovernor, Governor) returns (uint256) {
|
||||
function votingDelay() public view override returns (uint256) {
|
||||
return _votingDelay;
|
||||
}
|
||||
|
||||
function votingPeriod() public view override(IGovernor, Governor) returns (uint256) {
|
||||
function votingPeriod() public view override returns (uint256) {
|
||||
return _votingPeriod;
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ contract GovernorCompatibilityBravoMock is GovernorCompatibilityBravo, GovernorT
|
||||
return _proposalThreshold;
|
||||
}
|
||||
|
||||
function quorum(uint256) public pure override(IGovernor, Governor) returns (uint256) {
|
||||
function quorum(uint256) public pure override returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ contract GovernorCompatibilityBravoMock is GovernorCompatibilityBravo, GovernorT
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override(GovernorCompatibilityBravo, GovernorTimelockCompound)
|
||||
override(IGovernorTimelock, GovernorTimelockCompound)
|
||||
returns (uint256)
|
||||
{
|
||||
return super.proposalEta(proposalId);
|
||||
@ -84,7 +84,7 @@ contract GovernorCompatibilityBravoMock is GovernorCompatibilityBravo, GovernorT
|
||||
uint256[] memory values,
|
||||
bytes[] memory calldatas,
|
||||
bytes32 salt
|
||||
) public virtual override(GovernorCompatibilityBravo, GovernorTimelockCompound) returns (uint256) {
|
||||
) public virtual override(IGovernorTimelock, GovernorTimelockCompound) returns (uint256) {
|
||||
return super.queue(targets, values, calldatas, salt);
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ contract GovernorMock is Governor, GovernorVotesQuorumFraction, GovernorCounting
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override(Governor, GovernorVotes)
|
||||
override(IGovernor, GovernorVotes)
|
||||
returns (uint256)
|
||||
{
|
||||
return super.getVotes(account, blockNumber);
|
||||
|
||||
@ -37,18 +37,18 @@ contract GovernorTimelockCompoundMock is GovernorTimelockCompound, GovernorVotes
|
||||
return super.supportsInterface(interfaceId);
|
||||
}
|
||||
|
||||
function votingDelay() public view override(IGovernor, Governor) returns (uint256) {
|
||||
function votingDelay() public view override returns (uint256) {
|
||||
return _votingDelay;
|
||||
}
|
||||
|
||||
function votingPeriod() public view override(IGovernor, Governor) returns (uint256) {
|
||||
function votingPeriod() public view override returns (uint256) {
|
||||
return _votingPeriod;
|
||||
}
|
||||
|
||||
function quorum(uint256 blockNumber)
|
||||
public
|
||||
view
|
||||
override(IGovernor, Governor, GovernorVotesQuorumFraction)
|
||||
override(IGovernor, GovernorVotesQuorumFraction)
|
||||
returns (uint256)
|
||||
{
|
||||
return super.quorum(blockNumber);
|
||||
@ -99,7 +99,7 @@ contract GovernorTimelockCompoundMock is GovernorTimelockCompound, GovernorVotes
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override(IGovernor, Governor, GovernorVotes)
|
||||
override(IGovernor, GovernorVotes)
|
||||
returns (uint256)
|
||||
{
|
||||
return super.getVotes(account, blockNumber);
|
||||
|
||||
@ -37,18 +37,18 @@ contract GovernorTimelockControlMock is GovernorTimelockControl, GovernorVotesQu
|
||||
return super.supportsInterface(interfaceId);
|
||||
}
|
||||
|
||||
function votingDelay() public view override(IGovernor, Governor) returns (uint256) {
|
||||
function votingDelay() public view override returns (uint256) {
|
||||
return _votingDelay;
|
||||
}
|
||||
|
||||
function votingPeriod() public view override(IGovernor, Governor) returns (uint256) {
|
||||
function votingPeriod() public view override returns (uint256) {
|
||||
return _votingPeriod;
|
||||
}
|
||||
|
||||
function quorum(uint256 blockNumber)
|
||||
public
|
||||
view
|
||||
override(IGovernor, Governor, GovernorVotesQuorumFraction)
|
||||
override(IGovernor, GovernorVotesQuorumFraction)
|
||||
returns (uint256)
|
||||
{
|
||||
return super.quorum(blockNumber);
|
||||
@ -99,7 +99,7 @@ contract GovernorTimelockControlMock is GovernorTimelockControl, GovernorVotesQu
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override(IGovernor, Governor, GovernorVotes)
|
||||
override(IGovernor, GovernorVotes)
|
||||
returns (uint256)
|
||||
{
|
||||
return super.getVotes(account, blockNumber);
|
||||
|
||||
@ -29,7 +29,7 @@ contract('Governor', function (accounts) {
|
||||
beforeEach(async function () {
|
||||
this.owner = owner;
|
||||
this.token = await Token.new(tokenName, tokenSymbol);
|
||||
this.mock = await Governor.new(name, this.token.address, 4, 16, 0);
|
||||
this.mock = await Governor.new(name, this.token.address, 4, 16, 10);
|
||||
this.receiver = await CallReceiver.new();
|
||||
await this.token.mint(owner, tokenSupply);
|
||||
await this.token.delegate(voter1, { from: voter1 });
|
||||
@ -72,7 +72,7 @@ contract('Governor', function (accounts) {
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For, reason: 'This is nice' },
|
||||
{ voter: voter2, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
{ voter: voter2, weight: web3.utils.toWei('7'), support: Enums.VoteType.For },
|
||||
{ voter: voter3, weight: web3.utils.toWei('5'), support: Enums.VoteType.Against },
|
||||
{ voter: voter4, weight: web3.utils.toWei('2'), support: Enums.VoteType.Abstain },
|
||||
],
|
||||
@ -194,7 +194,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: this.voter, signature, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: this.voter, signature, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
};
|
||||
});
|
||||
@ -252,8 +252,8 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter2, weight: web3.utils.toWei('1'), support: Enums.VoteType.Abstain },
|
||||
{ voter: voter1, weight: web3.utils.toWei('5'), support: Enums.VoteType.For },
|
||||
{ voter: voter2, weight: web3.utils.toWei('5'), support: Enums.VoteType.Abstain },
|
||||
],
|
||||
};
|
||||
});
|
||||
@ -285,7 +285,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
steps: {
|
||||
execute: { error: 'Governor: call reverted without message' },
|
||||
@ -306,7 +306,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
steps: {
|
||||
execute: { error: 'CallReceiverMock: reverting' },
|
||||
@ -329,13 +329,13 @@ contract('Governor', function (accounts) {
|
||||
voters: [
|
||||
{
|
||||
voter: voter1,
|
||||
weight: web3.utils.toWei('1'),
|
||||
weight: web3.utils.toWei('5'),
|
||||
support: Enums.VoteType.For,
|
||||
error: 'Governor: unknown proposal id',
|
||||
},
|
||||
{
|
||||
voter: voter2,
|
||||
weight: web3.utils.toWei('1'),
|
||||
weight: web3.utils.toWei('5'),
|
||||
support: Enums.VoteType.Abstain,
|
||||
error: 'Governor: unknown proposal id',
|
||||
},
|
||||
@ -382,8 +382,8 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter2, weight: web3.utils.toWei('1'), support: Enums.VoteType.Abstain },
|
||||
{ voter: voter1, weight: web3.utils.toWei('5'), support: Enums.VoteType.For },
|
||||
{ voter: voter2, weight: web3.utils.toWei('5'), support: Enums.VoteType.Abstain },
|
||||
],
|
||||
};
|
||||
});
|
||||
@ -406,7 +406,7 @@ contract('Governor', function (accounts) {
|
||||
voters: [
|
||||
{
|
||||
voter: voter1,
|
||||
weight: web3.utils.toWei('1'),
|
||||
weight: web3.utils.toWei('10'),
|
||||
support: new BN('255'),
|
||||
error: 'GovernorVotingSimple: invalid value for enum VoteType',
|
||||
},
|
||||
@ -433,12 +433,12 @@ contract('Governor', function (accounts) {
|
||||
voters: [
|
||||
{
|
||||
voter: voter1,
|
||||
weight: web3.utils.toWei('1'),
|
||||
weight: web3.utils.toWei('5'),
|
||||
support: Enums.VoteType.For,
|
||||
},
|
||||
{
|
||||
voter: voter1,
|
||||
weight: web3.utils.toWei('1'),
|
||||
weight: web3.utils.toWei('5'),
|
||||
support: Enums.VoteType.For,
|
||||
error: 'GovernorVotingSimple: vote already casted',
|
||||
},
|
||||
@ -459,7 +459,9 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('0'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('5'), support: Enums.VoteType.For },
|
||||
{ voter: voter2, weight: web3.utils.toWei('4'), support: Enums.VoteType.Abstain },
|
||||
{ voter: voter3, weight: web3.utils.toWei('10'), support: Enums.VoteType.Against },
|
||||
],
|
||||
steps: {
|
||||
execute: { error: 'Governor: proposal not successful' },
|
||||
@ -480,7 +482,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.Against },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.Against },
|
||||
],
|
||||
steps: {
|
||||
execute: { error: 'Governor: proposal not successful' },
|
||||
@ -501,7 +503,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
steps: {
|
||||
wait: { enable: false },
|
||||
@ -593,7 +595,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
steps: {
|
||||
execute: { enable: false },
|
||||
@ -617,7 +619,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
};
|
||||
});
|
||||
@ -692,7 +694,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
steps: {
|
||||
wait: { enable: false },
|
||||
@ -723,7 +725,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
steps: {
|
||||
execute: { enable: false },
|
||||
@ -753,7 +755,7 @@ contract('Governor', function (accounts) {
|
||||
],
|
||||
tokenHolder: owner,
|
||||
voters: [
|
||||
{ voter: voter1, weight: web3.utils.toWei('1'), support: Enums.VoteType.For },
|
||||
{ voter: voter1, weight: web3.utils.toWei('10'), support: Enums.VoteType.For },
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
@ -215,6 +215,51 @@ contract('GovernorCompatibilityBravo', function (accounts) {
|
||||
runGovernorWorkflow();
|
||||
});
|
||||
|
||||
describe('cancel', function () {
|
||||
beforeEach(async function () {
|
||||
this.settings = {
|
||||
proposal: [
|
||||
[ this.receiver.address ], // targets
|
||||
[ web3.utils.toWei('0') ], // values
|
||||
[ this.receiver.contract.methods.mockFunction().encodeABI() ], // calldatas
|
||||
'<proposal description>', // description
|
||||
],
|
||||
proposer,
|
||||
tokenHolder: owner,
|
||||
steps: {
|
||||
wait: { enable: false },
|
||||
queue: { enable: false },
|
||||
execute: { enable: false },
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('by proposer', function () {
|
||||
afterEach(async function () {
|
||||
await this.mock.cancel(this.id, { from: proposer });
|
||||
});
|
||||
runGovernorWorkflow();
|
||||
});
|
||||
|
||||
describe('if proposer below threshold', function () {
|
||||
afterEach(async function () {
|
||||
await this.token.transfer(voter1, web3.utils.toWei('1'), { from: proposer });
|
||||
await this.mock.cancel(this.id);
|
||||
});
|
||||
runGovernorWorkflow();
|
||||
});
|
||||
|
||||
describe('not if proposer above threshold', function () {
|
||||
afterEach(async function () {
|
||||
await expectRevert(
|
||||
this.mock.cancel(this.id),
|
||||
'GovernorBravo: proposer above threshold',
|
||||
);
|
||||
});
|
||||
runGovernorWorkflow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with compatibility interface', function () {
|
||||
beforeEach(async function () {
|
||||
this.settings = {
|
||||
|
||||
@ -100,7 +100,7 @@ function shouldSupportInterfaces (interfaces = []) {
|
||||
expect(await this.contractUnderTest.supportsInterface.estimateGas(interfaceId)).to.be.lte(30000);
|
||||
});
|
||||
|
||||
it('claims support', async function () {
|
||||
it('claims support [skip-on-coverage]', async function () {
|
||||
expect(await this.contractUnderTest.supportsInterface(interfaceId)).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user