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

difftreelog

Merge pull request #887 from UniqueNetwork/fix/staking-events

Yaroslav Bolyukin2023-02-16parents: #58315dd #5ae113b.patch.diff
in: master

4 files changed

modifiedpallets/app-promotion/src/lib.rsdiffbeforeafterboth
793793
794 <PendingUnstake<T>>::insert(unpending_block, pendings);794 <PendingUnstake<T>>::insert(unpending_block, pendings);
795795
796 Self::deposit_event(Event::Unstake(staker_id, total_staked));796 Self::deposit_event(Event::Unstake(staker_id, unstaked_balance));
797797
798 Ok(())798 Ok(())
799 }799 }
modifiedtests/src/benchmarks/utils/common.tsdiffbeforeafterboth
2import {ITokenPropertyPermission, TCollectionMode} from '../../util/playgrounds/types';2import {ITokenPropertyPermission, TCollectionMode} from '../../util/playgrounds/types';
3import {UniqueNFTCollection, UniqueRFTCollection} from '../../util/playgrounds/unique';3import {UniqueNFTCollection, UniqueRFTCollection} from '../../util/playgrounds/unique';
4import {IKeyringPair} from '@polkadot/types/types';4import {IKeyringPair} from '@polkadot/types/types';
5import {ContractImports} from '../../eth/util/playgrounds/types';
65
7export const PROPERTIES = Array(40)6export const PROPERTIES = Array(40)
8 .fill(0)7 .fill(0)
modifiedtests/src/sub/appPromotion/appPromotion.test.tsdiffbeforeafterboth
795 const [_stake1, stake2] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});795 const [_stake1, stake2] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});
796 await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake2.block));796 await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake2.block));
797797
798 const payoutToStaker = (await helper.admin.payoutStakers(palletAdmin, 100)).find((payout) => payout.staker === staker.address)?.payout;798 const payoutToStaker = (await helper.admin.payoutStakers(palletAdmin, 100)).find((payout) => payout.staker === staker.address)!.payout;
799 expect(payoutToStaker + 300n * nominal).to.equal(calculateIncome(300n * nominal));799 expect(payoutToStaker + 300n * nominal).to.equal(calculateIncome(300n * nominal));
800800
801 const totalStakedPerBlock = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});801 const totalStakedPerBlock = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});
867 await helper.staking.stake(staker, 100n * nominal);867 await helper.staking.stake(staker, 100n * nominal);
868 await helper.staking.unstakePartial(staker, 100n * nominal - 1n);868 await helper.staking.unstakePartial(staker, 100n * nominal - 1n);
869869
870 const [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});870 const [_stake1, stake2] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});
871 await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake.block));871 await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake2.block));
872872
873 const payouts = await helper.admin.payoutStakers(palletAdmin, 100);873 const stakerPayout = await payUntilRewardFor(staker.address, helper);
874 const stakerPayout = payouts.find(p => p.staker === staker.address);
875 expect(stakerPayout!.stake).to.eq(100n * nominal + 1n);874 expect(stakerPayout.stake).to.eq(100n * nominal + 1n);
876 });875 });
877876
878 itSub('can eventually pay all rewards', async ({helper}) => {877 itSub('can eventually pay all rewards', async ({helper}) => {
901 });900 });
902 });901 });
902
903 describe('events', () => {
904 [
905 {method: 'unstakePartial' as const},
906 {method: 'unstakeAll' as const},
907 ].map(testCase => {
908 itSub(testCase.method, async ({helper}) => {
909 const unstakeParams = testCase.method === 'unstakePartial'
910 ? [100n * nominal - 1n]
911 : [];
912 const [staker] = getAccount(1);
913 await helper.staking.stake(staker, 100n * nominal);
914 await helper.staking.stake(staker, 200n * nominal);
915 const {result} = await helper.executeExtrinsic(staker, `api.tx.appPromotion.${testCase.method}`, unstakeParams);
916
917 const event = result.events.find(e => e.event.section === 'appPromotion' && e.event.method === 'Unstake');
918 const unstakerEvents = event?.event.data[0].toString();
919 const unstakedEvents = BigInt(event?.event.data[1].toString());
920 expect(unstakerEvents).to.eq(staker.address);
921 expect(unstakedEvents).to.eq(testCase.method === 'unstakeAll' ? 300n * nominal : 100n * nominal - 1n);
922 });
923 });
924
925 itSub('stake', async ({helper}) => {
926 const [staker] = getAccount(1);
927 const {result} = await helper.executeExtrinsic(staker, 'api.tx.appPromotion.stake', [100n * nominal]);
928
929 const event = result.events.find(e => e.event.section === 'appPromotion' && e.event.method === 'Stake');
930 const stakerEvents = event?.event.data[0].toString();
931 const stakedEvents = BigInt(event?.event.data[1].toString());
932 expect(stakerEvents).to.eq(staker.address);
933 expect(stakedEvents).to.eq(100n * nominal);
934 });
935
936 // Flaky
937 itSub.skip('payoutStakers', async ({helper}) => {
938 const [staker1, staker2] = getAccount(2);
939 const STAKE1 = 100n * nominal;
940 const STAKE2 = 200n * nominal;
941 await helper.staking.stake(staker1, STAKE1);
942 await helper.staking.stake(staker2, STAKE2);
943
944 const [stake2] = await helper.staking.getTotalStakedPerBlock({Substrate: staker2.address});
945 await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake2.block));
946
947 const results = await helper.admin.payoutStakers(palletAdmin, 100);
948 const stakersEvents = results.filter(ev => ev.staker === staker1.address || ev.staker === staker2.address);
949 expect(stakersEvents).has.length(2);
950 expect(stakersEvents).has.not.ordered.members([
951 {staker: staker1.address, stake: STAKE1, payout: calculateIncome(STAKE1) - STAKE1},
952 {staker: staker2.address, stake: STAKE2, payout: calculateIncome(STAKE2) - STAKE2},
953 ]);
954 });
955 });
903});956});
904957
958
959// Sometimes is is required to make a cycle in order for the payment to be calculated for a specific account
960async function payUntilRewardFor(account: string, helper: DevUniqueHelper) {
961 for (let i = 0; i < 3; i++) {
962 const payouts = await helper.admin.payoutStakers(palletAdmin, 100);
963 const accountPayout = payouts.find(p => p.staker === account);
964 if (accountPayout) return accountPayout;
965 }
966 throw Error(`Cannot find payout for ${account}`);
967}
905968
906function calculateIncome(base: bigint, iter = 0, calcPeriod: bigint = UNLOCKING_PERIOD): bigint {969function calculateIncome(base: bigint, iter = 0, calcPeriod: bigint = UNLOCKING_PERIOD): bigint {
907 const DAY = 7200n;970 const DAY = 7200n;
modifiedtests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth
733 this.helper = helper;733 this.helper = helper;
734 }734 }
735735
736 async payoutStakers(signer: IKeyringPair, stakersToPayout: number) {736 async payoutStakers(signer: IKeyringPair, stakersToPayout: number): Promise<{staker: string, stake: bigint, payout: bigint}[]> {
737 const payoutResult = await this.helper.executeExtrinsic(signer, 'api.tx.appPromotion.payoutStakers', [stakersToPayout], true);737 const payoutResult = await this.helper.executeExtrinsic(signer, 'api.tx.appPromotion.payoutStakers', [stakersToPayout], true);
738 return payoutResult.result.events.filter(e => e.event.method === 'StakingRecalculation').map(e => {738 return payoutResult.result.events.filter(e => e.event.method === 'StakingRecalculation').map(e => {
739 return {739 return {