git.delta.rocks / unique-network / refs/commits / 5da2ac33955b

difftreelog

fix(tests) update test cases and resolve review comments

Maksandre2024-06-05parent: #ed0719f.patch.diff
in: master

2 files changed

modifiedjs-packages/tests/sub/governance/council.test.tsdiffbeforeafterboth
before · js-packages/tests/sub/governance/council.test.ts
12import type {IKeyringPair} from '@polkadot/types/types';3import {usingPlaygrounds, itSub, expect, Pallets, requirePalletsOrSkip, describeGov} from '@unique/test-utils/util.js';4import {Event} from '@unique/test-utils';5import {initCouncil, democracyLaunchPeriod, democracyVotingPeriod, democracyEnactmentPeriod, councilMotionDuration, democracyFastTrackVotingPeriod, fellowshipRankLimit, clearCouncil, clearTechComm, initTechComm, clearFellowship, dummyProposal, dummyProposalCall, initFellowship, defaultEnactmentMoment, fellowshipPropositionOrigin, initFinCouncil} from './util.js';6import type {ICounselors} from './util.js';78describeGov('Governance: Council tests', () => {9  let donor: IKeyringPair;10  let counselors: ICounselors;11  let sudoer: IKeyringPair;1213  const moreThanHalfCouncilThreshold = 3;1415  before(async function() {16    await usingPlaygrounds(async (helper, privateKey) => {17      requirePalletsOrSkip(this, helper, [Pallets.Council]);1819      donor = await privateKey({url: import.meta.url});20      sudoer = await privateKey('//Alice');21    });22  });2324  beforeEach(async () => {25    counselors = await initCouncil(donor, sudoer);26  });2728  afterEach(async () => {29    await clearCouncil(sudoer);30    await clearTechComm(sudoer);31  });3233  async function proposalFromMoreThanHalfCouncil(proposal: any) {34    return await usingPlaygrounds(async (helper) => {35      expect((await helper.callRpc('api.query.councilMembership.members')).toJSON().length).to.be.equal(5);36      const proposeResult = await helper.council.collective.propose(37        counselors.filip,38        proposal,39        moreThanHalfCouncilThreshold,40      );4142      const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);43      const proposalIndex = councilProposedEvent.proposalIndex;44      const proposalHash = councilProposedEvent.proposalHash;454647      await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);48      await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);49      await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);5051      return await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);52    });53  }5455  async function proposalFromAllCouncil(proposal: any) {56    return await usingPlaygrounds(async (helper) => {57      expect((await helper.callRpc('api.query.councilMembership.members')).toJSON().length).to.be.equal(5);58      const proposeResult = await helper.council.collective.propose(59        counselors.filip,60        proposal,61        moreThanHalfCouncilThreshold,62      );6364      const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);65      const proposalIndex = councilProposedEvent.proposalIndex;66      const proposalHash = councilProposedEvent.proposalHash;676869      await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);70      await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);71      await helper.council.collective.vote(counselors.ildar, proposalHash, proposalIndex, true);72      await helper.council.collective.vote(counselors.irina, proposalHash, proposalIndex, true);73      await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);7475      return await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);76    });77  }7879  itSub('>50% of Council can externally propose SuperMajorityAgainst', async ({helper}) => {80    const forceSetBalanceReceiver = helper.arrange.createEmptyAccount();81    const forceSetBalanceTestValue = 20n * 10n ** 25n;8283    const democracyProposal = await helper.constructApiCall('api.tx.balances.forceSetBalance', [84      forceSetBalanceReceiver.address, forceSetBalanceTestValue,85    ]);8687    const councilProposal = await helper.democracy.externalProposeDefaultCall(democracyProposal);8889    const proposeResult = await helper.council.collective.propose(90      counselors.filip,91      councilProposal,92      moreThanHalfCouncilThreshold,93    );9495    const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);96    const proposalIndex = councilProposedEvent.proposalIndex;97    const proposalHash = councilProposedEvent.proposalHash;9899    await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);100    await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);101    await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);102103    await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);104105    const democracyStartedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);106    const democracyReferendumIndex = democracyStartedEvent.referendumIndex;107    const democracyThreshold = democracyStartedEvent.threshold;108109    expect(democracyThreshold).to.be.equal('SuperMajorityAgainst');110111    await helper.democracy.vote(counselors.filip, democracyReferendumIndex, {112      Standard: {113        vote: {114          aye: true,115          conviction: 1,116        },117        balance: 10_000n,118      },119    });120121    await helper.democracy.vote(counselors.charu, democracyReferendumIndex, {122      Standard: {123        vote: {124          aye: false,125          conviction: 1,126        },127        balance: 50_000n,128      },129    });130131    const passedReferendumEvent = await helper.wait.expectEvent(democracyVotingPeriod, Event.Democracy.Passed);132    expect(passedReferendumEvent.referendumIndex).to.be.equal(democracyReferendumIndex);133134    await helper.wait.expectEvent(democracyEnactmentPeriod, Event.Scheduler.Dispatched);135    const receiverBalance = await helper.balance.getSubstrate(forceSetBalanceReceiver.address);136    expect(receiverBalance).to.be.equal(forceSetBalanceTestValue);137  });138139  itSub('Council prime member vote is the default', async ({helper}) => {140    const newTechCommMember = helper.arrange.createEmptyAccount();141    const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address);142    const proposeResult = await helper.council.collective.propose(143      counselors.filip,144      addMemberProposal,145      moreThanHalfCouncilThreshold,146    );147148    const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);149    const proposalIndex = councilProposedEvent.proposalIndex;150    const proposalHash = councilProposedEvent.proposalHash;151152    await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);153154    await helper.wait.newBlocks(councilMotionDuration);155    const closeResult = await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);156    const closeEvent = Event.Council.Closed.expect(closeResult);157    const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON() as string[];158    expect(closeEvent.yes).to.be.equal(members.length);159  });160161  itSub('Superuser can add a member', async ({helper}) => {162    const newMember = helper.arrange.createEmptyAccount();163    await expect(helper.getSudo().council.membership.addMember(sudoer, newMember.address)).to.be.fulfilled;164165    const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();166    expect(members).to.contains(newMember.address);167  });168169  itSub('Superuser can remove a member', async ({helper}) => {170    await expect(helper.getSudo().council.membership.removeMember(sudoer, counselors.alex.address)).to.be.fulfilled;171172    const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();173    expect(members).to.not.contains(counselors.alex.address);174  });175176  itSub('>50% Council can add TechComm member', async ({helper}) => {177    const newTechCommMember = helper.arrange.createEmptyAccount();178    const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address);179180    await proposalFromMoreThanHalfCouncil(addMemberProposal);181182    const techCommMembers = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();183    expect(techCommMembers).to.contains(newTechCommMember.address);184  });185186  itSub('Council can remove TechComm member', async ({helper}) => {187    const techComm = await initTechComm(donor, sudoer);188    const removeMemberPrpoposal = helper.technicalCommittee.membership.removeMemberCall(techComm.andy.address);189    await proposalFromMoreThanHalfCouncil(removeMemberPrpoposal);190191    const techCommMembers = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();192    expect(techCommMembers).to.not.contains(techComm.andy.address);193  });194195  itSub('Council can remove FinCouncil member', async ({helper}) => {196    const finCouncil = await initFinCouncil(donor, sudoer);197    const removeMemberPrpoposal = helper.finCouncil.membership.removeMemberCall(finCouncil.andy.address);198    await proposalFromMoreThanHalfCouncil(removeMemberPrpoposal);199200    const finCouncilMembers = await helper.finCouncil.membership.getMembers();201    expect(finCouncilMembers).to.not.contains(finCouncil.andy.address);202  });203204  itSub('Council can add FinCouncil member', async ({helper}) => {205    await initFinCouncil(donor, sudoer);206    const newFinCouncilMember = helper.arrange.createEmptyAccount();207    const addMemberPrpoposal = helper.finCouncil.membership.addMemberCall(newFinCouncilMember.address);208    await proposalFromMoreThanHalfCouncil(addMemberPrpoposal);209210    const finCouncilMembers = await helper.finCouncil.membership.getMembers();211    expect(finCouncilMembers).to.contains(newFinCouncilMember.address);212  });213214  itSub.skip('Council member can add Fellowship member', async ({helper}) => {215    const newFellowshipMember = helper.arrange.createEmptyAccount();216    await expect(helper.council.collective.execute(217      counselors.alex,218      helper.fellowship.collective.addMemberCall(newFellowshipMember.address),219    )).to.be.fulfilled;220    const fellowshipMembers = (await helper.callRpc('api.query.fellowshipCollective.members')).toJSON();221    expect(fellowshipMembers).to.contains(newFellowshipMember.address);222  });223224  itSub('>50% Council can promote Fellowship member', async ({helper}) => {225    const fellowship = await initFellowship(donor, sudoer);226    const memberWithZeroRank = fellowship[0][0];227228    const proposal = helper.fellowship.collective.promoteCall(memberWithZeroRank.address);229    await proposalFromMoreThanHalfCouncil(proposal);230    const record = (await helper.callRpc('api.query.fellowshipCollective.members', [memberWithZeroRank.address])).toJSON();231    expect(record).to.be.deep.equal({rank: 1});232233    await clearFellowship(sudoer);234  });235236  itSub('>50% Council can demote Fellowship member', async ({helper}) => {237    const fellowship = await initFellowship(donor, sudoer);238    const memberWithRankOne = fellowship[1][0];239240    const proposal = helper.fellowship.collective.demoteCall(memberWithRankOne.address);241    await proposalFromMoreThanHalfCouncil(proposal);242243    const record = (await helper.callRpc('api.query.fellowshipCollective.members', [memberWithRankOne.address])).toJSON();244    expect(record).to.be.deep.equal({rank: 0});245246    await clearFellowship(sudoer);247  });248249  itSub('>50% Council can add\remove Fellowship member', async ({helper}) => {250    try {251      const newMember = helper.arrange.createEmptyAccount();252253      const proposalAdd = helper.fellowship.collective.addMemberCall(newMember.address);254      const proposalRemove = helper.fellowship.collective.removeMemberCall(newMember.address, fellowshipRankLimit);255      await expect(proposalFromMoreThanHalfCouncil(proposalAdd)).to.be.fulfilled;256      expect(await helper.fellowship.collective.getMembers()).to.be.deep.contain(newMember.address);257      await expect(proposalFromMoreThanHalfCouncil(proposalRemove)).to.be.fulfilled;258      expect(await helper.fellowship.collective.getMembers()).to.be.not.deep.contain(newMember.address);259    }260    finally {261      await clearFellowship(sudoer);262    }263  });264265  itSub('Council can blacklist Democracy proposals', async ({helper}) => {266    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);267    await expect(proposalFromAllCouncil(helper.democracy.blacklistCall(preimageHash, null))).to.be.fulfilled;268  });269270  itSub('Sudo can blacklist Democracy proposals', async ({helper}) => {271    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);272    await expect(helper.getSudo().democracy.blacklist(sudoer, preimageHash)).to.be.fulfilled;273  });274275  itSub('[Negative] Council cannot add Council member', async ({helper}) => {276    const newCouncilMember = helper.arrange.createEmptyAccount();277    const addMemberProposal = helper.council.membership.addMemberCall(newCouncilMember.address);278279    await expect(proposalFromAllCouncil(addMemberProposal)).to.be.rejected;280  });281282  itSub('[Negative] Council cannot remove Council member', async ({helper}) => {283    const removeMemberProposal = helper.council.membership.removeMemberCall(counselors.alex.address);284285    await expect(proposalFromAllCouncil(removeMemberProposal)).to.be.rejected;286  });287288  itSub('[Negative] Council cannot submit regular democracy proposal', async ({helper}) => {289    const councilProposal = await helper.democracy.proposeCall(dummyProposalCall(helper), 0n);290291    await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);292  });293294  itSub('[Negative] Council cannot externally propose SimpleMajority', async ({helper}) => {295    const councilProposal = await helper.democracy.externalProposeMajorityCall(dummyProposalCall(helper));296297    await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);298  });299300  itSub('[Negative] Council cannot externally propose SuperMajorityApprove', async ({helper}) => {301    const councilProposal = await helper.democracy.externalProposeCall(dummyProposalCall(helper));302303    await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);304  });305306  itSub('[Negative] Council member cannot add/remove a Council member', async ({helper}) => {307    const newCouncilMember = helper.arrange.createEmptyAccount();308    await expect(helper.council.collective.execute(309      counselors.alex,310      helper.council.membership.addMemberCall(newCouncilMember.address),311    )).to.be.rejectedWith('BadOrigin');312    await expect(helper.council.collective.execute(313      counselors.alex,314      helper.council.membership.removeMemberCall(counselors.charu.address),315    )).to.be.rejectedWith('BadOrigin');316  });317318  itSub('[Negative] Council cannot set/clear Council prime member', async ({helper}) => {319    const proposalForSet = await helper.council.membership.setPrimeCall(counselors.charu.address);320    const proposalForClear = await helper.council.membership.clearPrimeCall();321322    await expect(proposalFromAllCouncil(proposalForSet)).to.be.rejectedWith(/BadOrigin/);323    await expect(proposalFromAllCouncil(proposalForClear)).to.be.rejectedWith(/BadOrigin/);324325  });326327  itSub('[Negative] Council member cannot set/clear Council prime member', async ({helper}) => {328    await expect(helper.council.collective.execute(329      counselors.alex,330      helper.council.membership.setPrimeCall(counselors.charu.address),331    )).to.be.rejectedWith('BadOrigin');332    await expect(helper.council.collective.execute(333      counselors.alex,334      helper.council.membership.clearPrimeCall(),335    )).to.be.rejectedWith('BadOrigin');336  });337338  itSub('[Negative] Council member cannot add/remove a TechComm member', async ({helper}) => {339    const newTechCommMember = helper.arrange.createEmptyAccount();340    await expect(helper.council.collective.execute(341      counselors.alex,342      helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address),343    )).to.be.rejectedWith('BadOrigin');344    await expect(helper.council.collective.execute(345      counselors.alex,346      helper.technicalCommittee.membership.removeMemberCall(newTechCommMember.address),347    )).to.be.rejectedWith('BadOrigin');348  });349350  itSub('[Negative] Council member can\'t add FinCouncil member', async ({helper}) => {351    const newFinCouncilMember = helper.arrange.createEmptyAccount();352    await expect(helper.council.collective.execute(353      counselors.alex,354      helper.finCouncil.membership.addMemberCall(newFinCouncilMember.address),355    )).rejectedWith('BadOrigin');356  });357358  itSub('[Negative] Council member can\'t remove FinCouncil member', async ({helper}) => {359    const finCouncil = await initFinCouncil(donor, sudoer);360    await expect(helper.council.collective.execute(361      counselors.alex,362      helper.finCouncil.membership.removeMemberCall(finCouncil.ildar.address),363    )).rejectedWith('BadOrigin');364  });365366  itSub('[Negative] Council member cannot promote/demote a Fellowship member', async ({helper}) => {367    const fellowship = await initFellowship(donor, sudoer);368    const memberWithRankOne = fellowship[1][0];369370    await expect(helper.council.collective.execute(371      counselors.alex,372      helper.fellowship.collective.promoteCall(memberWithRankOne.address),373    )).to.be.rejectedWith('BadOrigin');374    await expect(helper.council.collective.execute(375      counselors.alex,376      helper.fellowship.collective.demoteCall(memberWithRankOne.address),377    )).to.be.rejectedWith('BadOrigin');378    await clearFellowship(sudoer);379  });380381  itSub('[Negative] Council cannot fast-track Democracy proposals', async ({helper}) => {382    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);383    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);384385    await expect(proposalFromAllCouncil(helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0)))386      .to.be.rejectedWith(/BadOrigin/);387  });388389  itSub('[Negative] Council member cannot fast-track Democracy proposals', async ({helper}) => {390    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);391    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);392393    await expect(helper.council.collective.execute(394      counselors.alex,395      helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0),396    )).to.be.rejectedWith('BadOrigin');397  });398399  itSub('[Negative] Council cannot cancel Democracy proposals', async ({helper}) => {400    const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);401    const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;402403    await expect(proposalFromAllCouncil(helper.democracy.cancelProposalCall(proposalIndex)))404      .to.be.rejectedWith(/BadOrigin/);405  });406407  itSub('[Negative] Council member cannot cancel Democracy proposals', async ({helper}) => {408409    const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);410    const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;411412    await expect(helper.council.collective.execute(413      counselors.alex,414      helper.democracy.cancelProposalCall(proposalIndex),415    )).to.be.rejectedWith('BadOrigin');416  });417418  itSub('[Negative] Council cannot cancel ongoing Democracy referendums', async ({helper}) => {419    await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));420    const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);421    const referendumIndex = startedEvent.referendumIndex;422423    await expect(proposalFromAllCouncil(helper.democracy.emergencyCancelCall(referendumIndex)))424      .to.be.rejectedWith(/BadOrigin/);425  });426427  itSub('[Negative] Council member cannot cancel ongoing Democracy referendums', async ({helper}) => {428    await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));429    const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);430    const referendumIndex = startedEvent.referendumIndex;431432    await expect(helper.council.collective.execute(433      counselors.alex,434      helper.democracy.emergencyCancelCall(referendumIndex),435    )).to.be.rejectedWith('BadOrigin');436  });437438  itSub('[Negative] Council cannot cancel Fellowship referendums', async ({helper}) => {439    const fellowship = await initFellowship(donor, sudoer);440    const fellowshipProposer = fellowship[5][0];441    const proposal = dummyProposal(helper);442443    const submitResult = await helper.fellowship.referenda.submit(444      fellowshipProposer,445      fellowshipPropositionOrigin,446      proposal,447      defaultEnactmentMoment,448    );449450    const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;451452    await expect(proposalFromAllCouncil(helper.fellowship.referenda.cancelCall(referendumIndex)))453      .to.be.rejectedWith(/BadOrigin/);454  });455456  itSub('[Negative] Council member cannot cancel Fellowship referendums', async ({helper}) => {457    const fellowship = await initFellowship(donor, sudoer);458    const fellowshipProposer = fellowship[5][0];459    const proposal = dummyProposal(helper);460461    const submitResult = await helper.fellowship.referenda.submit(462      fellowshipProposer,463      fellowshipPropositionOrigin,464      proposal,465      defaultEnactmentMoment,466    );467    const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;468    await expect(helper.council.collective.execute(469      counselors.alex,470      helper.fellowship.referenda.cancelCall(referendumIndex),471    )).to.be.rejectedWith('BadOrigin');472  });473474  itSub('[Negative] Council referendum cannot be closed until the voting threshold is met', async ({helper}) => {475    const councilSize = (await helper.callRpc('api.query.councilMembership.members')).toJSON().length as any as number;476    expect(councilSize).is.greaterThan(1);477    const proposeResult = await helper.council.collective.propose(478      counselors.filip,479      dummyProposalCall(helper),480      councilSize,481    );482483    const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);484    const proposalIndex = councilProposedEvent.proposalIndex;485    const proposalHash = councilProposedEvent.proposalHash;486487488    await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);489    await expect(helper.council.collective.close(counselors.filip, proposalHash, proposalIndex)).to.be.rejectedWith('TooEarly');490  });491492});
after · js-packages/tests/sub/governance/council.test.ts
12import type {IKeyringPair} from '@polkadot/types/types';3import {usingPlaygrounds, itSub, expect, Pallets, requirePalletsOrSkip, describeGov} from '@unique/test-utils/util.js';4import {Event} from '@unique/test-utils';5import {initCouncil, democracyLaunchPeriod, democracyVotingPeriod, democracyEnactmentPeriod, councilMotionDuration, democracyFastTrackVotingPeriod, fellowshipRankLimit, clearCouncil, clearTechComm, initTechComm, clearFellowship, dummyProposal, dummyProposalCall, initFellowship, defaultEnactmentMoment, fellowshipPropositionOrigin, initFinCouncil} from './util.js';6import type {ICounselors} from './util.js';78describeGov('Governance: Council tests', () => {9  let donor: IKeyringPair;10  let counselors: ICounselors;11  let sudoer: IKeyringPair;1213  const moreThanHalfCouncilThreshold = 3;1415  before(async function() {16    await usingPlaygrounds(async (helper, privateKey) => {17      requirePalletsOrSkip(this, helper, [Pallets.Council]);1819      donor = await privateKey({url: import.meta.url});20      sudoer = await privateKey('//Alice');21    });22  });2324  beforeEach(async () => {25    counselors = await initCouncil(donor, sudoer);26  });2728  afterEach(async () => {29    await clearCouncil(sudoer);30    await clearTechComm(sudoer);31  });3233  async function proposalFromMoreThanHalfCouncil(proposal: any) {34    return await usingPlaygrounds(async (helper) => {35      expect((await helper.callRpc('api.query.councilMembership.members')).toJSON().length).to.be.equal(5);36      const proposeResult = await helper.council.collective.propose(37        counselors.filip,38        proposal,39        moreThanHalfCouncilThreshold,40      );4142      const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);43      const proposalIndex = councilProposedEvent.proposalIndex;44      const proposalHash = councilProposedEvent.proposalHash;454647      await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);48      await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);49      await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);5051      return await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);52    });53  }5455  async function proposalFromAllCouncil(proposal: any) {56    return await usingPlaygrounds(async (helper) => {57      expect((await helper.callRpc('api.query.councilMembership.members')).toJSON().length).to.be.equal(5);58      const proposeResult = await helper.council.collective.propose(59        counselors.filip,60        proposal,61        moreThanHalfCouncilThreshold,62      );6364      const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);65      const proposalIndex = councilProposedEvent.proposalIndex;66      const proposalHash = councilProposedEvent.proposalHash;676869      await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);70      await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);71      await helper.council.collective.vote(counselors.ildar, proposalHash, proposalIndex, true);72      await helper.council.collective.vote(counselors.irina, proposalHash, proposalIndex, true);73      await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);7475      return await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);76    });77  }7879  itSub('>50% of Council can externally propose SuperMajorityAgainst', async ({helper}) => {80    const forceSetBalanceReceiver = helper.arrange.createEmptyAccount();81    const forceSetBalanceTestValue = 20n * 10n ** 25n;8283    const democracyProposal = await helper.constructApiCall('api.tx.balances.forceSetBalance', [84      forceSetBalanceReceiver.address, forceSetBalanceTestValue,85    ]);8687    const councilProposal = await helper.democracy.externalProposeDefaultCall(democracyProposal);8889    const proposeResult = await helper.council.collective.propose(90      counselors.filip,91      councilProposal,92      moreThanHalfCouncilThreshold,93    );9495    const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);96    const proposalIndex = councilProposedEvent.proposalIndex;97    const proposalHash = councilProposedEvent.proposalHash;9899    await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);100    await helper.council.collective.vote(counselors.charu, proposalHash, proposalIndex, true);101    await helper.council.collective.vote(counselors.filip, proposalHash, proposalIndex, true);102103    await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);104105    const democracyStartedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);106    const democracyReferendumIndex = democracyStartedEvent.referendumIndex;107    const democracyThreshold = democracyStartedEvent.threshold;108109    expect(democracyThreshold).to.be.equal('SuperMajorityAgainst');110111    await helper.democracy.vote(counselors.filip, democracyReferendumIndex, {112      Standard: {113        vote: {114          aye: true,115          conviction: 1,116        },117        balance: 10_000n,118      },119    });120121    await helper.democracy.vote(counselors.charu, democracyReferendumIndex, {122      Standard: {123        vote: {124          aye: false,125          conviction: 1,126        },127        balance: 50_000n,128      },129    });130131    const passedReferendumEvent = await helper.wait.expectEvent(democracyVotingPeriod, Event.Democracy.Passed);132    expect(passedReferendumEvent.referendumIndex).to.be.equal(democracyReferendumIndex);133134    await helper.wait.expectEvent(democracyEnactmentPeriod, Event.Scheduler.Dispatched);135    const receiverBalance = await helper.balance.getSubstrate(forceSetBalanceReceiver.address);136    expect(receiverBalance).to.be.equal(forceSetBalanceTestValue);137  });138139  itSub('Council prime member vote is the default', async ({helper}) => {140    const newTechCommMember = helper.arrange.createEmptyAccount();141    const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address);142    const proposeResult = await helper.council.collective.propose(143      counselors.filip,144      addMemberProposal,145      moreThanHalfCouncilThreshold,146    );147148    const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);149    const proposalIndex = councilProposedEvent.proposalIndex;150    const proposalHash = councilProposedEvent.proposalHash;151152    await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);153154    await helper.wait.newBlocks(councilMotionDuration);155    const closeResult = await helper.council.collective.close(counselors.filip, proposalHash, proposalIndex);156    const closeEvent = Event.Council.Closed.expect(closeResult);157    const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON() as string[];158    expect(closeEvent.yes).to.be.equal(members.length);159  });160161  itSub('Superuser can add a member', async ({helper}) => {162    const newMember = helper.arrange.createEmptyAccount();163    await expect(helper.getSudo().council.membership.addMember(sudoer, newMember.address)).to.be.fulfilled;164165    const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();166    expect(members).to.contains(newMember.address);167  });168169  itSub('Superuser can remove a member', async ({helper}) => {170    await expect(helper.getSudo().council.membership.removeMember(sudoer, counselors.alex.address)).to.be.fulfilled;171172    const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();173    expect(members).to.not.contains(counselors.alex.address);174  });175176  itSub('>50% Council can add TechComm member', async ({helper}) => {177    const newTechCommMember = helper.arrange.createEmptyAccount();178    const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address);179180    await proposalFromMoreThanHalfCouncil(addMemberProposal);181182    const techCommMembers = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();183    expect(techCommMembers).to.contains(newTechCommMember.address);184  });185186  itSub('Council can remove TechComm member', async ({helper}) => {187    const techComm = await initTechComm(donor, sudoer);188    const removeMemberPrpoposal = helper.technicalCommittee.membership.removeMemberCall(techComm.andy.address);189    await proposalFromMoreThanHalfCouncil(removeMemberPrpoposal);190191    const techCommMembers = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();192    expect(techCommMembers).to.not.contains(techComm.andy.address);193  });194195  itSub('Council can remove FinCouncil member', async ({helper}) => {196    const finCouncil = await initFinCouncil(donor, sudoer);197    const removeMemberPrpoposal = helper.finCouncil.membership.removeMemberCall(finCouncil.andy.address);198    await proposalFromMoreThanHalfCouncil(removeMemberPrpoposal);199200    const finCouncilMembers = await helper.finCouncil.membership.getMembers();201    expect(finCouncilMembers).to.not.contains(finCouncil.andy.address);202  });203204  itSub('Council can add FinCouncil member', async ({helper}) => {205    await initFinCouncil(donor, sudoer);206    const newFinCouncilMember = helper.arrange.createEmptyAccount();207    const addMemberPrpoposal = helper.finCouncil.membership.addMemberCall(newFinCouncilMember.address);208    await proposalFromMoreThanHalfCouncil(addMemberPrpoposal);209210    const finCouncilMembers = await helper.finCouncil.membership.getMembers();211    expect(finCouncilMembers).to.contains(newFinCouncilMember.address);212  });213214  itSub.skip('Council member can add Fellowship member', async ({helper}) => {215    const newFellowshipMember = helper.arrange.createEmptyAccount();216    await expect(helper.council.collective.execute(217      counselors.alex,218      helper.fellowship.collective.addMemberCall(newFellowshipMember.address),219    )).to.be.fulfilled;220    const fellowshipMembers = (await helper.callRpc('api.query.fellowshipCollective.members')).toJSON();221    expect(fellowshipMembers).to.contains(newFellowshipMember.address);222  });223224  itSub('>50% Council can promote Fellowship member', async ({helper}) => {225    const fellowship = await initFellowship(donor, sudoer);226    const memberWithZeroRank = fellowship[0][0];227228    const proposal = helper.fellowship.collective.promoteCall(memberWithZeroRank.address);229    await proposalFromMoreThanHalfCouncil(proposal);230    const record = (await helper.callRpc('api.query.fellowshipCollective.members', [memberWithZeroRank.address])).toJSON();231    expect(record).to.be.deep.equal({rank: 1});232233    await clearFellowship(sudoer);234  });235236  itSub('>50% Council can demote Fellowship member', async ({helper}) => {237    const fellowship = await initFellowship(donor, sudoer);238    const memberWithRankOne = fellowship[1][0];239240    const proposal = helper.fellowship.collective.demoteCall(memberWithRankOne.address);241    await proposalFromMoreThanHalfCouncil(proposal);242243    const record = (await helper.callRpc('api.query.fellowshipCollective.members', [memberWithRankOne.address])).toJSON();244    expect(record).to.be.deep.equal({rank: 0});245246    await clearFellowship(sudoer);247  });248249  itSub('>50% Council can add\remove Fellowship member', async ({helper}) => {250    try {251      const newMember = helper.arrange.createEmptyAccount();252253      const proposalAdd = helper.fellowship.collective.addMemberCall(newMember.address);254      const proposalRemove = helper.fellowship.collective.removeMemberCall(newMember.address, fellowshipRankLimit);255      await expect(proposalFromMoreThanHalfCouncil(proposalAdd)).to.be.fulfilled;256      expect(await helper.fellowship.collective.getMembers()).to.be.deep.contain(newMember.address);257      await expect(proposalFromMoreThanHalfCouncil(proposalRemove)).to.be.fulfilled;258      expect(await helper.fellowship.collective.getMembers()).to.be.not.deep.contain(newMember.address);259    }260    finally {261      await clearFellowship(sudoer);262    }263  });264265  itSub('Council can blacklist Democracy proposals', async ({helper}) => {266    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);267    await expect(proposalFromAllCouncil(helper.democracy.blacklistCall(preimageHash, null))).to.be.fulfilled;268  });269270  itSub('Sudo can blacklist Democracy proposals', async ({helper}) => {271    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);272    await expect(helper.getSudo().democracy.blacklist(sudoer, preimageHash)).to.be.fulfilled;273  });274275  itSub('[Negative] Council cannot add Council member', async ({helper}) => {276    const newCouncilMember = helper.arrange.createEmptyAccount();277    const addMemberProposal = helper.council.membership.addMemberCall(newCouncilMember.address);278279    await expect(proposalFromAllCouncil(addMemberProposal)).to.be.rejected;280  });281282  itSub('[Negative] Council cannot remove Council member', async ({helper}) => {283    const removeMemberProposal = helper.council.membership.removeMemberCall(counselors.alex.address);284285    await expect(proposalFromAllCouncil(removeMemberProposal)).to.be.rejected;286  });287288  itSub('[Negative] Council cannot submit regular democracy proposal', async ({helper}) => {289    const councilProposal = await helper.democracy.proposeCall(dummyProposalCall(helper), 0n);290291    await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);292  });293294  itSub('[Negative] Council cannot externally propose SimpleMajority', async ({helper}) => {295    const councilProposal = await helper.democracy.externalProposeMajorityCall(dummyProposalCall(helper));296297    await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);298  });299300  itSub('[Negative] Council cannot externally propose SuperMajorityApprove', async ({helper}) => {301    const councilProposal = await helper.democracy.externalProposeCall(dummyProposalCall(helper));302303    await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith(/BadOrigin/);304  });305306  itSub('[Negative] Council member cannot add/remove a Council member', async ({helper}) => {307    const newCouncilMember = helper.arrange.createEmptyAccount();308    await expect(helper.council.collective.execute(309      counselors.alex,310      helper.council.membership.addMemberCall(newCouncilMember.address),311    )).to.be.rejectedWith('BadOrigin');312    await expect(helper.council.collective.execute(313      counselors.alex,314      helper.council.membership.removeMemberCall(counselors.charu.address),315    )).to.be.rejectedWith('BadOrigin');316  });317318  itSub('[Negative] Council cannot set/clear Council prime member', async ({helper}) => {319    const proposalForSet = await helper.council.membership.setPrimeCall(counselors.charu.address);320    const proposalForClear = await helper.council.membership.clearPrimeCall();321322    await expect(proposalFromAllCouncil(proposalForSet)).to.be.rejectedWith(/BadOrigin/);323    await expect(proposalFromAllCouncil(proposalForClear)).to.be.rejectedWith(/BadOrigin/);324325  });326327  itSub('[Negative] Council member cannot set/clear Council prime member', async ({helper}) => {328    await expect(helper.council.collective.execute(329      counselors.alex,330      helper.council.membership.setPrimeCall(counselors.charu.address),331    )).to.be.rejectedWith('BadOrigin');332    await expect(helper.council.collective.execute(333      counselors.alex,334      helper.council.membership.clearPrimeCall(),335    )).to.be.rejectedWith('BadOrigin');336  });337338  itSub('[Negative] Council member cannot add/remove a TechComm member', async ({helper}) => {339    const newTechCommMember = helper.arrange.createEmptyAccount();340    await expect(helper.council.collective.execute(341      counselors.alex,342      helper.technicalCommittee.membership.addMemberCall(newTechCommMember.address),343    )).to.be.rejectedWith('BadOrigin');344    await expect(helper.council.collective.execute(345      counselors.alex,346      helper.technicalCommittee.membership.removeMemberCall(newTechCommMember.address),347    )).to.be.rejectedWith('BadOrigin');348  });349350  itSub('[Negative] Council member can\'t add FinCouncil member', async ({helper}) => {351    const newFinCouncilMember = helper.arrange.createEmptyAccount();352    await expect(helper.council.collective.execute(353      counselors.alex,354      helper.finCouncil.membership.addMemberCall(newFinCouncilMember.address),355    )).rejectedWith('BadOrigin');356  });357358  itSub('[Negative] Council member can\'t remove FinCouncil member', async ({helper}) => {359    const finCouncil = await initFinCouncil(donor, sudoer);360    await expect(helper.council.collective.execute(361      counselors.alex,362      helper.finCouncil.membership.removeMemberCall(finCouncil.ildar.address),363    )).rejectedWith('BadOrigin');364  });365366  itSub('[Negative] Council member cannot promote/demote a Fellowship member', async ({helper}) => {367    const fellowship = await initFellowship(donor, sudoer);368    const memberWithRankOne = fellowship[1][0];369370    await expect(helper.council.collective.execute(371      counselors.alex,372      helper.fellowship.collective.promoteCall(memberWithRankOne.address),373    )).to.be.rejectedWith('BadOrigin');374    await expect(helper.council.collective.execute(375      counselors.alex,376      helper.fellowship.collective.demoteCall(memberWithRankOne.address),377    )).to.be.rejectedWith('BadOrigin');378    await clearFellowship(sudoer);379  });380381  itSub('[Negative] Council cannot fast-track Democracy proposals', async ({helper}) => {382    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);383    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);384385    await expect(proposalFromAllCouncil(helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0)))386      .to.be.rejectedWith(/BadOrigin/);387  });388389  itSub('[Negative] Council member cannot fast-track Democracy proposals', async ({helper}) => {390    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);391    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);392393    await expect(helper.council.collective.execute(394      counselors.alex,395      helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0),396    )).to.be.rejectedWith('BadOrigin');397  });398399  itSub('[Negative] Council cannot cancel Democracy proposals', async ({helper}) => {400    const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);401    const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;402403    await expect(proposalFromAllCouncil(helper.democracy.cancelProposalCall(proposalIndex)))404      .to.be.rejectedWith(/BadOrigin/);405  });406407  itSub('[Negative] Council member cannot cancel Democracy proposals', async ({helper}) => {408409    const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);410    const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;411412    await expect(helper.council.collective.execute(413      counselors.alex,414      helper.democracy.cancelProposalCall(proposalIndex),415    )).to.be.rejectedWith('BadOrigin');416  });417418  itSub('[Negative] Council cannot cancel ongoing Democracy referendums', async ({helper}) => {419    await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));420    const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);421    const referendumIndex = startedEvent.referendumIndex;422423    await expect(proposalFromAllCouncil(helper.democracy.emergencyCancelCall(referendumIndex)))424      .to.be.rejectedWith(/BadOrigin/);425  });426427  itSub('[Negative] Council member cannot cancel ongoing Democracy referendums', async ({helper}) => {428    await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));429    const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);430    const referendumIndex = startedEvent.referendumIndex;431432    await expect(helper.council.collective.execute(433      counselors.alex,434      helper.democracy.emergencyCancelCall(referendumIndex),435    )).to.be.rejectedWith('BadOrigin');436  });437438  itSub('[Negative] Council cannot cancel Fellowship referendums', async ({helper}) => {439    const fellowship = await initFellowship(donor, sudoer);440    const fellowshipProposer = fellowship[5][0];441    const proposal = dummyProposal(helper);442443    const submitResult = await helper.fellowship.referenda.submit(444      fellowshipProposer,445      fellowshipPropositionOrigin,446      proposal,447      defaultEnactmentMoment,448    );449450    const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;451452    await expect(proposalFromAllCouncil(helper.fellowship.referenda.cancelCall(referendumIndex)))453      .to.be.rejectedWith(/BadOrigin/);454  });455456  itSub('[Negative] Council member cannot cancel Fellowship referendums', async ({helper}) => {457    const fellowship = await initFellowship(donor, sudoer);458    const fellowshipProposer = fellowship[5][0];459    const proposal = dummyProposal(helper);460461    const submitResult = await helper.fellowship.referenda.submit(462      fellowshipProposer,463      fellowshipPropositionOrigin,464      proposal,465      defaultEnactmentMoment,466    );467    const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;468    await expect(helper.council.collective.execute(469      counselors.alex,470      helper.fellowship.referenda.cancelCall(referendumIndex),471    )).to.be.rejectedWith('BadOrigin');472  });473474  itSub('[Negative] Council referendum cannot be closed until the voting threshold is met', async ({helper}) => {475    const councilSize = (await helper.callRpc('api.query.councilMembership.members')).toJSON().length as any as number;476    expect(councilSize).is.greaterThan(1);477    const proposeResult = await helper.council.collective.propose(478      counselors.filip,479      dummyProposalCall(helper),480      councilSize,481    );482483    const councilProposedEvent = Event.Council.Proposed.expect(proposeResult);484    const proposalIndex = councilProposedEvent.proposalIndex;485    const proposalHash = councilProposedEvent.proposalHash;486487488    await helper.council.collective.vote(counselors.alex, proposalHash, proposalIndex, true);489    await expect(helper.council.collective.close(counselors.filip, proposalHash, proposalIndex)).to.be.rejectedWith('TooEarly');490  });491492  itSub('[Negative] Council can\'t veto Democracy proposals', async ({helper}) => {493    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);494    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);495496    await expect(proposalFromAllCouncil(helper.democracy.vetoExternalCall(preimageHash)))497      .rejectedWith('BadOrigin');498  });499500  itSub('[Negative] Council member can\'t veto Democracy proposals', async ({helper}) => {501    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);502    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);503504    await expect(helper.council.collective.execute(505      counselors.charu,506      helper.democracy.vetoExternalCall(preimageHash),507    )).rejectedWith('BadOrigin');508  });509});
modifiedjs-packages/tests/sub/governance/financialCouncil.test.tsdiffbeforeafterboth
--- a/js-packages/tests/sub/governance/financialCouncil.test.ts
+++ b/js-packages/tests/sub/governance/financialCouncil.test.ts
@@ -28,7 +28,7 @@
     await clearTechComm(sudoer);
   });
 
-  async function proposalFromMoreThanHalfCouncil(proposal: any) {
+  async function proposalFromMoreThanHalfFinCouncil(proposal: any) {
     return await usingPlaygrounds(async (helper) => {
       expect((await helper.finCouncil.membership.getMembers()).length).to.be.equal(3);
       const proposeResult = await helper.finCouncil.collective.propose(
@@ -48,7 +48,7 @@
     });
   }
 
-  async function proposalFromAllCouncil(proposal: any) {
+  async function proposalFromAllFinCouncil(proposal: any) {
     return await usingPlaygrounds(async (helper) => {
       expect((await helper.finCouncil.membership.getMembers()).length).to.be.equal(3);
       const proposeResult = await helper.finCouncil.collective.propose(
@@ -103,7 +103,7 @@
 
     await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);
 
-    await expect(proposalFromAllCouncil(helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0)))
+    await expect(proposalFromAllFinCouncil(helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0)))
       .rejectedWith('BadOrigin');
   });
 
@@ -121,7 +121,7 @@
     const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);
     const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;
 
-    await expect(proposalFromAllCouncil(helper.democracy.cancelProposalCall(proposalIndex)))
+    await expect(proposalFromAllFinCouncil(helper.democracy.cancelProposalCall(proposalIndex)))
       .rejectedWith('BadOrigin');
   });
 
@@ -141,7 +141,7 @@
     const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);
     const referendumIndex = startedEvent.referendumIndex;
 
-    await expect(proposalFromAllCouncil(helper.democracy.emergencyCancelCall(referendumIndex)))
+    await expect(proposalFromAllFinCouncil(helper.democracy.emergencyCancelCall(referendumIndex)))
       .rejectedWith('BadOrigin');
   });
 
@@ -156,6 +156,14 @@
     )).to.be.rejectedWith('BadOrigin');
   });
 
+  itSub('[Negative] FinCouncil can\'t veto Democracy proposals', async ({helper}) => {
+    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);
+    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);
+
+    await expect(proposalFromAllFinCouncil(helper.democracy.vetoExternalCall(preimageHash)))
+      .rejectedWith('BadOrigin');
+  });
+
   itSub('[Negative] FinCouncil member can\'t veto Democracy proposals', async ({helper}) => {
     const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);
     await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);
@@ -170,7 +178,7 @@
     const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);
     await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);
 
-    await expect(proposalFromAllCouncil(helper.democracy.blacklistCall(preimageHash))).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(helper.democracy.blacklistCall(preimageHash))).to.be.rejectedWith('BadOrigin');
   });
 
   itSub('[Negative] FinCouncil member cannot blacklist Democracy proposals', async ({helper}) => {
@@ -183,7 +191,7 @@
     )).to.be.rejectedWith('BadOrigin');
   });
 
-  itSub('[Negative] FinCouncil can\' cancel Fellowship referendums', async ({helper}) => {
+  itSub('[Negative] FinCouncil can\'t cancel Fellowship referendums', async ({helper}) => {
     const fellowship = await initFellowship(donor, sudoer);
     const fellowshipProposer = fellowship[5][0];
     const proposal = dummyProposal(helper);
@@ -195,11 +203,11 @@
       defaultEnactmentMoment,
     );
     const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;
-    await expect(proposalFromAllCouncil(helper.fellowship.referenda.cancelCall(referendumIndex)))
+    await expect(proposalFromAllFinCouncil(helper.fellowship.referenda.cancelCall(referendumIndex)))
       .rejectedWith('BadOrigin');
   });
 
-  itSub('[Negative] TechComm member cannot cancel Fellowship referendums', async ({helper}) => {
+  itSub('[Negative] FinCouncil member cannot cancel Fellowship referendums', async ({helper}) => {
     const fellowship = await initFellowship(donor, sudoer);
     const fellowshipProposer = fellowship[5][0];
     const proposal = dummyProposal(helper);
@@ -219,7 +227,7 @@
     )).to.be.rejectedWith('BadOrigin');
   });
 
-  itSub('[Negative] FinCouncil member can\' add a Fellowship member', async ({helper}) => {
+  itSub('[Negative] FinCouncil member can\'t add a Fellowship member', async ({helper}) => {
     const newFellowshipMember = helper.arrange.createEmptyAccount();
     await expect(helper.finCouncil.collective.execute(
       finCounselors.andy,
@@ -230,13 +238,13 @@
   itSub('[Negative] FinCouncil cannot submit regular democracy proposal', async ({helper}) => {
     const councilProposal = await helper.democracy.proposeCall(dummyProposalCall(helper), 0n);
 
-    await expect(proposalFromAllCouncil(councilProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(councilProposal)).to.be.rejectedWith('BadOrigin');
   });
 
   itSub('[Negative] FinCouncil cannot externally propose SuperMajorityAgainst', async ({helper}) => {
     const commiteeProposal = await helper.democracy.externalProposeDefaultCall(dummyProposalCall(helper));
 
-    await expect(proposalFromAllCouncil(commiteeProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(commiteeProposal)).to.be.rejectedWith('BadOrigin');
   });
 
   itSub('[Negative] FinCouncil member cannot submit regular democracy proposal', async ({helper}) => {
@@ -251,13 +259,13 @@
   itSub('[Negative] FinCouncil cannot externally propose SimpleMajority', async ({helper}) => {
     const commiteeProposal = await helper.democracy.externalProposeMajorityCall(dummyProposalCall(helper));
 
-    await expect(proposalFromAllCouncil(commiteeProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(commiteeProposal)).to.be.rejectedWith('BadOrigin');
   });
 
   itSub('[Negative] FinCouncil cannot externally propose SuperMajorityApprove', async ({helper}) => {
     const commiteeProposal = await helper.democracy.externalProposeCall(dummyProposalCall(helper));
 
-    await expect(proposalFromAllCouncil(commiteeProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(commiteeProposal)).to.be.rejectedWith('BadOrigin');
   });
 
   itSub('[Negative] FinCouncil member cannot externally propose SuperMajorityAgainst', async ({helper}) => {
@@ -292,8 +300,8 @@
     const addMemberProposal = helper.council.membership.addMemberCall(newCouncilMember.address);
     const removeMemberProposal = helper.council.membership.removeMemberCall(newCouncilMember.address);
 
-    await expect(proposalFromAllCouncil(addMemberProposal)).to.be.rejectedWith('BadOrigin');
-    await expect(proposalFromAllCouncil(removeMemberProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(addMemberProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(removeMemberProposal)).to.be.rejectedWith('BadOrigin');
   });
 
   itSub('[Negative] FinCouncil member cannot add/remove a Council member', async ({helper}) => {
@@ -316,10 +324,30 @@
     const addMemberProposal = helper.finCouncil.membership.addMemberCall(newCouncilMember.address);
     const removeMemberProposal = helper.finCouncil.membership.removeMemberCall(finCounselors.ildar.address);
 
-    await expect(proposalFromAllCouncil(addMemberProposal)).to.be.rejectedWith('BadOrigin');
-    await expect(proposalFromAllCouncil(removeMemberProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(addMemberProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(removeMemberProposal)).to.be.rejectedWith('BadOrigin');
+  });
+
+  itSub('[Negative] FinCouncil cannot add/remove a FinCouncil prime member', async ({helper}) => {
+    const setPrimeCall = helper.finCouncil.membership.setPrimeCall(finCounselors.andy.address);
+    const clearPrimeCall = helper.finCouncil.membership.clearPrimeCall();
+
+    await expect(proposalFromAllFinCouncil(setPrimeCall)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(clearPrimeCall)).to.be.rejectedWith('BadOrigin');
   });
 
+  itSub('[Negative] FinCouncil member cannot add/remove a FinCouncil prime member', async ({helper}) => {
+    await expect(helper.finCouncil.collective.execute(
+      finCounselors.andy,
+      helper.finCouncil.membership.setPrimeCall(finCounselors.andy.address),
+    )).to.be.rejectedWith('BadOrigin');
+
+    await expect(helper.finCouncil.collective.execute(
+      finCounselors.andy,
+      helper.finCouncil.membership.clearPrimeCall(),
+    )).to.be.rejectedWith('BadOrigin');
+  });
+
   itSub('[Negative] FinCouncil member cannot add/remove a FinCouncil member', async ({helper}) => {
     const newCouncilMember = helper.arrange.createEmptyAccount();
     const addMemberProposal = helper.finCouncil.membership.addMemberCall(newCouncilMember.address);
@@ -340,8 +368,8 @@
     const proposalForSet = await helper.council.membership.setPrimeCall(counselors.charu.address);
     const proposalForClear = await helper.council.membership.clearPrimeCall();
 
-    await expect(proposalFromAllCouncil(proposalForSet)).to.be.rejectedWith('BadOrigin');
-    await expect(proposalFromAllCouncil(proposalForClear)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(proposalForSet)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(proposalForClear)).to.be.rejectedWith('BadOrigin');
     await clearCouncil(sudoer);
   });
 
@@ -363,17 +391,17 @@
 
   itSub('[Negative] FinCouncil cannot add/remove a TechComm member', async ({helper}) => {
     const newCommMember = helper.arrange.createEmptyAccount();
-    const addMemberProposal = helper.council.membership.addMemberCall(newCommMember.address);
-    const removeMemberProposal = helper.council.membership.removeMemberCall(newCommMember.address);
+    const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newCommMember.address);
+    const removeMemberProposal = helper.technicalCommittee.membership.removeMemberCall(newCommMember.address);
 
-    await expect(proposalFromAllCouncil(addMemberProposal)).to.be.rejectedWith('BadOrigin');
-    await expect(proposalFromAllCouncil(removeMemberProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(addMemberProposal)).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(removeMemberProposal)).to.be.rejectedWith('BadOrigin');
   });
 
   itSub('[Negative] FinCouncil member cannot add/remove a TechComm member', async ({helper}) => {
     const newCommMember = helper.arrange.createEmptyAccount();
-    const addMemberProposal = helper.council.membership.addMemberCall(newCommMember.address);
-    const removeMemberProposal = helper.council.membership.removeMemberCall(newCommMember.address);
+    const addMemberProposal = helper.technicalCommittee.membership.addMemberCall(newCommMember.address);
+    const removeMemberProposal = helper.technicalCommittee.membership.removeMemberCall(newCommMember.address);
 
     await expect(helper.finCouncil.collective.execute(
       finCounselors.andy,
@@ -388,7 +416,7 @@
   itSub('[Negative] FinCouncil cannot remove a Fellowship member', async ({helper}) => {
     const fellowship = await initFellowship(donor, sudoer);
 
-    await expect(proposalFromAllCouncil(helper.fellowship.collective.removeMemberCall(fellowship[5][0].address, 5))).to.be.rejectedWith('BadOrigin');
+    await expect(proposalFromAllFinCouncil(helper.fellowship.collective.removeMemberCall(fellowship[5][0].address, 5))).to.be.rejectedWith('BadOrigin');
     await clearFellowship(sudoer);
   });