difftreelog
Merge pull request #977 from UniqueNetwork/fix/gov-council-test
in: master
test(gov): added neg votes
1 file changed
tests/src/governance/council.test.tsdiffbeforeafterboth12import {IKeyringPair} from '@polkadot/types/types';3import {usingPlaygrounds, itSub, expect, Pallets, requirePalletsOrSkip, describeGov} from '../util';4import {Event} from '../util/playgrounds/unique.dev';5import {ICounselors, initCouncil, democracyLaunchPeriod, democracyVotingPeriod, democracyEnactmentPeriod, councilMotionDuration, democracyFastTrackVotingPeriod, fellowshipRankLimit, clearCouncil, clearTechComm, initTechComm, clearFellowship, dummyProposal, dummyProposalCall, initFellowship, defaultEnactmentMoment, fellowshipPropositionOrigin} from './util';67describeGov('Governance: Council tests', () => {8 let donor: IKeyringPair;9 let counselors: ICounselors;10 let sudoer: IKeyringPair;1112 const moreThanHalfCouncilThreshold = 3;1314 before(async function() {15 await usingPlaygrounds(async (helper, privateKey) => {16 requirePalletsOrSkip(this, helper, [Pallets.Council]);1718 donor = await privateKey({url: import.meta.url});19 sudoer = await privateKey('//Alice');20 });21 });2223 beforeEach(async () => {24 counselors = await initCouncil(donor, sudoer);25 });2627 afterEach(async () => {28 await clearCouncil(sudoer);29 await clearTechComm(sudoer);30 });3132 async function proposalFromMoreThanHalfCouncil(proposal: any) {33 return await usingPlaygrounds(async (helper) => {34 expect((await helper.callRpc('api.query.councilMembership.members')).toJSON().length).to.be.equal(5);35 const proposeResult = await helper.council.collective.propose(36 counselors.filip,37 proposal,38 moreThanHalfCouncilThreshold,39 );4041 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);42 const proposalIndex = councilProposedEvent.proposalIndex;43 const proposalHash = councilProposedEvent.proposalHash;444546 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);47 await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);48 await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);4950 return await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);51 });52 }5354 async function proposalFromAllCouncil(proposal: any) {55 return await usingPlaygrounds(async (helper) => {56 expect((await helper.callRpc('api.query.councilMembership.members')).toJSON().length).to.be.equal(5);57 const proposeResult = await helper.council.collective.propose(58 counselors.filip,59 proposal,60 moreThanHalfCouncilThreshold,61 );6263 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);64 const proposalIndex = councilProposedEvent.proposalIndex;65 const proposalHash = councilProposedEvent.proposalHash;666768 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);69 await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);70 await helper.council.collective.vote(counselors.ildar, proposalHash, proposalIndex, true);71 await helper.council.collective.vote(counselors.irina, proposalHash, proposalIndex, true);72 await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);7374 return await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);75 });76 }7778 itSub('>50% of Council can externally propose SuperMajorityAgainst', async ({helper}) => {79 const forceSetBalanceReceiver = helper.arrange.createEmptyAccount();80 const forceSetBalanceTestValue = 20n * 10n ** 25n;8182 const democracyProposal = await helper.constructApiCall('api.tx.balances.forceSetBalance', [83 forceSetBalanceReceiver.address, forceSetBalanceTestValue,84 ]);8586 const councilProposal = await helper.democracy.externalProposeDefaultCall(democracyProposal);8788 const proposeResult = await helper.council.collective.propose(89 counselors.filip,90 councilProposal,91 moreThanHalfCouncilThreshold,92 );9394 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);95 const proposalIndex = councilProposedEvent.proposalIndex;96 const proposalHash = councilProposedEvent.proposalHash;9798 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);99 await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);100 await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);101102 await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);103104 const democracyStartedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);105 const democracyReferendumIndex = democracyStartedEvent.referendumIndex;106 const democracyThreshold = democracyStartedEvent.threshold;107108 expect(democracyThreshold).to.be.equal('SuperMajorityAgainst');109110 await helper.democracy.vote(counselors.filip, democracyReferendumIndex, {111 Standard: {112 vote: {113 aye: true,114 conviction: 1,115 },116 balance: 10_000n,117 },118 });119120 const passedReferendumEvent = await helper.wait.expectEvent(democracyVotingPeriod, Event.Democracy.Passed);121 expect(passedReferendumEvent.referendumIndex).to.be.equal(democracyReferendumIndex);122123 await helper.wait.expectEvent(democracyEnactmentPeriod, Event.Scheduler.Dispatched);124 const receiverBalance = await helper.balance.getSubstrate(forceSetBalanceReceiver.address);125 expect(receiverBalance).to.be.equal(forceSetBalanceTestValue);126 });127128 itSub('Council prime member vote is the default', async ({helper}) => {129 const newTechCommMember = helper.arrange.createEmptyAccount();130 const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address);131 const proposeResult = await helper.council.collective.propose(132 counselors.filip,133 addMemberProposal,134 moreThanHalfCouncilThreshold,135 );136137 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);138 const proposalIndex = councilProposedEvent.proposalIndex;139 const proposalHash = councilProposedEvent.proposalHash;140141 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);142143 await helper.wait.newBlocks(councilMotionDuration);144 const closeResult = await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);145 const closeEvent = Event.Council.Closed.expect(closeResult);146 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON() as string[];147 expect(closeEvent.yes).to.be.equal(members.length);148 });149150 itSub('Superuser can add a member', async ({helper}) => {151 const newMember = helper.arrange.createEmptyAccount();152 await expect(helper.getSudo().council.membership.addMember(sudoer, newMember.address)).to.be.fulfilled;153154 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();155 expect(members).to.contains(newMember.address);156 });157158 itSub('Superuser can remove a member', async ({helper}) => {159 await expect(helper.getSudo().council.membership.removeMember(sudoer, counselors.alex.address)).to.be.fulfilled;160161 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();162 expect(members).to.not.contains(counselors.alex.address);163 });164165 itSub('>50% Council can add TechComm member', async ({helper}) => {166 const newTechCommMember = helper.arrange.createEmptyAccount();167 const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address);168169 await proposalFromMoreThanHalfCouncil(addMemberProposal);170171 const techCommMembers = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();172 expect(techCommMembers).to.contains(newTechCommMember.address);173 });174175 itSub('Council can remove TechComm member', async ({helper}) => {176 const techComm = await initTechComm(donor, sudoer);177 const removeMemberPrpoposal = helper.technicalCommittee.membership.removeMemberCall(techComm.andy.address);178 await proposalFromMoreThanHalfCouncil(removeMemberPrpoposal);179180 const techCommMembers = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();181 expect(techCommMembers).to.not.contains(techComm.andy.address);182 });183184 itSub.skip('Council member can add Fellowship member', async ({helper}) => {185 const newFellowshipMember = helper.arrange.createEmptyAccount();186 await expect(helper.council.collective.execute(187 counselors.alex,188 helper.fellowship.collective.addMemberCall(newFellowshipMember.address),189 )).to.be.fulfilled;190 const fellowshipMembers = (await helper.callRpc('api.query.fellowshipCollective.members')).toJSON();191 expect(fellowshipMembers).to.contains(newFellowshipMember.address);192 });193194 itSub('>50% Council can promote Fellowship member', async ({helper}) => {195 const fellowship = await initFellowship(donor, sudoer);196 const memberWithZeroRank = fellowship[0][0];197198 const proposal = helper.fellowship.collective.promoteCall(memberWithZeroRank.address);199 await proposalFromMoreThanHalfCouncil(proposal);200 const record = (await helper.callRpc('api.query.fellowshipCollective.members', [memberWithZeroRank.address])).toJSON();201 expect(record).to.be.deep.equal({rank: 1});202203 await clearFellowship(sudoer);204 });205206 itSub('>50% Council can demote Fellowship member', async ({helper}) => {207 const fellowship = await initFellowship(donor, sudoer);208 const memberWithRankOne = fellowship[1][0];209210 const proposal = helper.fellowship.collective.demoteCall(memberWithRankOne.address);211 await proposalFromMoreThanHalfCouncil(proposal);212213 const record = (await helper.callRpc('api.query.fellowshipCollective.members', [memberWithRankOne.address])).toJSON();214 expect(record).to.be.deep.equal({rank: 0});215216 await clearFellowship(sudoer);217 });218219 itSub('>50% Council can add\remove Fellowship member', async ({helper}) => {220 try {221 const newMember = helper.arrange.createEmptyAccount();222223 const proposalAdd = helper.fellowship.collective.addMemberCall(newMember.address);224 const proposalRemove = helper.fellowship.collective.removeMemberCall(newMember.address, fellowshipRankLimit);225 await expect(proposalFromMoreThanHalfCouncil(proposalAdd)).to.be.fulfilled;226 expect(await helper.fellowship.collective.getMembers()).to.be.deep.contain(newMember.address);227 await expect(proposalFromMoreThanHalfCouncil(proposalRemove)).to.be.fulfilled;228 expect(await helper.fellowship.collective.getMembers()).to.be.not.deep.contain(newMember.address);229 }230 finally {231 await clearFellowship(sudoer);232 }233 });234235 itSub('Council can blacklist Democracy proposals', async ({helper}) => {236 const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);237 await expect(proposalFromAllCouncil(helper.democracy.blacklistCall(preimageHash, null))).to.be.fulfilled;238 });239240 itSub('Sudo can blacklist Democracy proposals', async ({helper}) => {241 const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);242 await expect(helper.getSudo().democracy.blacklist(sudoer, preimageHash)).to.be.fulfilled;243 });244245 itSub('[Negative] Council cannot add Council member', async ({helper}) => {246 const newCouncilMember = helper.arrange.createEmptyAccount();247 const addMemberProposal = helper.council.membership.addMemberCall(newCouncilMember.address);248249 await expect(proposalFromAllCouncil(addMemberProposal)).to.be.rejected;250 });251252 itSub('[Negative] Council cannot remove Council member', async ({helper}) => {253 const removeMemberProposal = helper.council.membership.removeMemberCall(counselors.alex.address);254255 await expect(proposalFromAllCouncil(removeMemberProposal)).to.be.rejected;256 });257258 itSub('[Negative] Council cannot submit regular democracy proposal', async ({helper}) => {259 const councilProposal = await helper.democracy.proposeCall(dummyProposalCall(helper), 0n);260261 await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);262 });263264 itSub('[Negative] Council cannot externally propose SimpleMajority', async ({helper}) => {265 const councilProposal = await helper.democracy.externalProposeMajorityCall(dummyProposalCall(helper));266267 await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);268 });269270 itSub('[Negative] Council cannot externally propose SuperMajorityApprove', async ({helper}) => {271 const councilProposal = await helper.democracy.externalProposeCall(dummyProposalCall(helper));272273 await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);274 });275276 itSub('[Negative] Council member cannot add/remove a Council member', async ({helper}) => {277 const newCouncilMember = helper.arrange.createEmptyAccount();278 await expect(helper.council.collective.execute(279 counselors.alex,280 helper.council.membership.addMemberCall(newCouncilMember.address),281 )).to.be.rejectedWith('BadOrigin');282 await expect(helper.council.collective.execute(283 counselors.alex,284 helper.council.membership.removeMemberCall(counselors.charu.address),285 )).to.be.rejectedWith('BadOrigin');286 });287288 itSub('[Negative] Council cannot set/clear Council prime member', async ({helper}) => {289 const proposalForSet = await helper.council.membership.setPrimeCall(counselors.charu.address);290 const proposalForClear = await helper.council.membership.clearPrimeCall();291292 await expect(proposalFromAllCouncil(proposalForSet)).to.be.rejectedWith(/BadOrigin/);293 await expect(proposalFromAllCouncil(proposalForClear)).to.be.rejectedWith(/BadOrigin/);294295 });296297 itSub('[Negative] Council member cannot set/clear Council prime member', async ({helper}) => {298 await expect(helper.council.collective.execute(299 counselors.alex,300 helper.council.membership.setPrimeCall(counselors.charu.address),301 )).to.be.rejectedWith('BadOrigin');302 await expect(helper.council.collective.execute(303 counselors.alex,304 helper.council.membership.clearPrimeCall(),305 )).to.be.rejectedWith('BadOrigin');306 });307308 itSub('[Negative] Council member cannot add/remove a TechComm member', async ({helper}) => {309 const newTechCommMember = helper.arrange.createEmptyAccount();310 await expect(helper.council.collective.execute(311 counselors.alex,312 helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address),313 )).to.be.rejectedWith('BadOrigin');314 await expect(helper.council.collective.execute(315 counselors.alex,316 helper.technicalCommittee.membership.removeMemberCall(newTechCommMember.address),317 )).to.be.rejectedWith('BadOrigin');318 });319320 itSub('[Negative] Council member cannot promote/demote a Fellowship member', async ({helper}) => {321 const fellowship = await initFellowship(donor, sudoer);322 const memberWithRankOne = fellowship[1][0];323324 await expect(helper.council.collective.execute(325 counselors.alex,326 helper.fellowship.collective.promoteCall(memberWithRankOne.address),327 )).to.be.rejectedWith('BadOrigin');328 await expect(helper.council.collective.execute(329 counselors.alex,330 helper.fellowship.collective.demoteCall(memberWithRankOne.address),331 )).to.be.rejectedWith('BadOrigin');332 await clearFellowship(sudoer);333 });334335 itSub('[Negative] Council cannot fast-track Democracy proposals', async ({helper}) => {336 const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);337 await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);338339 await expect(proposalFromAllCouncil(helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0)))340 .to.be.rejectedWith(/BadOrigin/);341 });342343 itSub('[Negative] Council member cannot fast-track Democracy proposals', async ({helper}) => {344 const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);345 await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);346347 await expect(helper.council.collective.execute(348 counselors.alex,349 helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0),350 )).to.be.rejectedWith('BadOrigin');351 });352353 itSub('[Negative] Council cannot cancel Democracy proposals', async ({helper}) => {354 const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);355 const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;356357 await expect(proposalFromAllCouncil(helper.democracy.cancelProposalCall(proposalIndex)))358 .to.be.rejectedWith(/BadOrigin/);359 });360361 itSub('[Negative] Council member cannot cancel Democracy proposals', async ({helper}) => {362363 const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);364 const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;365366 await expect(helper.council.collective.execute(367 counselors.alex,368 helper.democracy.cancelProposalCall(proposalIndex),369 )).to.be.rejectedWith('BadOrigin');370 });371372 itSub('[Negative] Council cannot cancel ongoing Democracy referendums', async ({helper}) => {373 await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));374 const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);375 const referendumIndex = startedEvent.referendumIndex;376377 await expect(proposalFromAllCouncil(helper.democracy.emergencyCancelCall(referendumIndex)))378 .to.be.rejectedWith(/BadOrigin/);379 });380381 itSub('[Negative] Council member cannot cancel ongoing Democracy referendums', async ({helper}) => {382 await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));383 const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);384 const referendumIndex = startedEvent.referendumIndex;385386 await expect(helper.council.collective.execute(387 counselors.alex,388 helper.democracy.emergencyCancelCall(referendumIndex),389 )).to.be.rejectedWith('BadOrigin');390 });391392 itSub('[Negative] Council cannot cancel Fellowship referendums', async ({helper}) => {393 const fellowship = await initFellowship(donor, sudoer);394 const fellowshipProposer = fellowship[5][0];395 const proposal = dummyProposal(helper);396397 const submitResult = await helper.fellowship.referenda.submit(398 fellowshipProposer,399 fellowshipPropositionOrigin,400 proposal,401 defaultEnactmentMoment,402 );403404 const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;405406 await expect(proposalFromAllCouncil(helper.fellowship.referenda.cancelCall(referendumIndex)))407 .to.be.rejectedWith(/BadOrigin/);408 });409410 itSub('[Negative] Council member cannot cancel Fellowship referendums', async ({helper}) => {411 const fellowship = await initFellowship(donor, sudoer);412 const fellowshipProposer = fellowship[5][0];413 const proposal = dummyProposal(helper);414415 const submitResult = await helper.fellowship.referenda.submit(416 fellowshipProposer,417 fellowshipPropositionOrigin,418 proposal,419 defaultEnactmentMoment,420 );421 const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;422 await expect(helper.council.collective.execute(423 counselors.alex,424 helper.fellowship.referenda.cancelCall(referendumIndex),425 )).to.be.rejectedWith('BadOrigin');426 });427428 itSub('[Negative] Council referendum cannot be closed until the voting threshold is met', async ({helper}) => {429 const councilSize = (await helper.callRpc('api.query.councilMembership.members')).toJSON().length as any as number;430 expect(councilSize).is.greaterThan(1);431 const proposeResult = await helper.council.collective.propose(432 counselors.filip,433 dummyProposalCall(helper),434 councilSize,435 );436437 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);438 const proposalIndex = councilProposedEvent.proposalIndex;439 const proposalHash = councilProposedEvent.proposalHash;440441442 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);443 await expect(helper.council.collective.close(counselors.filip, proposalHash, proposalIndex)).to.be.rejectedWith('TooEarly');444 });445446});12import {IKeyringPair} from '@polkadot/types/types';3import {usingPlaygrounds, itSub, expect, Pallets, requirePalletsOrSkip, describeGov} from '../util';4import {Event} from '../util/playgrounds/unique.dev';5import {ICounselors, initCouncil, democracyLaunchPeriod, democracyVotingPeriod, democracyEnactmentPeriod, councilMotionDuration, democracyFastTrackVotingPeriod, fellowshipRankLimit, clearCouncil, clearTechComm, initTechComm, clearFellowship, dummyProposal, dummyProposalCall, initFellowship, defaultEnactmentMoment, fellowshipPropositionOrigin} from './util';67describeGov('Governance: Council tests', () => {8 let donor: IKeyringPair;9 let counselors: ICounselors;10 let sudoer: IKeyringPair;1112 const moreThanHalfCouncilThreshold = 3;1314 before(async function() {15 await usingPlaygrounds(async (helper, privateKey) => {16 requirePalletsOrSkip(this, helper, [Pallets.Council]);1718 donor = await privateKey({url: import.meta.url});19 sudoer = await privateKey('//Alice');20 });21 });2223 beforeEach(async () => {24 counselors = await initCouncil(donor, sudoer);25 });2627 afterEach(async () => {28 await clearCouncil(sudoer);29 await clearTechComm(sudoer);30 });3132 async function proposalFromMoreThanHalfCouncil(proposal: any) {33 return await usingPlaygrounds(async (helper) => {34 expect((await helper.callRpc('api.query.councilMembership.members')).toJSON().length).to.be.equal(5);35 const proposeResult = await helper.council.collective.propose(36 counselors.filip,37 proposal,38 moreThanHalfCouncilThreshold,39 );4041 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);42 const proposalIndex = councilProposedEvent.proposalIndex;43 const proposalHash = councilProposedEvent.proposalHash;444546 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);47 await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);48 await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);4950 return await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);51 });52 }5354 async function proposalFromAllCouncil(proposal: any) {55 return await usingPlaygrounds(async (helper) => {56 expect((await helper.callRpc('api.query.councilMembership.members')).toJSON().length).to.be.equal(5);57 const proposeResult = await helper.council.collective.propose(58 counselors.filip,59 proposal,60 moreThanHalfCouncilThreshold,61 );6263 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);64 const proposalIndex = councilProposedEvent.proposalIndex;65 const proposalHash = councilProposedEvent.proposalHash;666768 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);69 await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);70 await helper.council.collective.vote(counselors.ildar, proposalHash, proposalIndex, true);71 await helper.council.collective.vote(counselors.irina, proposalHash, proposalIndex, true);72 await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);7374 return await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);75 });76 }7778 itSub('>50% of Council can externally propose SuperMajorityAgainst', async ({helper}) => {79 const forceSetBalanceReceiver = helper.arrange.createEmptyAccount();80 const forceSetBalanceTestValue = 20n * 10n ** 25n;8182 const democracyProposal = await helper.constructApiCall('api.tx.balances.forceSetBalance', [83 forceSetBalanceReceiver.address, forceSetBalanceTestValue,84 ]);8586 const councilProposal = await helper.democracy.externalProposeDefaultCall(democracyProposal);8788 const proposeResult = await helper.council.collective.propose(89 counselors.filip,90 councilProposal,91 moreThanHalfCouncilThreshold,92 );9394 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);95 const proposalIndex = councilProposedEvent.proposalIndex;96 const proposalHash = councilProposedEvent.proposalHash;9798 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);99 await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);100 await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);101102 await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);103104 const democracyStartedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);105 const democracyReferendumIndex = democracyStartedEvent.referendumIndex;106 const democracyThreshold = democracyStartedEvent.threshold;107108 expect(democracyThreshold).to.be.equal('SuperMajorityAgainst');109110 await helper.democracy.vote(counselors.filip, democracyReferendumIndex, {111 Standard: {112 vote: {113 aye: true,114 conviction: 1,115 },116 balance: 10_000n,117 },118 });119120 await helper.democracy.vote(counselors.charu, democracyReferendumIndex, {121 Standard: {122 vote: {123 aye: false,124 conviction: 1,125 },126 balance: 50_000n,127 },128 });129130 const passedReferendumEvent = await helper.wait.expectEvent(democracyVotingPeriod, Event.Democracy.Passed);131 expect(passedReferendumEvent.referendumIndex).to.be.equal(democracyReferendumIndex);132133 await helper.wait.expectEvent(democracyEnactmentPeriod, Event.Scheduler.Dispatched);134 const receiverBalance = await helper.balance.getSubstrate(forceSetBalanceReceiver.address);135 expect(receiverBalance).to.be.equal(forceSetBalanceTestValue);136 });137138 itSub('Council prime member vote is the default', async ({helper}) => {139 const newTechCommMember = helper.arrange.createEmptyAccount();140 const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address);141 const proposeResult = await helper.council.collective.propose(142 counselors.filip,143 addMemberProposal,144 moreThanHalfCouncilThreshold,145 );146147 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);148 const proposalIndex = councilProposedEvent.proposalIndex;149 const proposalHash = councilProposedEvent.proposalHash;150151 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);152153 await helper.wait.newBlocks(councilMotionDuration);154 const closeResult = await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);155 const closeEvent = Event.Council.Closed.expect(closeResult);156 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON() as string[];157 expect(closeEvent.yes).to.be.equal(members.length);158 });159160 itSub('Superuser can add a member', async ({helper}) => {161 const newMember = helper.arrange.createEmptyAccount();162 await expect(helper.getSudo().council.membership.addMember(sudoer, newMember.address)).to.be.fulfilled;163164 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();165 expect(members).to.contains(newMember.address);166 });167168 itSub('Superuser can remove a member', async ({helper}) => {169 await expect(helper.getSudo().council.membership.removeMember(sudoer, counselors.alex.address)).to.be.fulfilled;170171 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();172 expect(members).to.not.contains(counselors.alex.address);173 });174175 itSub('>50% Council can add TechComm member', async ({helper}) => {176 const newTechCommMember = helper.arrange.createEmptyAccount();177 const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address);178179 await proposalFromMoreThanHalfCouncil(addMemberProposal);180181 const techCommMembers = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();182 expect(techCommMembers).to.contains(newTechCommMember.address);183 });184185 itSub('Council can remove TechComm member', async ({helper}) => {186 const techComm = await initTechComm(donor, sudoer);187 const removeMemberPrpoposal = helper.technicalCommittee.membership.removeMemberCall(techComm.andy.address);188 await proposalFromMoreThanHalfCouncil(removeMemberPrpoposal);189190 const techCommMembers = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();191 expect(techCommMembers).to.not.contains(techComm.andy.address);192 });193194 itSub.skip('Council member can add Fellowship member', async ({helper}) => {195 const newFellowshipMember = helper.arrange.createEmptyAccount();196 await expect(helper.council.collective.execute(197 counselors.alex,198 helper.fellowship.collective.addMemberCall(newFellowshipMember.address),199 )).to.be.fulfilled;200 const fellowshipMembers = (await helper.callRpc('api.query.fellowshipCollective.members')).toJSON();201 expect(fellowshipMembers).to.contains(newFellowshipMember.address);202 });203204 itSub('>50% Council can promote Fellowship member', async ({helper}) => {205 const fellowship = await initFellowship(donor, sudoer);206 const memberWithZeroRank = fellowship[0][0];207208 const proposal = helper.fellowship.collective.promoteCall(memberWithZeroRank.address);209 await proposalFromMoreThanHalfCouncil(proposal);210 const record = (await helper.callRpc('api.query.fellowshipCollective.members', [memberWithZeroRank.address])).toJSON();211 expect(record).to.be.deep.equal({rank: 1});212213 await clearFellowship(sudoer);214 });215216 itSub('>50% Council can demote Fellowship member', async ({helper}) => {217 const fellowship = await initFellowship(donor, sudoer);218 const memberWithRankOne = fellowship[1][0];219220 const proposal = helper.fellowship.collective.demoteCall(memberWithRankOne.address);221 await proposalFromMoreThanHalfCouncil(proposal);222223 const record = (await helper.callRpc('api.query.fellowshipCollective.members', [memberWithRankOne.address])).toJSON();224 expect(record).to.be.deep.equal({rank: 0});225226 await clearFellowship(sudoer);227 });228229 itSub('>50% Council can add\remove Fellowship member', async ({helper}) => {230 try {231 const newMember = helper.arrange.createEmptyAccount();232233 const proposalAdd = helper.fellowship.collective.addMemberCall(newMember.address);234 const proposalRemove = helper.fellowship.collective.removeMemberCall(newMember.address, fellowshipRankLimit);235 await expect(proposalFromMoreThanHalfCouncil(proposalAdd)).to.be.fulfilled;236 expect(await helper.fellowship.collective.getMembers()).to.be.deep.contain(newMember.address);237 await expect(proposalFromMoreThanHalfCouncil(proposalRemove)).to.be.fulfilled;238 expect(await helper.fellowship.collective.getMembers()).to.be.not.deep.contain(newMember.address);239 }240 finally {241 await clearFellowship(sudoer);242 }243 });244245 itSub('Council can blacklist Democracy proposals', async ({helper}) => {246 const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);247 await expect(proposalFromAllCouncil(helper.democracy.blacklistCall(preimageHash, null))).to.be.fulfilled;248 });249250 itSub('Sudo can blacklist Democracy proposals', async ({helper}) => {251 const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);252 await expect(helper.getSudo().democracy.blacklist(sudoer, preimageHash)).to.be.fulfilled;253 });254255 itSub('[Negative] Council cannot add Council member', async ({helper}) => {256 const newCouncilMember = helper.arrange.createEmptyAccount();257 const addMemberProposal = helper.council.membership.addMemberCall(newCouncilMember.address);258259 await expect(proposalFromAllCouncil(addMemberProposal)).to.be.rejected;260 });261262 itSub('[Negative] Council cannot remove Council member', async ({helper}) => {263 const removeMemberProposal = helper.council.membership.removeMemberCall(counselors.alex.address);264265 await expect(proposalFromAllCouncil(removeMemberProposal)).to.be.rejected;266 });267268 itSub('[Negative] Council cannot submit regular democracy proposal', async ({helper}) => {269 const councilProposal = await helper.democracy.proposeCall(dummyProposalCall(helper), 0n);270271 await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);272 });273274 itSub('[Negative] Council cannot externally propose SimpleMajority', async ({helper}) => {275 const councilProposal = await helper.democracy.externalProposeMajorityCall(dummyProposalCall(helper));276277 await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);278 });279280 itSub('[Negative] Council cannot externally propose SuperMajorityApprove', async ({helper}) => {281 const councilProposal = await helper.democracy.externalProposeCall(dummyProposalCall(helper));282283 await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);284 });285286 itSub('[Negative] Council member cannot add/remove a Council member', async ({helper}) => {287 const newCouncilMember = helper.arrange.createEmptyAccount();288 await expect(helper.council.collective.execute(289 counselors.alex,290 helper.council.membership.addMemberCall(newCouncilMember.address),291 )).to.be.rejectedWith('BadOrigin');292 await expect(helper.council.collective.execute(293 counselors.alex,294 helper.council.membership.removeMemberCall(counselors.charu.address),295 )).to.be.rejectedWith('BadOrigin');296 });297298 itSub('[Negative] Council cannot set/clear Council prime member', async ({helper}) => {299 const proposalForSet = await helper.council.membership.setPrimeCall(counselors.charu.address);300 const proposalForClear = await helper.council.membership.clearPrimeCall();301302 await expect(proposalFromAllCouncil(proposalForSet)).to.be.rejectedWith(/BadOrigin/);303 await expect(proposalFromAllCouncil(proposalForClear)).to.be.rejectedWith(/BadOrigin/);304305 });306307 itSub('[Negative] Council member cannot set/clear Council prime member', async ({helper}) => {308 await expect(helper.council.collective.execute(309 counselors.alex,310 helper.council.membership.setPrimeCall(counselors.charu.address),311 )).to.be.rejectedWith('BadOrigin');312 await expect(helper.council.collective.execute(313 counselors.alex,314 helper.council.membership.clearPrimeCall(),315 )).to.be.rejectedWith('BadOrigin');316 });317318 itSub('[Negative] Council member cannot add/remove a TechComm member', async ({helper}) => {319 const newTechCommMember = helper.arrange.createEmptyAccount();320 await expect(helper.council.collective.execute(321 counselors.alex,322 helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address),323 )).to.be.rejectedWith('BadOrigin');324 await expect(helper.council.collective.execute(325 counselors.alex,326 helper.technicalCommittee.membership.removeMemberCall(newTechCommMember.address),327 )).to.be.rejectedWith('BadOrigin');328 });329330 itSub('[Negative] Council member cannot promote/demote a Fellowship member', async ({helper}) => {331 const fellowship = await initFellowship(donor, sudoer);332 const memberWithRankOne = fellowship[1][0];333334 await expect(helper.council.collective.execute(335 counselors.alex,336 helper.fellowship.collective.promoteCall(memberWithRankOne.address),337 )).to.be.rejectedWith('BadOrigin');338 await expect(helper.council.collective.execute(339 counselors.alex,340 helper.fellowship.collective.demoteCall(memberWithRankOne.address),341 )).to.be.rejectedWith('BadOrigin');342 await clearFellowship(sudoer);343 });344345 itSub('[Negative] Council cannot fast-track Democracy proposals', async ({helper}) => {346 const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);347 await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);348349 await expect(proposalFromAllCouncil(helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0)))350 .to.be.rejectedWith(/BadOrigin/);351 });352353 itSub('[Negative] Council member cannot fast-track Democracy proposals', async ({helper}) => {354 const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);355 await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);356357 await expect(helper.council.collective.execute(358 counselors.alex,359 helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0),360 )).to.be.rejectedWith('BadOrigin');361 });362363 itSub('[Negative] Council cannot cancel Democracy proposals', async ({helper}) => {364 const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);365 const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;366367 await expect(proposalFromAllCouncil(helper.democracy.cancelProposalCall(proposalIndex)))368 .to.be.rejectedWith(/BadOrigin/);369 });370371 itSub('[Negative] Council member cannot cancel Democracy proposals', async ({helper}) => {372373 const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);374 const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;375376 await expect(helper.council.collective.execute(377 counselors.alex,378 helper.democracy.cancelProposalCall(proposalIndex),379 )).to.be.rejectedWith('BadOrigin');380 });381382 itSub('[Negative] Council cannot cancel ongoing Democracy referendums', async ({helper}) => {383 await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));384 const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);385 const referendumIndex = startedEvent.referendumIndex;386387 await expect(proposalFromAllCouncil(helper.democracy.emergencyCancelCall(referendumIndex)))388 .to.be.rejectedWith(/BadOrigin/);389 });390391 itSub('[Negative] Council member cannot cancel ongoing Democracy referendums', async ({helper}) => {392 await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));393 const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);394 const referendumIndex = startedEvent.referendumIndex;395396 await expect(helper.council.collective.execute(397 counselors.alex,398 helper.democracy.emergencyCancelCall(referendumIndex),399 )).to.be.rejectedWith('BadOrigin');400 });401402 itSub('[Negative] Council cannot cancel Fellowship referendums', async ({helper}) => {403 const fellowship = await initFellowship(donor, sudoer);404 const fellowshipProposer = fellowship[5][0];405 const proposal = dummyProposal(helper);406407 const submitResult = await helper.fellowship.referenda.submit(408 fellowshipProposer,409 fellowshipPropositionOrigin,410 proposal,411 defaultEnactmentMoment,412 );413414 const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;415416 await expect(proposalFromAllCouncil(helper.fellowship.referenda.cancelCall(referendumIndex)))417 .to.be.rejectedWith(/BadOrigin/);418 });419420 itSub('[Negative] Council member cannot cancel Fellowship referendums', async ({helper}) => {421 const fellowship = await initFellowship(donor, sudoer);422 const fellowshipProposer = fellowship[5][0];423 const proposal = dummyProposal(helper);424425 const submitResult = await helper.fellowship.referenda.submit(426 fellowshipProposer,427 fellowshipPropositionOrigin,428 proposal,429 defaultEnactmentMoment,430 );431 const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;432 await expect(helper.council.collective.execute(433 counselors.alex,434 helper.fellowship.referenda.cancelCall(referendumIndex),435 )).to.be.rejectedWith('BadOrigin');436 });437438 itSub('[Negative] Council referendum cannot be closed until the voting threshold is met', async ({helper}) => {439 const councilSize = (await helper.callRpc('api.query.councilMembership.members')).toJSON().length as any as number;440 expect(councilSize).is.greaterThan(1);441 const proposeResult = await helper.council.collective.propose(442 counselors.filip,443 dummyProposalCall(helper),444 councilSize,445 );446447 const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);448 const proposalIndex = councilProposedEvent.proposalIndex;449 const proposalHash = councilProposedEvent.proposalHash;450451452 await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);453 await expect(helper.council.collective.close(counselors.filip, proposalHash, proposalIndex)).to.be.rejectedWith('TooEarly');454 });455456});