Skip to content

Commit

Permalink
more tests refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nginnever committed Aug 4, 2021
1 parent 4546d7c commit ae27301
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 38 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
- TW017 "cancel proposal already executed"
- TW018 "cancel proposal already past deadline"
- TW019 "cancel proposal must be originator or Safe"
- TW020 "can't undelegate more votes than delegated"
- TW021 "cannot vote in the same block as delegation"
- TW020 "linear voting: can't undelegate more votes than delegated"
- TW021 "linear voting: cannot vote in the same block as delegation"
- TW022 "must register voting module before submitting a proposal"
```
11 changes: 6 additions & 5 deletions contracts/ProposalModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,12 @@ contract ProposalModule {
require(proposals[proposalId].executed == false, "TW009");
require(proposals[proposalId].deadline >= block.timestamp, "TW010");

// require voting module is registered
proposals[proposalId].hasVoted[msg.sender] = true;

if(vote == false){
proposals[proposalId].noVotes = IVoting(_votingModule).calculateWeight(msg.sender);
if(vote == true){
proposals[proposalId].yesVotes = proposals[proposalId].yesVotes + IVoting(_votingModule).calculateWeight(msg.sender);
} else {
proposals[proposalId].noVotes = IVoting(_votingModule).calculateWeight(msg.sender);
proposals[proposalId].noVotes = proposals[proposalId].noVotes + IVoting(_votingModule).calculateWeight(msg.sender);
}
}

Expand Down Expand Up @@ -156,8 +155,9 @@ contract ProposalModule {
bytes memory data
//Enum.Operation _operation
) public {
require(_votingModule != address(0), "TW022");
uint total = IVoting(_votingModule).calculateWeight(msg.sender);
require(_activeProposal[msg.sender] = false, "TW011");
require(_activeProposal[msg.sender] == false, "TW011");
require(total >= _minimumProposalAmount, "TW012");
// store calldata for tx to be executed
proposals[_totalProposalCount].value = value;
Expand All @@ -179,6 +179,7 @@ contract ProposalModule {
require(proposals[proposalId].gracePeriod == 0, "TW013");
require(proposals[proposalId].deadline <= block.timestamp, "TW014");
proposals[proposalId].gracePeriod = block.timestamp + _gracePeriod;
proposals[proposalId].queued = true;
emit GracePeriodStarted(proposals[proposalId].gracePeriod);
}

Expand Down
4 changes: 2 additions & 2 deletions contracts/VotingModules/LinearVoting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ contract LinearVoting {

address private _governanceToken;

mapping(address => Delegation) delegations;
mapping(address => Delegation) public delegations;

event VotesDelegated(uint number);
event VotesUndelegated(uint number);
Expand Down Expand Up @@ -50,7 +50,7 @@ contract LinearVoting {
}

function calculateWeight(address delegate) external view returns (uint) {
require(delegations[delegate].lastBlock < block.number, "TW021");
require(delegations[delegate].lastBlock < block.number, "TW021"); // todo move this to a check function
// can return quadtric here
return delegations[delegate].total;
}
Expand Down
216 changes: 188 additions & 28 deletions test/governanceModuleTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,49 +54,209 @@ describe('proposalModule:', () => {
await proposalModule.registerVoteModule(linearVoting.address)
})

it.only('can delegate votes to self', async () => {
it('can delegate votes to self', async () => {
const { proposalModule, linearVoting, safe, govToken, weth } = daoFixture
await linearVoting.delegate()
const bal = await govToken.balanceOf(wallet_0.address)
await govToken.approve(linearVoting.address, 1000)
await linearVoting.delegateVotes(wallet_0.address, 1000)
const delegatation = await linearVoting.delegations(wallet_0.address)
expect(delegatation.total).to.equal(1000)
expect(await govToken.balanceOf(linearVoting.address)).to.equal(1000)
})

it('can execute enter safe admin DAO proposal', async () => {
it('can undelegate votes to self', async () => {
const { proposalModule, linearVoting, safe, govToken, weth } = daoFixture
const bal = await govToken.balanceOf(wallet_0.address)
await govToken.approve(linearVoting.address, 1000)
await linearVoting.delegateVotes(wallet_0.address, 1000)
const delegatation = await linearVoting.delegations(wallet_0.address)
expect(delegatation.total).to.equal(1000)
expect(await govToken.balanceOf(linearVoting.address)).to.equal(1000)
await linearVoting.undelegateVotes(wallet_0.address, 1000)
const undelegatation = await linearVoting.delegations(wallet_0.address)
expect(undelegatation.total).to.equal(0)
expect(await govToken.balanceOf(linearVoting.address)).to.equal(0)
})

it('can delegate votes to others', async () => {
const { proposalModule, linearVoting, safe, govToken, weth } = daoFixture
const bal = await govToken.balanceOf(wallet_0.address)
await govToken.approve(linearVoting.address, 1000)
await linearVoting.delegateVotes(wallet_0.address, 1000)
await govToken.connect(wallet_1).approve(linearVoting.address, 1000)
await linearVoting.connect(wallet_1).delegateVotes(wallet_0.address, 1000)
await govToken.connect(wallet_2).approve(linearVoting.address, 1000)
await linearVoting.connect(wallet_2).delegateVotes(wallet_0.address, 1000)
const delegatation = await linearVoting.delegations(wallet_0.address)
expect(delegatation.total).to.equal(3000)
expect(await govToken.balanceOf(linearVoting.address)).to.equal(3000)
})

it('can undelegate votes to others', async () => {
const { proposalModule, linearVoting, safe, govToken, weth } = daoFixture
const bal = await govToken.balanceOf(wallet_0.address)
await govToken.approve(linearVoting.address, 1000)
await linearVoting.delegateVotes(wallet_0.address, 1000)
await govToken.connect(wallet_1).approve(linearVoting.address, 1000)
await linearVoting.connect(wallet_1).delegateVotes(wallet_0.address, 1000)
await govToken.connect(wallet_2).approve(linearVoting.address, 1000)
await linearVoting.connect(wallet_2).delegateVotes(wallet_0.address, 1000)
const delegatation = await linearVoting.delegations(wallet_0.address)
expect(delegatation.total).to.equal(3000)
expect(await govToken.balanceOf(linearVoting.address)).to.equal(3000)
await linearVoting.connect(wallet_2).undelegateVotes(wallet_0.address, 1000)
const undelegatation = await linearVoting.delegations(wallet_0.address)
expect(undelegatation.total).to.equal(2000)
expect(await govToken.balanceOf(linearVoting.address)).to.equal(2000)
})

it('can execute add safe admin DAO proposal', async () => {
const { weth, proposalModule, linearVoting, safe, govToken } = daoFixture
await executeContractCallWithSigners(safe, safe, "enableModule", [proposalModule.address], [wallet_0])
await executeContractCallWithSigners(safe, proposalModule, "registerVoteModule", [linearVoting.address], [wallet_0])
await govToken.approve(linearVoting.address, ethers.BigNumber.from('1000000000000000000'))
await linearVoting.delegateVotes(wallet_0.address, ethers.BigNumber.from('1000000000000000000'))
let addCall = buildContractCall(safe, "addOwnerWithThreshold", [wallet_2.address, 1], await safe.nonce())
await proposalModule.submitModularProposal(safe.address, 0, addCall.data)
let proposal = await proposalModule.proposals(0)
expect(proposal.value).to.equal(0)
expect(proposal.yesVotes).to.equal(ethers.BigNumber.from('1000000000000000000'))
expect(proposal.noVotes).to.equal(0)
expect(proposal.proposer).to.equal(wallet_0.address)
expect(proposal.canceled).to.equal(false)
expect(proposal.targetAddress).to.equal(safe.address)
expect(proposal.data).to.equal(addCall.data)
await network.provider.send("evm_increaseTime", [60])
await proposalModule.startModularQueue(0)
proposal = await proposalModule.proposals(0)
expect(proposal.queued).to.equal(true)
await network.provider.send("evm_increaseTime", [60])
await proposalModule.executeModularProposal(0)
proposal = await proposalModule.proposals(0)
expect(proposal.executed).to.equal(true)
const owners = await safe.getOwners()
expect(owners[0]).to.equal(wallet_2.address)
expect(owners[1]).to.equal(wallet_0.address)
})

let addCall = buildContractCall(safe, "addOwner", [wallet_2.address, 1], await safe.nonce())
it.skip('cannot create proposal with out delegation threshold', async () => {
const { weth, proposalModule, linearVoting, safe, govToken } = daoFixture
await executeContractCallWithSigners(safe, safe, "enableModule", [proposalModule.address], [wallet_0])
await executeContractCallWithSigners(safe, proposalModule, "registerVoteModule", [linearVoting.address], [wallet_0])
let addCall = buildContractCall(safe, "addOwnerWithThreshold", [wallet_2.address, 1], await safe.nonce())
await proposalModule.submitModularProposal(safe.address, 0, addCall.data)
})

it('can vote past the threshold with delegation', async () => {
const { weth, proposalModule, linearVoting, safe, govToken } = daoFixture
await executeContractCallWithSigners(safe, safe, "enableModule", [proposalModule.address], [wallet_0])
await executeContractCallWithSigners(safe, proposalModule, "registerVoteModule", [linearVoting.address], [wallet_0])
await govToken.approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.delegateVotes(wallet_0.address, ethers.BigNumber.from('500000000000000000'))
await govToken.connect(wallet_1).approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.connect(wallet_1).delegateVotes(wallet_0.address, ethers.BigNumber.from('500000000000000000'))
let addCall = buildContractCall(safe, "addOwnerWithThreshold", [wallet_2.address, 1], await safe.nonce())
await proposalModule.submitModularProposal(safe.address, 0, addCall.data)
let proposal = await proposalModule.proposals(0)
expect(proposal.value).to.equal(0)
expect(proposal.yesVotes).to.equal(ethers.BigNumber.from('1000000000000000000'))
expect(proposal.noVotes).to.equal(0)
expect(proposal.proposer).to.equal(wallet_0.address)
expect(proposal.canceled).to.equal(false)
expect(proposal.targetAddress).to.equal(safe.address)
expect(proposal.data).to.equal(addCall.data)
await network.provider.send("evm_increaseTime", [60])
await proposalModule.startModularGracePeriod(0)
await proposalModule.startModularQueue(0)
proposal = await proposalModule.proposals(0)
expect(proposal.queued).to.equal(true)
await network.provider.send("evm_increaseTime", [60])
await proposalModule.executeModularProposal(0)
let owners = await safe.getOwners()
console.log(owners)
proposal = await proposalModule.proposals(0)
expect(proposal.executed).to.equal(true)
const owners = await safe.getOwners()
expect(owners[0]).to.equal(wallet_2.address)
expect(owners[1]).to.equal(wallet_0.address)
})

await proposalModule.headOfHouseEnterMember(wallet_3.address)
expect(await proposalModule.memberCount()).to.equal(2)
let role = {
headOfHouse: false,
member: true
}
await proposalModule.connect(wallet_2).joinDAOProposal(role)
await proposalModule.connect(wallet_3).vote(0, true)
it.skip('can vote in same block as delegatation', async () => {
const { weth, proposalModule, linearVoting, safe, govToken } = daoFixture
await executeContractCallWithSigners(safe, safe, "enableModule", [proposalModule.address], [wallet_0])
await executeContractCallWithSigners(safe, proposalModule, "registerVoteModule", [linearVoting.address], [wallet_0])
await govToken.approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.delegateVotes(wallet_0.address, ethers.BigNumber.from('500000000000000000'))
await govToken.connect(wallet_1).approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.connect(wallet_1).delegateVotes(wallet_1.address, ethers.BigNumber.from('500000000000000000'))
const weight = await linearVoting.calculateWeight(wallet_1.address)
})


it.only('can vote past the threshold with independent delegatation', async () => {
const { weth, proposalModule, linearVoting, safe, govToken } = daoFixture
await executeContractCallWithSigners(safe, safe, "enableModule", [proposalModule.address], [wallet_0])
await executeContractCallWithSigners(safe, proposalModule, "registerVoteModule", [linearVoting.address], [wallet_0])
await govToken.approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.delegateVotes(wallet_0.address, ethers.BigNumber.from('500000000000000000'))
await govToken.connect(wallet_1).approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.connect(wallet_1).delegateVotes(wallet_1.address, ethers.BigNumber.from('500000000000000000'))
await network.provider.send("evm_mine")
const weight = await linearVoting.calculateWeight(wallet_1.address)
expect(weight).to.equal(ethers.BigNumber.from('500000000000000000'))
let addCall = buildContractCall(safe, "addOwnerWithThreshold", [wallet_2.address, 1], await safe.nonce())
await proposalModule.submitModularProposal(safe.address, 0, addCall.data)
let proposal = await proposalModule.proposals(0)
expect(proposal.yesVotes).to.equal('1000000000000010000') // if they buy on the market this will be non-zero
expect(proposal.value).to.equal(0)
expect(proposal.yesVotes).to.equal(ethers.BigNumber.from('500000000000000000'))
expect(proposal.noVotes).to.equal(0)
expect(await govToken.balanceOf(wallet_2.address)).to.equal('1000000000000000000')
expect(await govToken.balanceOf(proposalModule.address)).to.equal('50000000000000000000000')
await network.provider.send("evm_increaseTime", [259200])
await proposalModule.connect(wallet_2).executeEnterDAOProposal(0)
expect(await govToken.balanceOf(wallet_2.address)).to.equal('1000000000000000000')
expect(proposal.proposer).to.equal(wallet_0.address)
expect(proposal.canceled).to.equal(false)
expect(proposal.targetAddress).to.equal(safe.address)
expect(proposal.data).to.equal(addCall.data)
await proposalModule.connect(wallet_1).vote(0, true)
proposal = await proposalModule.proposals(0)
expect(proposal.yesVotes).to.equal(ethers.BigNumber.from('1000000000000000000'))
await network.provider.send("evm_increaseTime", [60])
await proposalModule.startModularQueue(0)
proposal = await proposalModule.proposals(0)
expect(proposal.queued).to.equal(true)
await network.provider.send("evm_increaseTime", [60])
await proposalModule.executeModularProposal(0)
proposal = await proposalModule.proposals(0)
expect(proposal.executed).to.equal(true)
expect(proposal.canceled).to.equal(false)
let member = await proposalModule.members(wallet_2.address)
expect(member.shares).to.equal(0)
expect(member.roles.member).to.equal(true)
expect(await proposalModule.balance()).to.equal(0)
expect(await proposalModule.totalContribution()).to.equal(0)
expect(await proposalModule.memberCount()).to.equal(3)
const owners = await safe.getOwners()
expect(owners[0]).to.equal(wallet_2.address)
expect(owners[1]).to.equal(wallet_0.address)
})

it('can only vote once per proposal', async () => {
const { weth, proposalModule, linearVoting, safe, govToken } = daoFixture
await executeContractCallWithSigners(safe, safe, "enableModule", [proposalModule.address], [wallet_0])
await executeContractCallWithSigners(safe, proposalModule, "registerVoteModule", [linearVoting.address], [wallet_0])
await govToken.approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.delegateVotes(wallet_0.address, ethers.BigNumber.from('500000000000000000'))
await govToken.connect(wallet_1).approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.connect(wallet_1).delegateVotes(wallet_1.address, ethers.BigNumber.from('500000000000000000'))
let addCall = buildContractCall(safe, "addOwnerWithThreshold", [wallet_2.address, 1], await safe.nonce())
await proposalModule.submitModularProposal(safe.address, 0, addCall.data)
await proposalModule.connect(wallet_1).vote(0, true)
await proposalModule.connect(wallet_1).vote(0, true)
})

it.skip('cannot enter queue if not past threshold', async () => {
const { weth, proposalModule, linearVoting, safe, govToken } = daoFixture
await executeContractCallWithSigners(safe, safe, "enableModule", [proposalModule.address], [wallet_0])
await executeContractCallWithSigners(safe, proposalModule, "registerVoteModule", [linearVoting.address], [wallet_0])
await govToken.approve(linearVoting.address, ethers.BigNumber.from('500000000000000000'))
await linearVoting.delegateVotes(wallet_0.address, ethers.BigNumber.from('500000000000000000'))
let addCall = buildContractCall(safe, "addOwnerWithThreshold", [wallet_2.address, 1], await safe.nonce())
await proposalModule.submitModularProposal(safe.address, 0, addCall.data)
let proposal = await proposalModule.proposals(0)
expect(proposal.yesVotes).to.equal(ethers.BigNumber.from('500000000000000000'))
await network.provider.send("evm_increaseTime", [60])
await proposalModule.startModularQueue(0)
})

it('cannot enter queue if not past deadline', async () => {

})

it('can have only one DAO proposal at a time', async () => {
Expand Down
5 changes: 4 additions & 1 deletion test/shared/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function getFixtureWithParams(
wallet: SignerWithAddress,
fromWallet: boolean = true
): Promise<any> {

const [wallet_0, wallet_1, wallet_2, wallet_3] = waffle.provider.getWallets();
const wethContract = await ethers.getContractFactory("WETH9")
// deploy tokens
const weth = await wethContract.deploy()
Expand All @@ -29,6 +29,9 @@ export async function getFixtureWithParams(

const govTokenContract = await ethers.getContractFactory("GovernanceToken")
const govToken = await govTokenContract.deploy("GovToken", "GT", ethers.BigNumber.from('100000000000000000000000'))
await govToken.transfer(wallet_1.address, ethers.BigNumber.from('1000000000000000000'))
await govToken.transfer(wallet_2.address, ethers.BigNumber.from('1000000000000000000'))
await govToken.transfer(wallet_3.address, ethers.BigNumber.from('1000000000000000000'))
console.log('Gov Token Deploy Cost ' + govToken.deployTransaction.gasLimit.toString())
console.log("deployed governance token: ", govToken.address)

Expand Down

0 comments on commit ae27301

Please sign in to comment.