Skip to content

Commit

Permalink
Merge pull request #3 from indexed-finance/meta-governance
Browse files Browse the repository at this point in the history
Require votes > 0 & Add natspec docs for meta governor contracts
  • Loading branch information
d1ll0n committed Jan 22, 2021
2 parents b405d86 + 3718c2a commit da78631
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 1 deletion.
26 changes: 26 additions & 0 deletions contracts/meta/MetaGovernorCOMP.sol
Expand Up @@ -5,6 +5,27 @@ pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/SafeMath.sol";


/**
* @title MetaGovernorCOMP
* @dev Meta-governance contract for Compound's GovernorAlpha.
*
* This contract enables NDX holders to vote, by simple majority, on how to cast
* votes for Compound governance proposals.
*
* Each Compound proposal is wrapped as a meta proposal, which has an endBlock which
* ends some number of blocks prior to the end of the real proposal in order to give
* NDX holders time to cast meta votes prior to casting votes for the entire dao.
*
* This contract counts voting power from users the same way as the typical GovernorAlpha,
* which is to call getPriorVotes to check the delegation a voting account held at the time
* the external proposal began.
*
* Once a meta proposal has ended, it may be executed to cast votes on Compound. If the proposal
* has more votes in favor than against, it will cast votes supporting the proposal. Otherwise,
* it will cast votes against the proposal.
*
* This contract may not be used to submit proposals to Compound, only to vote on them.
*/
contract MetaGovernorCOMP {
using SafeMath for uint256;

Expand Down Expand Up @@ -112,6 +133,7 @@ contract MetaGovernorCOMP {
}

function _getMetaProposal(uint256 proposalId) internal returns (MetaProposal storage) {
// Get the meta proposal if it exists, else initialize the block fields using the external proposal.
MetaProposal storage proposal = proposals[proposalId];
if (proposal.startBlock == 0) {
IGovernorAlpha.Proposal memory externalProposal = compGovernor.proposals(proposalId);
Expand All @@ -137,6 +159,10 @@ contract MetaGovernorCOMP {
"MetaGovernorCOMP::_castVote: voter already voted"
);
uint96 votes = ndx.getPriorVotes(voter, proposal.startBlock);
require(
votes > 0,
"MetaGovernorCOMP::_castVote: caller has no delegated NDX"
);

if (support) {
proposal.forVotes = SafeMath.add(proposal.forVotes, votes);
Expand Down
26 changes: 26 additions & 0 deletions contracts/meta/MetaGovernorUNI.sol
Expand Up @@ -5,6 +5,27 @@ pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/SafeMath.sol";


/**
* @title MetaGovernorUNI
* @dev Meta-governance contract for Uniswap's GovernorAlpha.
*
* This contract enables NDX holders to vote, by simple majority, on how to cast
* votes for Uniswap governance proposals.
*
* Each Uniswap proposal is wrapped as a meta proposal, which has an endBlock which
* ends some number of blocks prior to the end of the real proposal in order to give
* NDX holders time to cast meta votes prior to casting votes for the entire dao.
*
* This contract counts voting power from users the same way as the typical GovernorAlpha,
* which is to call getPriorVotes to check the delegation a voting account held at the time
* the external proposal began.
*
* Once a meta proposal has ended, it may be executed to cast votes on Uniswap. If the proposal
* has more votes in favor than against, it will cast votes supporting the proposal. Otherwise,
* it will cast votes against the proposal.
*
* This contract may not be used to submit proposals to Uniswap, only to vote on them.
*/
contract MetaGovernorUNI {
using SafeMath for uint256;

Expand Down Expand Up @@ -112,6 +133,7 @@ contract MetaGovernorUNI {
}

function _getMetaProposal(uint256 proposalId) internal returns (MetaProposal storage) {
// Get the meta proposal if it exists, else initialize the block fields using the external proposal.
MetaProposal storage proposal = proposals[proposalId];
if (proposal.startBlock == 0) {
IGovernorAlpha.Proposal memory externalProposal = uniGovernor.proposals(proposalId);
Expand All @@ -137,6 +159,10 @@ contract MetaGovernorUNI {
"MetaGovernorUNI::_castVote: voter already voted"
);
uint96 votes = ndx.getPriorVotes(voter, proposal.startBlock);
require(
votes > 0,
"MetaGovernorUNI::_castVote: caller has no delegated NDX"
);

if (support) {
proposal.forVotes = SafeMath.add(proposal.forVotes, votes);
Expand Down
8 changes: 7 additions & 1 deletion test/MetaGovernorCOMP.spec.js
Expand Up @@ -76,10 +76,16 @@ describe('MetaGovernorCOMP', () => {
let balance, metaProposal, proposal;
setupTests();

it('rejects if caller has no votes', async () => {
await expect(
metaGovernor.connect(signer2).castVote(1, true)
).to.be.revertedWith('MetaGovernorCOMP::_castVote: caller has no delegated NDX')
})

it('casts vote', async () => {
balance = await ndx.balanceOf(deployer);
await metaGovernor.castVote(1, true);
metaProposal = await metaGovernor.proposals( 1);
metaProposal = await metaGovernor.proposals(1);
proposal = await compGovernor.proposals(1);
})

Expand Down
6 changes: 6 additions & 0 deletions test/MetaGovernorUNI.spec.js
Expand Up @@ -76,6 +76,12 @@ describe('MetaGovernorUNI', () => {
let balance, metaProposal, proposal;
setupTests();

it('rejects if caller has no votes', async () => {
await expect(
metaGovernor.connect(signer2).castVote(1, true)
).to.be.revertedWith('MetaGovernorUNI::_castVote: caller has no delegated NDX')
})

it('casts vote', async () => {
balance = await ndx.balanceOf(deployer);
await metaGovernor.castVote(1, true);
Expand Down

0 comments on commit da78631

Please sign in to comment.