git.delta.rocks / unique-network / refs/commits / ed0719fab73d

difftreelog

source

js-packages/tests/sub/governance/technicalCommittee.test.ts18.9 KiBsourcehistory
1import type {IKeyringPair} from '@polkadot/types/types';2import {usingPlaygrounds, itSub, expect, Pallets, requirePalletsOrSkip, describeGov} from '@unique/test-utils/util.js';3import {Event} from '@unique/test-utils';4import {initCouncil, democracyLaunchPeriod, democracyFastTrackVotingPeriod, clearCouncil, clearTechComm, clearFellowship, defaultEnactmentMoment, dummyProposal, dummyProposalCall, fellowshipPropositionOrigin, initFellowship, initTechComm, hardResetFellowshipReferenda, hardResetDemocracy, hardResetGovScheduler} from './util.js';5import type {ITechComms} from './util.js';67describeGov('Governance: Technical Committee tests', () => {8  let sudoer: IKeyringPair;9  let techcomms: ITechComms;10  let donor: IKeyringPair;11  let preImageHash: string;121314  const allTechCommitteeThreshold = 3;1516  before(async function() {17    await usingPlaygrounds(async (helper, privateKey) => {18      requirePalletsOrSkip(this, helper, [Pallets.TechnicalCommittee]);19      sudoer = await privateKey('//Alice');20      donor = await privateKey({url: import.meta.url});2122      techcomms = await initTechComm(donor, sudoer);2324      const proposalCall = await helper.constructApiCall('api.tx.balances.forceSetBalance', [donor.address, 20n * 10n ** 25n]);25      preImageHash = await helper.preimage.notePreimageFromCall(sudoer, proposalCall, true);26    });27  });2829  after(async () => {30    await usingPlaygrounds(async (helper) => {31      await clearTechComm(sudoer);3233      await helper.preimage.unnotePreimage(sudoer, preImageHash);34      await hardResetFellowshipReferenda(sudoer);35      await hardResetDemocracy(sudoer);36      await hardResetGovScheduler(sudoer);37    });38  });3940  function proposalFromAllCommittee(proposal: any) {41    return usingPlaygrounds(async (helper) => {42      expect((await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON().length).to.be.equal(allTechCommitteeThreshold);43      const proposeResult = await helper.technicalCommittee.collective.propose(44        techcomms.andy,45        proposal,46        allTechCommitteeThreshold,47      );4849      const commiteeProposedEvent = Event.TechnicalCommittee.Proposed.expect(proposeResult);50      const proposalIndex = commiteeProposedEvent.proposalIndex;51      const proposalHash = commiteeProposedEvent.proposalHash;525354      await helper.technicalCommittee.collective.vote(techcomms.andy, proposalHash, proposalIndex, true);55      await helper.technicalCommittee.collective.vote(techcomms.constantine, proposalHash, proposalIndex, true);56      await helper.technicalCommittee.collective.vote(techcomms.greg, proposalHash, proposalIndex, true);5758      const closeResult = await helper.technicalCommittee.collective.close(techcomms.andy, proposalHash, proposalIndex);59      Event.TechnicalCommittee.Closed.expect(closeResult);60      Event.TechnicalCommittee.Approved.expect(closeResult);61      const {result} = Event.TechnicalCommittee.Executed.expect(closeResult);62      expect(result).to.eq('Ok');6364      return closeResult;65    });66  }6768  itSub('TechComm can fast-track Democracy proposals', async ({helper}) => {69    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);70    await helper.wait.parachainBlockMultiplesOf(35n);7172    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);7374    const fastTrackProposal = await proposalFromAllCommittee(helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0));75    Event.Democracy.Started.expect(fastTrackProposal);76  });7778  itSub('TechComm can cancel Democracy proposals', async ({helper}) => {79    const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);80    const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;8182    const cancelProposal = await proposalFromAllCommittee(helper.democracy.cancelProposalCall(proposalIndex));83    Event.Democracy.ProposalCanceled.expect(cancelProposal);84  });8586  itSub('TechComm can cancel ongoing Democracy referendums', async ({helper}) => {87    await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));88    const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);89    const referendumIndex = startedEvent.referendumIndex;9091    const emergencyCancelProposal = await proposalFromAllCommittee(helper.democracy.emergencyCancelCall(referendumIndex));92    Event.Democracy.Cancelled.expect(emergencyCancelProposal);93  });9495  itSub('TechComm member can veto Democracy proposals', async ({helper}) => {96    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);97    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);9899    const vetoExternalCall = await helper.technicalCommittee.collective.execute(100      techcomms.andy,101      helper.democracy.vetoExternalCall(preimageHash),102    );103    Event.Democracy.Vetoed.expect(vetoExternalCall);104  });105106  itSub('TechComm can cancel Fellowship referendums', async ({helper}) => {107    const fellowship = await initFellowship(donor, sudoer);108    const fellowshipProposer = fellowship[5][0];109    const proposal = dummyProposal(helper);110111    const submitResult = await helper.fellowship.referenda.submit(112      fellowshipProposer,113      fellowshipPropositionOrigin,114      proposal,115      defaultEnactmentMoment,116    );117    const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;118    const cancelProposal = await proposalFromAllCommittee(helper.fellowship.referenda.cancelCall(referendumIndex));119    Event.FellowshipReferenda.Cancelled.expect(cancelProposal);120  });121122  itSub.skip('TechComm member can add a Fellowship member', async ({helper}) => {123    const newFellowshipMember = helper.arrange.createEmptyAccount();124    await expect(helper.technicalCommittee.collective.execute(125      techcomms.andy,126      helper.fellowship.collective.addMemberCall(newFellowshipMember.address),127    )).to.be.fulfilled;128    const fellowshipMembers = (await helper.callRpc('api.query.fellowshipCollective.members')).toJSON();129    expect(fellowshipMembers).to.contains(newFellowshipMember.address);130    await clearFellowship(sudoer);131  });132133  itSub('[Negative] TechComm can\'t add FinCouncil member', async ({helper}) => {134    const newFinCouncilMember = helper.arrange.createEmptyAccount();135    const addMemberProposal = helper.finCouncil.membership.addMemberCall(newFinCouncilMember.address);136    await proposalFromAllCommittee(addMemberProposal);137138    const finCouncilMembers = await helper.finCouncil.membership.getMembers();139    expect(finCouncilMembers).to.contains(newFinCouncilMember.address);140  });141142143  itSub('[Negative] TechComm member can\'t add FinCouncil member', async ({helper}) => {144    const newFinCouncilMember = helper.arrange.createEmptyAccount();145    await expect(helper.technicalCommittee.collective.execute(146      techcomms.greg,147      helper.finCouncil.membership.addMemberCall(newFinCouncilMember.address),148    )).rejectedWith('BadOrigin');149  });150151  itSub('[Negative] TechComm member cannot register foreign asset', async ({helper}) => {152    const location = {153      parents: 1,154      interior: {X3: [155        {156          Parachain: 1000,157        },158        {159          PalletInstance: 50,160        },161        {162          GeneralIndex: 1985,163        },164      ]},165    };166    const assetId = {Concrete: location};167168    const foreignAssetProposal = helper.constructApiCall(169      'api.tx.foreignAssets.forceRegisterForeignAsset',170      [{V3: assetId}, helper.util.str2vec('New Asset2'), 'NEW', {Fungible: 10}],171    );172173    await expect(helper.technicalCommittee.collective.execute(techcomms.andy, foreignAssetProposal))174      .to.be.rejectedWith('BadOrigin');175  });176177  itSub('[Negative] TechComm cannot submit regular democracy proposal', async ({helper}) => {178    const councilProposal = await helper.democracy.proposeCall(dummyProposalCall(helper), 0n);179180    await expect(proposalFromAllCommittee(councilProposal)).to.be.rejectedWith('BadOrigin');181  });182183  itSub('[Negative] TechComm cannot externally propose SuperMajorityAgainst', async ({helper}) => {184    const commiteeProposal = await helper.democracy.externalProposeDefaultCall(dummyProposalCall(helper));185186    await expect(proposalFromAllCommittee(commiteeProposal)).to.be.rejectedWith('BadOrigin');187  });188189  itSub('[Negative] TechComm cannot externally propose SimpleMajority', async ({helper}) => {190    const commiteeProposal = await helper.democracy.externalProposeMajorityCall(dummyProposalCall(helper));191192    await expect(proposalFromAllCommittee(commiteeProposal)).to.be.rejectedWith('BadOrigin');193  });194195  itSub('[Negative] TechComm cannot externally propose SuperMajorityApprove', async ({helper}) => {196    const commiteeProposal = await helper.democracy.externalProposeCall(dummyProposalCall(helper));197198    await expect(proposalFromAllCommittee(commiteeProposal)).to.be.rejectedWith('BadOrigin');199  });200201  itSub('[Negative] TechComm member cannot submit regular democracy proposal', async ({helper}) => {202    const memberProposal = await helper.democracy.proposeCall(dummyProposalCall(helper), 0n);203204    await expect(helper.technicalCommittee.collective.execute(205      techcomms.andy,206      memberProposal,207    )).to.be.rejectedWith('BadOrigin');208  });209210  itSub('[Negative] TechComm member cannot externally propose SuperMajorityAgainst', async ({helper}) => {211    const memberProposal = await helper.democracy.externalProposeDefaultCall(dummyProposalCall(helper));212213    await expect(helper.technicalCommittee.collective.execute(214      techcomms.andy,215      memberProposal,216    )).to.be.rejectedWith('BadOrigin');217  });218219  itSub('[Negative] TechComm member cannot externally propose SimpleMajority', async ({helper}) => {220    const memberProposal = await helper.democracy.externalProposeMajorityCall(dummyProposalCall(helper));221222    await expect(helper.technicalCommittee.collective.execute(223      techcomms.andy,224      memberProposal,225    )).to.be.rejectedWith('BadOrigin');226  });227228  itSub('[Negative] TechComm member cannot externally propose SuperMajorityApprove', async ({helper}) => {229    const memberProposal = await helper.democracy.externalProposeCall(dummyProposalCall(helper));230231    await expect(helper.technicalCommittee.collective.execute(232      techcomms.andy,233      memberProposal,234    )).to.be.rejectedWith('BadOrigin');235  });236237238  itSub.skip('[Negative] TechComm cannot promote/demote Fellowship member', async () => {239240  });241242  itSub.skip('[Negative] TechComm member cannot promote/demote Fellowship member', async () => {243244  });245246  itSub('[Negative] TechComm cannot add/remove a Council member', async ({helper}) => {247    const newCouncilMember = helper.arrange.createEmptyAccount();248    const addMemberProposal = helper.council.membership.addMemberCall(newCouncilMember.address);249    const removeMemberProposal = helper.council.membership.removeMemberCall(newCouncilMember.address);250251    await expect(proposalFromAllCommittee(addMemberProposal)).to.be.rejectedWith('BadOrigin');252    await expect(proposalFromAllCommittee(removeMemberProposal)).to.be.rejectedWith('BadOrigin');253  });254255  itSub('[Negative] TechComm member cannot add/remove a Council member', async ({helper}) => {256    const newCouncilMember = helper.arrange.createEmptyAccount();257    const addMemberProposal = helper.council.membership.addMemberCall(newCouncilMember.address);258    const removeMemberProposal = helper.council.membership.removeMemberCall(newCouncilMember.address);259260    await expect(helper.technicalCommittee.collective.execute(261      techcomms.andy,262      addMemberProposal,263    )).to.be.rejectedWith('BadOrigin');264    await expect(helper.technicalCommittee.collective.execute(265      techcomms.andy,266      removeMemberProposal,267    )).to.be.rejectedWith('BadOrigin');268  });269270  itSub('[Negative] TechComm cannot set/clear Council prime member', async ({helper}) => {271    const counselors = await initCouncil(donor, sudoer);272    const proposalForSet = await helper.council.membership.setPrimeCall(counselors.charu.address);273    const proposalForClear = await helper.council.membership.clearPrimeCall();274275    await expect(proposalFromAllCommittee(proposalForSet)).to.be.rejectedWith('BadOrigin');276    await expect(proposalFromAllCommittee(proposalForClear)).to.be.rejectedWith('BadOrigin');277    await clearCouncil(sudoer);278  });279280  itSub('[Negative] TechComm member cannot set/clear Council prime member', async ({helper}) => {281    const counselors = await initCouncil(donor, sudoer);282    const proposalForSet = await helper.council.membership.setPrimeCall(counselors.charu.address);283    const proposalForClear = await helper.council.membership.clearPrimeCall();284285    await expect(helper.technicalCommittee.collective.execute(286      techcomms.andy,287      proposalForSet,288    )).to.be.rejectedWith('BadOrigin');289    await expect(helper.technicalCommittee.collective.execute(290      techcomms.andy,291      proposalForClear,292    )).to.be.rejectedWith('BadOrigin');293    await clearCouncil(sudoer);294  });295296  itSub('[Negative] TechComm cannot add/remove a TechComm member', async ({helper}) => {297    const newCommMember = helper.arrange.createEmptyAccount();298    const addMemberProposal = helper.council.membership.addMemberCall(newCommMember.address);299    const removeMemberProposal = helper.council.membership.removeMemberCall(newCommMember.address);300301    await expect(proposalFromAllCommittee(addMemberProposal)).to.be.rejectedWith('BadOrigin');302    await expect(proposalFromAllCommittee(removeMemberProposal)).to.be.rejectedWith('BadOrigin');303  });304305  itSub('[Negative] TechComm member cannot add/remove a TechComm member', async ({helper}) => {306    const newCommMember = helper.arrange.createEmptyAccount();307    const addMemberProposal = helper.council.membership.addMemberCall(newCommMember.address);308    const removeMemberProposal = helper.council.membership.removeMemberCall(newCommMember.address);309310    await expect(helper.technicalCommittee.collective.execute(311      techcomms.andy,312      addMemberProposal,313    )).to.be.rejectedWith('BadOrigin');314    await expect(helper.technicalCommittee.collective.execute(315      techcomms.andy,316      removeMemberProposal,317    )).to.be.rejectedWith('BadOrigin');318  });319320  itSub('[Negative] TechComm cannot remove a Fellowship member', async ({helper}) => {321    const fellowship = await initFellowship(donor, sudoer);322323    await expect(proposalFromAllCommittee(helper.fellowship.collective.removeMemberCall(fellowship[5][0].address, 5))).to.be.rejectedWith('BadOrigin');324    await clearFellowship(sudoer);325  });326327  itSub('[Negative] TechComm member cannot remove a Fellowship member', async ({helper}) => {328    const fellowship = await initFellowship(donor, sudoer);329330    await expect(helper.technicalCommittee.collective.execute(331      techcomms.andy,332      helper.fellowship.collective.removeMemberCall(fellowship[5][0].address, 5),333    )).to.be.rejectedWith('BadOrigin');334    await clearFellowship(sudoer);335  });336337  itSub('[Negative] TechComm member cannot fast-track Democracy proposals', async ({helper}) => {338    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);339    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);340341    await expect(helper.technicalCommittee.collective.execute(342      techcomms.andy,343      helper.democracy.fastTrackCall(preimageHash, democracyFastTrackVotingPeriod, 0),344    )).to.be.rejectedWith('BadOrigin');345  });346347  itSub('[Negative] TechComm member cannot cancel Democracy proposals', async ({helper}) => {348    const proposeResult = await helper.getSudo().democracy.propose(sudoer, dummyProposalCall(helper), 0n);349    const proposalIndex = Event.Democracy.Proposed.expect(proposeResult).proposalIndex;350351    await expect(helper.technicalCommittee.collective.execute(352      techcomms.andy,353      helper.democracy.cancelProposalCall(proposalIndex),354    ))355      .to.be.rejectedWith('BadOrigin');356  });357358  itSub('[Negative] TechComm member cannot cancel ongoing Democracy referendums', async ({helper}) => {359    await helper.getSudo().democracy.externalProposeDefault(sudoer, dummyProposalCall(helper));360    const startedEvent = await helper.wait.expectEvent(democracyLaunchPeriod, Event.Democracy.Started);361    const referendumIndex = startedEvent.referendumIndex;362363    await expect(helper.technicalCommittee.collective.execute(364      techcomms.andy,365      helper.democracy.emergencyCancelCall(referendumIndex),366    )).to.be.rejectedWith('BadOrigin');367  });368369  itSub('[Negative] TechComm cannot blacklist Democracy proposals', async ({helper}) => {370    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);371    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);372373    await expect(proposalFromAllCommittee(helper.democracy.blacklistCall(preimageHash))).to.be.rejectedWith('BadOrigin');374  });375376  itSub('[Negative] TechComm member cannot blacklist Democracy proposals', async ({helper}) => {377    const preimageHash = await helper.preimage.notePreimageFromCall(sudoer, dummyProposalCall(helper), true);378    await helper.getSudo().democracy.externalProposeDefaultWithPreimage(sudoer, preimageHash);379380    await expect(helper.technicalCommittee.collective.execute(381      techcomms.andy,382      helper.democracy.blacklistCall(preimageHash),383    )).to.be.rejectedWith('BadOrigin');384  });385386  itSub.skip('[Negative] TechComm member cannot veto external Democracy proposals until the cool-off period pass', async () => {387388  });389390  itSub('[Negative] TechComm member cannot cancel Fellowship referendums', async ({helper}) => {391    const fellowship = await initFellowship(donor, sudoer);392    const fellowshipProposer = fellowship[5][0];393    const proposal = dummyProposal(helper);394395    const submitResult = await helper.fellowship.referenda.submit(396      fellowshipProposer,397      fellowshipPropositionOrigin,398      proposal,399      defaultEnactmentMoment,400    );401402    const referendumIndex = Event.FellowshipReferenda.Submitted.expect(submitResult).referendumIndex;403404    await expect(helper.technicalCommittee.collective.execute(405      techcomms.andy,406      helper.fellowship.referenda.cancelCall(referendumIndex),407    )).to.be.rejectedWith('BadOrigin');408  });409410  itSub('[Negative] TechComm referendum cannot be closed until the voting threshold is met', async ({helper}) => {411    const committeeSize = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON().length as any as number;412    expect(committeeSize).is.greaterThan(1);413    const proposeResult = await helper.technicalCommittee.collective.propose(414      techcomms.andy,415      dummyProposalCall(helper),416      committeeSize,417    );418419    const committeeProposedEvent = Event.TechnicalCommittee.Proposed.expect(proposeResult);420    const proposalIndex = committeeProposedEvent.proposalIndex;421    const proposalHash = committeeProposedEvent.proposalHash;422423    await helper.technicalCommittee.collective.vote(techcomms.constantine, proposalHash, proposalIndex, true);424425    await expect(helper.technicalCommittee.collective.close(techcomms.andy, proposalHash, proposalIndex)).to.be.rejectedWith('TooEarly');426  });427});