git.delta.rocks / unique-network / refs/commits / 6a055472d116

difftreelog

Tests: unstakeAll after each test

Max Andreev2023-02-15parent: #5495238.patch.diff
in: master

2 files changed

modifiedtests/src/sub/appPromotion/appPromotion.test.tsdiffbeforeafterboth
--- a/tests/src/sub/appPromotion/appPromotion.test.ts
+++ b/tests/src/sub/appPromotion/appPromotion.test.ts
@@ -26,6 +26,13 @@
 let nominal: bigint;
 let palletAddress: string;
 let accounts: IKeyringPair[];
+let usedAccounts: IKeyringPair[] = [];
+
+function getAccount(accountsNumber: number) {
+  const accs = accounts.splice(0, accountsNumber);
+  usedAccounts.push(...accs);
+  return accs;
+}
 // App promotion periods:
 // LOCKING_PERIOD = 12 blocks of relay
 // UNLOCKING_PERIOD = 6 blocks of parachain
@@ -39,15 +46,29 @@
       palletAdmin = await privateKey('//PromotionAdmin');
       nominal = helper.balance.getOneTokenNominal();
 
-      const accountBalances = new Array(100);
-      accountBalances.fill(1000n);
+      const accountBalances = new Array(200).fill(1000n);
       accounts = await helper.arrange.createAccounts(accountBalances, donor); // create accounts-pool to speed up tests
     });
   });
 
+  afterEach(async () => {
+    await usingPlaygrounds(async (helper) => {
+      let unstakeTxs = [];
+      for (const account of usedAccounts) {
+        if (unstakeTxs.length === 3) {
+          await Promise.all(unstakeTxs);
+          unstakeTxs = [];
+        }
+        unstakeTxs.push(helper.staking.unstakeAll(account));
+      }
+      await Promise.all(unstakeTxs);
+      usedAccounts = [];
+    });
+  });
+
   describe('stake extrinsic', () => {
     itSub('should "lock" staking balance, add it to "staked" map, and increase "totalStaked" amount', async ({helper}) => {
-      const [staker, recepient] = [accounts.pop()!, accounts.pop()!];
+      const [staker, recepient] = getAccount(2);
       const totalStakedBefore = await helper.staking.getTotalStaked();
 
       // Minimum stake amount is 100:
@@ -114,7 +135,7 @@
     });
 
     itSub('should allow to stake() if balance is locked with different id', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
 
       // staker has tokens locked with vesting id:
       await helper.balance.vestedTransfer(donor, staker.address, {start: 0n, period: 1n, periodCount: 1n, perPeriod: 200n * nominal});
@@ -147,7 +168,7 @@
     });
 
     itSub('should not allow to stake(), if stake amount is more than total free balance minus locked by staking', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
 
       // Can't stake full balance because Alice needs to pay some fee
       await expect(helper.staking.stake(staker, 1000n * nominal)).to.be.rejected; // With('Arithmetic')
@@ -159,7 +180,7 @@
     });
 
     itSub('for different accounts in one block is possible', async ({helper}) => {
-      const crowd = [accounts.pop()!, accounts.pop()!, accounts.pop()!, accounts.pop()!];
+      const crowd = getAccount(4);
 
       const crowdStartsToStake = crowd.map(user => helper.staking.stake(user, 100n * nominal));
       await expect(Promise.all(crowdStartsToStake)).to.be.fulfilled;
@@ -175,7 +196,7 @@
       {method: 'unstakePartial' as const},
     ].map(testCase => {
       itSub(`[${testCase.method}] should move tokens to "pendingUnstake" and subtract it from totalStaked`, async ({helper}) => {
-        const [staker, recepient] = [accounts.pop()!, accounts.pop()!];
+        const [staker, recepient] = getAccount(2);
         const totalStakedBefore = await helper.staking.getTotalStaked();
         const STAKE_AMOUNT = 900n * nominal;
 
@@ -201,7 +222,7 @@
       {method: 'unstakePartial' as const},
     ].map(testCase => {
       itSub(`[${testCase.method}] should unlock balance after unlocking period ends and remove it from "pendingUnstake"`, async ({helper}) => {
-        const staker = accounts.pop()!;
+        const [staker] = getAccount(1);
         await helper.staking.stake(staker, 100n * nominal);
         testCase.method === 'unstakeAll'
           ? await helper.staking.unstakeAll(staker)
@@ -224,7 +245,7 @@
       {method: 'unstakePartial' as const},
     ].map(testCase => {
       itSub(`[${testCase.method}] should successfully unstake multiple stakes`, async ({helper}) => {
-        const staker = accounts.pop()!;
+        const [staker] = getAccount(1);
         await helper.staking.stake(staker, 100n * nominal);
         await helper.staking.stake(staker, 200n * nominal);
         await helper.staking.stake(staker, 300n * nominal);
@@ -264,7 +285,7 @@
       {method: 'unstakePartial' as const},
     ].map(testCase => {
       itSub(`[${testCase.method}] should not have any effects if no active stakes`, async ({helper}) => {
-        const staker = accounts.pop()!;
+        const [staker] = getAccount(1);
 
         // unstake has no effect if no stakes at all
         testCase.method === 'unstakeAll'
@@ -298,7 +319,7 @@
       {method: 'unstakePartial' as const},
     ].map(testCase => {
       itSub(`[${testCase.method}] should create different pending-unlock for each unlocking stake`, async ({helper}) => {
-        const staker = accounts.pop()!;
+        const [staker] = getAccount(1);
         await helper.staking.stake(staker, 100n * nominal);
         testCase.method === 'unstakeAll'
           ? await helper.staking.unstakeAll(staker)
@@ -321,7 +342,7 @@
       {method: 'unstakePartial' as const},
     ].map(testCase => {
       itSub(`[${testCase.method}] should be possible for 3 accounts in one block`, async ({helper}) => {
-        const stakers = [accounts.pop()!, accounts.pop()!, accounts.pop()!];
+        const stakers = getAccount(3);
 
         await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal)));
         await Promise.all(stakers.map(staker => {
@@ -339,7 +360,7 @@
 
     itSub('should not be possible for more than 3 accounts in one block', async ({helper}) => {
       if (!await helper.arrange.isDevNode()) {
-        const stakers = await helper.arrange.createAccounts([200n,200n,200n,200n,200n,200n,200n,200n,200n,200n], donor);
+        const stakers = getAccount(10);
 
         await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal)));
         const unstakingResults = await Promise.allSettled(stakers.map((staker, i) => {
@@ -354,7 +375,7 @@
     });
 
     itSub('Cannot partially unstake more than staked', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
       // Staker stakes 300:
       await helper.staking.stake(staker, 100n * nominal);
       await helper.staking.stake(staker, 200n * nominal);
@@ -374,7 +395,7 @@
     });
 
     itSub('Can partially unstake arbitrary amount', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
       await helper.staking.stake(staker, 100n * nominal);
       await helper.staking.stake(staker, 200n * nominal);
 
@@ -408,7 +429,7 @@
     });
 
     itSub('can mix different type of unstakes', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
       await helper.staking.stake(staker, 100n * nominal);
       await helper.staking.stake(staker, 200n * nominal);
 
@@ -433,7 +454,7 @@
   describe('collection sponsoring', () => {
     itSub('should actually sponsor transactions', async ({helper}) => {
       const api = helper.getApi();
-      const [collectionOwner, tokenSender, receiver] = [accounts.pop()!, accounts.pop()!, accounts.pop()!];
+      const [collectionOwner, tokenSender, receiver] = getAccount(3);
       const collection = await helper.nft.mintCollection(collectionOwner, {name: 'Name', description: 'Description', tokenPrefix: 'Prefix', limits: {sponsorTransferTimeout: 0}});
       const token = await collection.mintToken(collectionOwner, {Substrate: tokenSender.address});
       await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId));
@@ -450,7 +471,7 @@
 
     itSub('can not be set by non admin', async ({helper}) => {
       const api = helper.getApi();
-      const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!];
+      const [collectionOwner, nonAdmin] = getAccount(2);
 
       const collection  = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
 
@@ -460,7 +481,7 @@
 
     itSub('should set pallet address as confirmed admin', async ({helper}) => {
       const api = helper.getApi();
-      const [collectionOwner, oldSponsor] = [accounts.pop()!, accounts.pop()!];
+      const [collectionOwner, oldSponsor] = getAccount(2);
 
       // Can set sponsoring for collection without sponsor
       const collectionWithoutSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'No-sponsor', description: 'New Collection', tokenPrefix: 'Promotion'});
@@ -482,7 +503,7 @@
 
     itSub('can be overwritten by collection owner', async ({helper}) => {
       const api = helper.getApi();
-      const [collectionOwner, newSponsor] = [accounts.pop()!, accounts.pop()!];
+      const [collectionOwner, newSponsor] = getAccount(2);
       const collection  = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
       const collectionId = collection.collectionId;
 
@@ -501,7 +522,7 @@
     itSub('should not overwrite collection limits set by the owner earlier', async ({helper}) => {
       const api = helper.getApi();
       const limits = {ownerCanDestroy: true, ownerCanTransfer: true, sponsorTransferTimeout: 0};
-      const collectionWithLimits = await helper.nft.mintCollection(accounts.pop()!, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits});
+      const collectionWithLimits = await helper.nft.mintCollection(getAccount(1)[0], {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits});
 
       await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithLimits.collectionId))).to.be.fulfilled;
       expect((await collectionWithLimits.getData())?.raw.limits).to.be.deep.contain(limits);
@@ -509,7 +530,7 @@
 
     itSub('should reject transaction if collection doesn\'t exist', async ({helper}) => {
       const api = helper.getApi();
-      const collectionOwner = accounts.pop()!;
+      const [collectionOwner] = getAccount(1);
 
       // collection has never existed
       await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(999999999))).to.be.rejected;
@@ -524,7 +545,7 @@
   describe('stopSponsoringCollection', () => {
     itSub('can not be called by non-admin', async ({helper}) => {
       const api = helper.getApi();
-      const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!];
+      const [collectionOwner, nonAdmin] = getAccount(2);
       const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
 
       await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.fulfilled;
@@ -535,7 +556,7 @@
 
     itSub('should set sponsoring as disabled', async ({helper}) => {
       const api = helper.getApi();
-      const [collectionOwner, recepient] = [accounts.pop()!, accounts.pop()!];
+      const [collectionOwner, recepient] = getAccount(2);
       const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits: {sponsorTransferTimeout: 0}});
       const token = await collection.mintToken(collectionOwner, {Substrate: collectionOwner.address});
 
@@ -553,7 +574,7 @@
 
     itSub('should not affect collection which is not sponsored by pallete', async ({helper}) => {
       const api = helper.getApi();
-      const collectionOwner = accounts.pop()!;
+      const [collectionOwner] = getAccount(1);
       const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: collectionOwner.address});
       await collection.confirmSponsorship(collectionOwner);
 
@@ -563,7 +584,7 @@
     });
 
     itSub('should reject transaction if collection does not exist', async ({helper}) => {
-      const collectionOwner = accounts.pop()!;
+      const [collectionOwner] = getAccount(1);
       const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
 
       await collection.burn(collectionOwner);
@@ -637,7 +658,7 @@
     });
 
     itEth('can not be set by non admin', async ({helper}) => {
-      const nonAdmin = accounts.pop()!;
+      const [nonAdmin] = getAccount(1);
       const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase();
       const flipper = await helper.eth.deployFlipper(contractOwner); // await deployFlipper(web3, contractOwner);
       const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner);
@@ -719,7 +740,7 @@
     });
 
     itEth('can not be called by non-admin', async ({helper}) => {
-      const nonAdmin = accounts.pop()!;
+      const [nonAdmin] = getAccount(1);
       const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase();
       const flipper = await helper.eth.deployFlipper(contractOwner);
 
@@ -729,7 +750,7 @@
     });
 
     itEth('should not affect a contract which is not sponsored by pallete', async ({helper}) => {
-      const nonAdmin = accounts.pop()!;
+      const [nonAdmin] = getAccount(1);
       const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase();
       const flipper = await helper.eth.deployFlipper(contractOwner);
       const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner);
@@ -741,12 +762,12 @@
 
   describe('payoutStakers', () => {
     itSub('can not be called by non admin', async ({helper}) => {
-      const nonAdmin = accounts.pop()!;
+      const [nonAdmin] = getAccount(1);
       await expect(helper.admin.payoutStakers(nonAdmin, 100)).to.be.rejectedWith('appPromotion.NoPermission');
     });
 
     itSub('should increase total staked', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
       const totalStakedBefore = await helper.staking.getTotalStaked();
       await helper.staking.stake(staker, 100n * nominal);
 
@@ -763,7 +784,7 @@
     });
 
     itSub('should credit 0.05% for staking period', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
 
       await waitPromotionPeriodDoesntEnd(helper);
 
@@ -789,7 +810,7 @@
     });
 
     itSub('shoud be paid for more than one period if payments was missed', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
 
       await helper.staking.stake(staker, 100n * nominal);
       // wait for two rewards are available:
@@ -808,7 +829,7 @@
 
     itSub('should not be credited for pending-unstaked tokens', async ({helper}) => {
       // staker unstakes before rewards been payed
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
       await helper.staking.stake(staker, 100n * nominal);
       const [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});
       await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake.block) + LOCKING_PERIOD);
@@ -823,7 +844,7 @@
     });
 
     itSub('should bring compound interest', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
 
       await helper.staking.stake(staker, 100n * nominal);
 
@@ -841,7 +862,7 @@
     });
 
     itSub('can calculate reward for tiny stake', async ({helper}) => {
-      const staker = accounts.pop()!;
+      const [staker] = getAccount(1);
       await helper.staking.stake(staker, 100n * nominal);
       await helper.staking.stake(staker, 100n * nominal);
       await helper.staking.unstakePartial(staker, 100n * nominal - 1n);
@@ -855,7 +876,8 @@
     });
 
     itSub('can eventually pay all rewards', async ({helper}) => {
-      const stakers = await helper.arrange.createAccounts(new Array(100).fill(200n), donor);
+      const stakers = getAccount(30);
+      // Create 30 stakes:
       await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal)));
 
       let unstakingTxs = [];
@@ -867,7 +889,7 @@
         unstakingTxs.push(helper.staking.unstakePartial(staker, 100n * nominal - 1n));
       }
 
-      const [staker] = await helper.arrange.createAccounts([1000n], donor);
+      const [staker] = getAccount(1);
       await helper.staking.stake(staker, 100n * nominal);
       const [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});
       await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake.block));
modifiedtests/src/util/globalSetup.tsdiffbeforeafterboth
29 const api = helper.getApi();29 const api = helper.getApi();
30 await helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})));30 await helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})));
31 const nominal = helper.balance.getOneTokenNominal();31 const nominal = helper.balance.getOneTokenNominal();
32 await helper.balance.transferToSubstrate(superuser, palletAdmin.address, 1000n * nominal);32 await helper.balance.transferToSubstrate(superuser, palletAdmin.address, 10000n * nominal);
33 await helper.balance.transferToSubstrate(superuser, palletAddress, 1000n * nominal);33 await helper.balance.transferToSubstrate(superuser, palletAddress, 10000n * nominal);
34 await helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [api.tx.configuration34 await helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [api.tx.configuration
35 .setAppPromotionConfigurationOverride({35 .setAppPromotionConfigurationOverride({
36 recalculationInterval: LOCKING_PERIOD,36 recalculationInterval: LOCKING_PERIOD,