Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Governance Testing and Variable Vote Length #30

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
725 changes: 725 additions & 0 deletions src/Governor.sol

Large diffs are not rendered by default.

23 changes: 0 additions & 23 deletions src/IlliniBlockchainGovernance.t.sol

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {GovernorVotes} from "./extensions/GovernorVotes.sol";
import {GovernorVotesQuorumFraction} from "./extensions/GovernorVotesQuorumFraction.sol";
import {IVotes} from "./utils/IVotes.sol";

import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import "./Governor.sol";
import "./extensions/GovernorSettings.sol";
import "./extensions/GovernorCountingSimple.sol";
import "./extensions/GovernorVotes.sol";
import "./extensions/GovernorVotesQuorumFraction.sol";
import "./utils/IVotes.sol";

contract IlliniBlockchainGovernor is
Governor,
Expand All @@ -27,11 +26,6 @@ contract IlliniBlockchainGovernor is
GovernorVotesQuorumFraction(67)
{}

/* NOTE:
- include variable vote time in proposal
- implement voting with our token
*/

// The following functions are overrides required by Solidity.

function votingDelay()
Expand Down
4 changes: 2 additions & 2 deletions src/IlliniBlockchainSP22Token.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ contract IlliniBlockchainSP22Token is ERC1155, Ownable, ERC1155Votes {
uint16 termId;
}

string[] internal terms;
string[2] internal terms;
mapping(uint256 => TokenMetadata) public tokenMetadata;
string public name = "IlliniBlockchain";

// A nonce to ensure we have a unique id each time we mint.
uint256 public nonce = 0;

constructor() {
terms = ["Fall", "Spring"];
terms = ["Spring", "Fall"];
}

function contractURI() public view returns (string memory) {
Expand Down
107 changes: 107 additions & 0 deletions src/extensions/GovernorCountingSimple.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorCountingSimple.sol)

pragma solidity ^0.8.0;

import "../Governor.sol";

/**
* @dev Extension of {Governor} for simple, 3 options, vote counting.
*
* _Available since v4.3._
*/
abstract contract GovernorCountingSimple is Governor {
/**
* @dev Supported vote types. Matches Governor Bravo ordering.
*/
enum VoteType {
Against,
For,
Abstain
}

struct ProposalVote {
uint256 againstVotes;
uint256 forVotes;
uint256 abstainVotes;
mapping(address => bool) hasVoted;
}

mapping(uint256 => ProposalVote) private _proposalVotes;

/**
* @dev See {IGovernor-COUNTING_MODE}.
*/
// solhint-disable-next-line func-name-mixedcase
function COUNTING_MODE() public pure virtual override returns (string memory) {
return "support=bravo&quorum=for,abstain";
}

/**
* @dev See {IGovernor-hasVoted}.
*/
function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
return _proposalVotes[proposalId].hasVoted[account];
}

/**
* @dev Accessor to the internal vote counts.
*/
function proposalVotes(uint256 proposalId)
public
view
virtual
returns (
uint256 againstVotes,
uint256 forVotes,
uint256 abstainVotes
)
{
ProposalVote storage proposalvote = _proposalVotes[proposalId];
return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);
}

/**
* @dev See {Governor-_quorumReached}.
*/
function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
ProposalVote storage proposalvote = _proposalVotes[proposalId];

return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;
}

/**
* @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
*/
function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
ProposalVote storage proposalvote = _proposalVotes[proposalId];

return proposalvote.forVotes > proposalvote.againstVotes;
}

/**
* @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
*/
function _countVote(
uint256 proposalId,
address account,
uint8 support,
uint256 weight,
bytes memory // params
) internal virtual override {
ProposalVote storage proposalvote = _proposalVotes[proposalId];

require(!proposalvote.hasVoted[account], "GovernorVotingSimple: vote already cast");
proposalvote.hasVoted[account] = true;

if (support == uint8(VoteType.Against)) {
proposalvote.againstVotes += weight;
} else if (support == uint8(VoteType.For)) {
proposalvote.forVotes += weight;
} else if (support == uint8(VoteType.Abstain)) {
proposalvote.abstainVotes += weight;
} else {
revert("GovernorVotingSimple: invalid value for enum VoteType");
}
}
}
114 changes: 114 additions & 0 deletions src/extensions/GovernorSettings.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorSettings.sol)

pragma solidity ^0.8.0;

import "../Governor.sol";

/**
* @dev Extension of {Governor} for settings updatable through governance.
*
* _Available since v4.4._
*/
abstract contract GovernorSettings is Governor {
uint256 private _votingDelay;
uint256 private _votingPeriod;
uint256 private _proposalThreshold;

event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);

/**
* @dev Initialize the governance parameters.
*/
constructor(
uint256 initialVotingDelay,
uint256 initialVotingPeriod,
uint256 initialProposalThreshold
) {
_setVotingDelay(initialVotingDelay);
_setVotingPeriod(initialVotingPeriod);
_setProposalThreshold(initialProposalThreshold);
}

/**
* @dev See {IGovernor-votingDelay}.
*/
function votingDelay() public view virtual override returns (uint256) {
return _votingDelay;
}

/**
* @dev See {IGovernor-votingPeriod}.
*/
function votingPeriod() public view virtual override returns (uint256) {
return _votingPeriod;
}

/**
* @dev See {Governor-proposalThreshold}.
*/
function proposalThreshold() public view virtual override returns (uint256) {
return _proposalThreshold;
}

/**
* @dev Update the voting delay. This operation can only be performed through a governance proposal.
*
* Emits a {VotingDelaySet} event.
*/
function setVotingDelay(uint256 newVotingDelay) public virtual onlyGovernance {
_setVotingDelay(newVotingDelay);
}

/**
* @dev Update the voting period. This operation can only be performed through a governance proposal.
*
* Emits a {VotingPeriodSet} event.
*/
function setVotingPeriod(uint256 newVotingPeriod) public virtual onlyGovernance {
_setVotingPeriod(newVotingPeriod);
}

/**
* @dev Update the proposal threshold. This operation can only be performed through a governance proposal.
*
* Emits a {ProposalThresholdSet} event.
*/
function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance {
_setProposalThreshold(newProposalThreshold);
}

/**
* @dev Internal setter for the voting delay.
*
* Emits a {VotingDelaySet} event.
*/
function _setVotingDelay(uint256 newVotingDelay) internal virtual {
emit VotingDelaySet(_votingDelay, newVotingDelay);
_votingDelay = newVotingDelay;
}

/**
* @dev Internal setter for the voting period.
*
* Emits a {VotingPeriodSet} event.
*/
function _setVotingPeriod(uint256 newVotingPeriod) internal virtual {
// voting period must be at least one block long
require(newVotingPeriod > 0, "GovernorSettings: voting period too low");
emit VotingPeriodSet(_votingPeriod, newVotingPeriod);
_votingPeriod = newVotingPeriod;
}

/**
* @dev Internal setter for the proposal threshold.
*
* Emits a {ProposalThresholdSet} event.
*/
function _setProposalThreshold(uint256 newProposalThreshold) internal virtual {
emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold);
_proposalThreshold = newProposalThreshold;
}
}
6 changes: 3 additions & 3 deletions src/extensions/GovernorVotes.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: MIT
// Modification of OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotes.sol)
// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotes.sol)

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/governance/Governor.sol";
import {IVotes} from "../utils/IVotes.sol";
import "../Governor.sol";
import "../utils/IVotes.sol";

/**
* @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/GovernorVotesQuorumFraction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

pragma solidity ^0.8.0;

import {GovernorVotes} from "./GovernorVotes.sol";
import "./GovernorVotes.sol";

/**
* @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a
Expand Down
Loading