Skip to content

Commit 1d2dfdb

Browse files
committed
Standard voting mode tests
1 parent ff4d3c0 commit 1d2dfdb

File tree

1 file changed

+144
-20
lines changed

1 file changed

+144
-20
lines changed

test/TokenVoting.t.sol

Lines changed: 144 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,8 @@ contract TokenVotingTest is TestBase {
392392
// It reverts if the total token supply is 0
393393
address[] memory holders = new address[](1);
394394
holders[0] = alice;
395-
uint256[] memory balances = new uint256[](1);
396395

397-
(dao, plugin,,) = new SimpleBuilder().withNewToken(holders, balances).build();
396+
(dao, plugin,,) = new SimpleBuilder().withNewToken(holders, 0).build();
398397
dao.grant(address(plugin), alice, plugin.CREATE_PROPOSAL_PERMISSION_ID());
399398

400399
vm.expectRevert(TokenVoting.NoVotingPower.selector);
@@ -541,65 +540,190 @@ contract TokenVotingTest is TestBase {
541540
}
542541

543542
modifier givenInTheStandardVotingMode() {
543+
address[] memory holders = new address[](10);
544+
for (uint256 i = 0; i < 10; i++) {
545+
holders[i] = vm.addr(100 + i);
546+
}
547+
uint256 balance = 10 ether;
548+
549+
(dao, plugin, token,) = new SimpleBuilder().withSupportThreshold(500_000).withMinParticipation(250_000)
550+
.withNewToken(holders, balance).build();
551+
552+
dao.grant(address(plugin), address(this), plugin.CREATE_PROPOSAL_PERMISSION_ID());
553+
dao.grant(address(plugin), vm.addr(100), plugin.CREATE_PROPOSAL_PERMISSION_ID());
554+
dao.grant(address(plugin), address(this), plugin.EXECUTE_PROPOSAL_PERMISSION_ID());
555+
544556
_;
545557
}
546558

547-
function test_WhenInteractingWithANonexistentProposal() external givenInTheStandardVotingMode {
559+
function test_revert_WhenInteractingWithANonexistentProposal() external givenInTheStandardVotingMode {
548560
// It reverts if proposal does not exist
549-
vm.skip(true);
561+
vm.expectRevert(abi.encodeWithSelector(MajorityVotingBase.NonexistentProposal.selector, 999));
562+
plugin.canExecute(999);
550563
}
551564

552-
function test_WhenVotingBeforeTheProposalHasStarted() external givenInTheStandardVotingMode {
565+
function test_revert_WhenVotingBeforeTheProposalHasStarted() external givenInTheStandardVotingMode {
553566
// It does not allow voting, when the vote has not started yet
554-
vm.skip(true);
567+
uint64 futureDate = uint64(block.timestamp + 1 days);
568+
uint256 proposalId =
569+
plugin.createProposal("0x", new Action[](0), 0, futureDate, 0, IMajorityVoting.VoteOption.None, false);
570+
571+
vm.expectRevert(
572+
abi.encodeWithSelector(
573+
MajorityVotingBase.VoteCastForbidden.selector, proposalId, vm.addr(100), IMajorityVoting.VoteOption.Yes
574+
)
575+
);
576+
vm.prank(vm.addr(100));
577+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
555578
}
556579

557-
function test_WhenAUserWith0TokensTriesToVote() external givenInTheStandardVotingMode {
580+
function test_revert_WhenAUserWith0TokensTriesToVote() external givenInTheStandardVotingMode {
558581
// It should not be able to vote if user has 0 token
559-
vm.skip(true);
582+
uint256 proposalId = _createDummyProposal(vm.addr(100));
583+
584+
vm.expectRevert(
585+
abi.encodeWithSelector(
586+
MajorityVotingBase.VoteCastForbidden.selector, proposalId, david, IMajorityVoting.VoteOption.Yes
587+
)
588+
);
589+
vm.prank(david); // David has 0 tokens
590+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
560591
}
561592

562593
function test_WhenMultipleUsersVoteYesNoAndAbstain() external givenInTheStandardVotingMode {
563594
// It increases the yes, no, and abstain count and emits correct events
564-
vm.skip(true);
595+
uint256 proposalId = _createDummyProposal(vm.addr(100));
596+
uint256 bal = 10 ether;
597+
598+
vm.expectEmit(true, true, true, true);
599+
emit IMajorityVoting.VoteCast(proposalId, vm.addr(101), IMajorityVoting.VoteOption.Yes, bal);
600+
vm.prank(vm.addr(101));
601+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
602+
603+
vm.expectEmit(true, true, true, true);
604+
emit IMajorityVoting.VoteCast(proposalId, vm.addr(102), IMajorityVoting.VoteOption.No, bal);
605+
vm.prank(vm.addr(102));
606+
plugin.vote(proposalId, IMajorityVoting.VoteOption.No, false);
607+
608+
vm.expectEmit(true, true, true, true);
609+
emit IMajorityVoting.VoteCast(proposalId, vm.addr(103), IMajorityVoting.VoteOption.Abstain, bal);
610+
vm.prank(vm.addr(103));
611+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Abstain, false);
612+
613+
(,,, MajorityVotingBase.Tally memory tally,,,) = plugin.getProposal(proposalId);
614+
assertEq(tally.yes, bal);
615+
assertEq(tally.no, bal);
616+
assertEq(tally.abstain, bal);
565617
}
566618

567-
function test_WhenAUserTriesToVoteWithVoteOptionNone() external givenInTheStandardVotingMode {
619+
function test_revert_WhenAUserTriesToVoteWithVoteOptionNone() external givenInTheStandardVotingMode {
568620
// It reverts on voting None
569-
vm.skip(true);
621+
uint256 proposalId = _createDummyProposal(vm.addr(100));
622+
vm.prank(vm.addr(101));
623+
vm.expectRevert(
624+
abi.encodeWithSelector(
625+
MajorityVotingBase.VoteCastForbidden.selector, proposalId, vm.addr(101), IMajorityVoting.VoteOption.None
626+
)
627+
);
628+
plugin.vote(proposalId, IMajorityVoting.VoteOption.None, false);
570629
}
571630

572-
function test_WhenAUserTriesToReplaceTheirExistingVote() external givenInTheStandardVotingMode {
631+
function test_revert_WhenAUserTriesToReplaceTheirExistingVote() external givenInTheStandardVotingMode {
573632
// It reverts on vote replacement
574-
vm.skip(true);
633+
uint256 proposalId = _createDummyProposal(vm.addr(100));
634+
vm.prank(vm.addr(101));
635+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
636+
637+
vm.prank(vm.addr(101));
638+
vm.expectRevert(
639+
abi.encodeWithSelector(
640+
MajorityVotingBase.VoteCastForbidden.selector, proposalId, vm.addr(101), IMajorityVoting.VoteOption.No
641+
)
642+
);
643+
plugin.vote(proposalId, IMajorityVoting.VoteOption.No, false);
575644
}
576645

577646
function test_WhenAProposalMeetsExecutionCriteriaBeforeTheEndDate() external givenInTheStandardVotingMode {
578647
// It cannot early execute
579-
vm.skip(true);
648+
uint256 proposalId = _createDummyProposal(vm.addr(100));
649+
for (uint256 i = 1; i <= 6; i++) {
650+
vm.prank(vm.addr(100 + i));
651+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
652+
}
653+
// Support and Participation are high enough, but it's Standard mode
654+
assertTrue(plugin.isSupportThresholdReachedEarly(proposalId));
655+
assertTrue(plugin.isMinParticipationReached(proposalId));
656+
assertFalse(plugin.canExecute(proposalId));
580657
}
581658

582659
function test_WhenAProposalMeetsParticipationAndSupportThresholdsAfterTheEndDate()
583660
external
584661
givenInTheStandardVotingMode
585662
{
586663
// It can execute normally if participation and support are met
587-
vm.skip(true);
664+
uint256 proposalId = _createDummyProposal(vm.addr(100));
665+
// 2 yes (20), 1 no (10) -> 3 voters, 30 total votes -> 30% participation, >50% support
666+
vm.prank(vm.addr(101));
667+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
668+
vm.prank(vm.addr(102));
669+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
670+
vm.prank(vm.addr(103));
671+
plugin.vote(proposalId, IMajorityVoting.VoteOption.No, false);
672+
673+
(,, MajorityVotingBase.ProposalParameters memory params,,,,) = plugin.getProposal(proposalId);
674+
vm.warp(params.endDate);
675+
676+
assertTrue(plugin.canExecute(proposalId));
677+
plugin.execute(proposalId);
678+
(bool open, bool executed,,,,,) = plugin.getProposal(proposalId);
679+
assertFalse(open);
680+
assertTrue(executed);
588681
}
589682

590683
function test_WhenVotingWithTheTryEarlyExecutionOption() external givenInTheStandardVotingMode {
591684
// It does not execute early when voting with the `tryEarlyExecution` option
592-
vm.skip(true);
685+
uint256 proposalId = _createDummyProposal(vm.addr(100));
686+
for (uint256 i = 1; i < 7; i++) {
687+
vm.prank(vm.addr(100 + i));
688+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
689+
}
690+
691+
vm.prank(vm.addr(107));
692+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, true); // try early exec
693+
694+
(, bool executed,,,,,) = plugin.getProposal(proposalId);
695+
assertFalse(executed);
593696
}
594697

595-
function test_WhenTryingToExecuteAProposalThatIsNotYetDecided() external givenInTheStandardVotingMode {
698+
function test_revert_WhenTryingToExecuteAProposalThatIsNotYetDecided() external givenInTheStandardVotingMode {
596699
// It reverts if vote is not decided yet
597-
vm.skip(true);
700+
uint256 proposalId = _createDummyProposal(vm.addr(100));
701+
vm.expectRevert(abi.encodeWithSelector(MajorityVotingBase.ProposalExecutionForbidden.selector, proposalId));
702+
plugin.execute(proposalId);
598703
}
599704

600-
function test_WhenTheCallerDoesNotHaveEXECUTEPROPOSALPERMISSIONID() external givenInTheStandardVotingMode {
705+
function test_revert_WhenTheCallerDoesNotHaveEXECUTEPROPOSALPERMISSIONID() external givenInTheStandardVotingMode {
601706
// It can not execute even if participation and support are met when caller does not have permission
602-
vm.skip(true);
707+
uint256 proposalId = _createDummyProposal(vm.addr(100));
708+
vm.prank(vm.addr(101));
709+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
710+
vm.prank(vm.addr(102));
711+
plugin.vote(proposalId, IMajorityVoting.VoteOption.Yes, false);
712+
vm.prank(vm.addr(103));
713+
plugin.vote(proposalId, IMajorityVoting.VoteOption.No, false);
714+
715+
(,, MajorityVotingBase.ProposalParameters memory params,,,,) = plugin.getProposal(proposalId);
716+
vm.warp(params.endDate);
717+
718+
dao.revoke(address(dao), address(plugin), dao.EXECUTE_PERMISSION_ID());
719+
720+
vm.expectRevert(
721+
abi.encodeWithSelector(
722+
DaoUnauthorized.selector, address(dao), address(plugin), bob, plugin.EXECUTE_PROPOSAL_PERMISSION_ID()
723+
)
724+
);
725+
vm.prank(bob); // Bob has no permission
726+
plugin.execute(proposalId);
603727
}
604728

605729
modifier givenInTheEarlyExecutionVotingMode() {

0 commit comments

Comments
 (0)