-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test/bonding: Test GovernorCountingOverridable
- Loading branch information
Showing
5 changed files
with
625 additions
and
5 deletions.
There are no files selected for viewing
78 changes: 78 additions & 0 deletions
78
contracts/test/mocks/GovernorCountingOverridableTestable.sol
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,78 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.9; | ||
|
||
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/governance/GovernorUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesQuorumFractionUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorSettingsUpgradeable.sol"; | ||
|
||
import "../../treasury/GovernorCountingOverridable.sol"; | ||
|
||
/** | ||
* @dev This is a concrete contract to test the GovernorCountingOverridable extension. It implements the minimum | ||
* necessary to get a working Governor to test the extension. | ||
*/ | ||
contract GovernorCountingOverridableTestable is | ||
Initializable, | ||
GovernorUpgradeable, | ||
GovernorSettingsUpgradeable, | ||
GovernorVotesUpgradeable, | ||
GovernorCountingOverridable | ||
{ | ||
// use non-standard values for these to test if it's really used | ||
uint256 constant QUOTA = 420000; // 42% | ||
uint256 constant QUORUM = 370000; // 37% | ||
|
||
IVotes internal iVotes; // 🍎 | ||
|
||
function initialize(IVotes _votes) public initializer { | ||
iVotes = _votes; | ||
|
||
__Governor_init("GovernorCountingOverridableConcrete"); | ||
__GovernorSettings_init( | ||
0, /* no voting delay */ | ||
100, /* 100 blocks voting period */ | ||
0 /* no minimum proposal threshold */ | ||
); | ||
|
||
__GovernorVotes_init(iVotes); | ||
__GovernorCountingOverridable_init(); | ||
} | ||
|
||
function votes() public view override returns (IVotes) { | ||
return iVotes; | ||
} | ||
|
||
function quota() public pure override returns (uint256) { | ||
return QUOTA; | ||
} | ||
|
||
function quorum(uint256 timepoint) public view virtual override returns (uint256) { | ||
uint256 totalSupply = iVotes.getPastTotalSupply(timepoint); | ||
return MathUtils.percOf(totalSupply, QUORUM); | ||
} | ||
|
||
/** | ||
* @dev Expose internal _quorumReached function for testing. | ||
*/ | ||
function quorumReached(uint256 proposalId) public view returns (bool) { | ||
return super._quorumReached(proposalId); | ||
} | ||
|
||
/** | ||
* @dev Expose internal _voteSucceeded function for testing. | ||
*/ | ||
function voteSucceeded(uint256 proposalId) public view returns (bool) { | ||
return super._voteSucceeded(proposalId); | ||
} | ||
|
||
function proposalThreshold() | ||
public | ||
view | ||
override(GovernorUpgradeable, GovernorSettingsUpgradeable) | ||
returns (uint256) | ||
{ | ||
return super.proposalThreshold(); | ||
} | ||
} |
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,110 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.9; | ||
|
||
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20SnapshotUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; | ||
|
||
import { IVotes } from "../../treasury/GovernorCountingOverridable.sol"; | ||
import "../../bonding/libraries/SortedArrays.sol"; | ||
|
||
/** | ||
* @dev Minimum implementation of an IVotes interface to test the GovernorCountingOverridable extension. | ||
*/ | ||
contract VotesMock is | ||
Initializable, | ||
ERC20Upgradeable, | ||
ERC20BurnableUpgradeable, | ||
OwnableUpgradeable, | ||
ERC20VotesUpgradeable, | ||
IVotes | ||
{ | ||
mapping(address => uint256[]) private _delegateChangingTimes; | ||
mapping(address => mapping(uint256 => address)) private _delegatedAtTime; | ||
|
||
function initialize() public initializer { | ||
__ERC20_init("VotesMock", "VTCK"); | ||
__ERC20Burnable_init(); | ||
__Ownable_init(); | ||
__ERC20Votes_init(); | ||
} | ||
|
||
function delegatedAt(address _account, uint256 _timepoint) external view returns (address) { | ||
uint256[] storage rounds = _delegateChangingTimes[_account]; | ||
if (rounds.length == 0 || _timepoint < rounds[0]) { | ||
return address(0); | ||
} | ||
|
||
uint256 prevRound = SortedArrays.findLowerBound(rounds, _timepoint); | ||
return _delegatedAtTime[_account][prevRound]; | ||
} | ||
|
||
function _delegate(address _delegator, address _to) internal override { | ||
super._delegate(_delegator, _to); | ||
|
||
uint256 currTime = clock(); | ||
|
||
uint256[] storage rounds = _delegateChangingTimes[_delegator]; | ||
SortedArrays.pushSorted(rounds, currTime); | ||
_delegatedAtTime[_delegator][currTime] = _to; | ||
} | ||
|
||
/** | ||
* @dev Simulates the behavior of our actual voting power, where the delegator also has voting power which can | ||
* override their transcoder's vote. This is not the case in the OpenZeppelin implementation. | ||
*/ | ||
function getPastVotes(address account, uint256 blockNumber) | ||
public | ||
view | ||
override(IVotesUpgradeable, ERC20VotesUpgradeable) | ||
returns (uint256) | ||
{ | ||
// Blatant simplification that only works in our tests where we never change participants balance during | ||
// proposal voting period. We check and return delegators current state instead of tracking historical values. | ||
if (delegates(account) != account) { | ||
return balanceOf(account); | ||
} | ||
return super.getPastVotes(account, blockNumber); | ||
} | ||
|
||
/** | ||
* @dev Same as above. Still don't understand why the OZ implementation for these 2 is incompatible, with getPast* | ||
* reverting if you query it with the current round. | ||
*/ | ||
function getVotes(address account) | ||
public | ||
view | ||
override(IVotesUpgradeable, ERC20VotesUpgradeable) | ||
returns (uint256) | ||
{ | ||
if (delegates(account) != account) { | ||
return balanceOf(account); | ||
} | ||
return super.getVotes(account); | ||
} | ||
|
||
function mint(address to, uint256 amount) public onlyOwner { | ||
_mint(to, amount); | ||
} | ||
|
||
// The following functions are overrides required by Solidity. | ||
|
||
function _afterTokenTransfer( | ||
address from, | ||
address to, | ||
uint256 amount | ||
) internal override(ERC20Upgradeable, ERC20VotesUpgradeable) { | ||
super._afterTokenTransfer(from, to, amount); | ||
} | ||
|
||
function _mint(address to, uint256 amount) internal override(ERC20Upgradeable, ERC20VotesUpgradeable) { | ||
super._mint(to, amount); | ||
} | ||
|
||
function _burn(address account, uint256 amount) internal override(ERC20Upgradeable, ERC20VotesUpgradeable) { | ||
super._burn(account, amount); | ||
} | ||
} |
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
Oops, something went wrong.