From 78a9ca040ab8720defdf8c15e4e7832c763410b2 Mon Sep 17 00:00:00 2001 From: ut-akuznetsov <59873862+ut-akuznetsov@users.noreply.github.com> Date: Tue, 22 Nov 2022 09:13:05 +0000 Subject: [PATCH] Merge pull request #727 from UniqueNetwork/feature/shortTimingsAppPromotion Feature/short timings app promotion --- --- a/runtime/common/config/pallets/app_promotion.rs +++ b/runtime/common/config/pallets/app_promotion.rs @@ -29,8 +29,8 @@ #[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))] parameter_types! { pub const AppPromotionId: PalletId = PalletId(*b"appstake"); - pub const RecalculationInterval: BlockNumber = 20; - pub const PendingInterval: BlockNumber = 10; + pub const RecalculationInterval: BlockNumber = 8; + pub const PendingInterval: BlockNumber = 4; pub const Nominal: Balance = UNIQUE; // pub const Day: BlockNumber = DAYS; pub IntervalIncome: Perbill = Perbill::from_rational(RecalculationInterval::get(), RELAY_DAYS) * Perbill::from_rational(5u32, 10_000); --- a/tests/src/app-promotion.test.ts +++ b/tests/src/app-promotion.test.ts @@ -24,12 +24,8 @@ let nominal: bigint; let palletAddress: string; let accounts: IKeyringPair[]; -const LOCKING_PERIOD = 20n; // 20 blocks of relay -const UNLOCKING_PERIOD = 10n; // 10 blocks of parachain -const rewardAvailableInBlock = (stakedInBlock: bigint) => { - if (stakedInBlock % LOCKING_PERIOD === 0n) return stakedInBlock + 20n; - return (stakedInBlock - stakedInBlock % LOCKING_PERIOD) + (LOCKING_PERIOD * 2n); -}; +const LOCKING_PERIOD = 8n; // 8 blocks of relay +const UNLOCKING_PERIOD = 4n; // 4 blocks of parachain describe('App promotion', () => { before(async function () { @@ -548,7 +544,7 @@ expect(totalStakedAfter).to.equal(totalStakedBefore + (100n * nominal) + totalPayout); // staker can unstake await helper.staking.unstake(staker); - expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedAfter - calculateIncome(100n * nominal, 10n)); + expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedAfter - calculateIncome(100n * nominal)); }); itSub('should credit 0.05% for staking period', async ({helper}) => { @@ -564,11 +560,11 @@ await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake2.block)); const payoutToStaker = (await helper.admin.payoutStakers(palletAdmin, 100)).find((payout) => payout.staker === staker.address)?.payout; - expect(payoutToStaker + 300n * nominal).to.equal(calculateIncome(300n * nominal, 10n)); + expect(payoutToStaker + 300n * nominal).to.equal(calculateIncome(300n * nominal)); const totalStakedPerBlock = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); - expect(totalStakedPerBlock[0].amount).to.equal(calculateIncome(100n * nominal, 10n)); - expect(totalStakedPerBlock[1].amount).to.equal(calculateIncome(200n * nominal, 10n)); + expect(totalStakedPerBlock[0].amount).to.equal(calculateIncome(100n * nominal)); + expect(totalStakedPerBlock[1].amount).to.equal(calculateIncome(200n * nominal)); }); itSub('shoud be paid for more than one period if payments was missed', async ({helper}) => { @@ -581,7 +577,7 @@ await helper.admin.payoutStakers(palletAdmin, 100); [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); - const frozenBalanceShouldBe = calculateIncome(100n * nominal, 10n, 2); + const frozenBalanceShouldBe = calculateIncome(100n * nominal, 2); expect(stake.amount).to.be.equal(frozenBalanceShouldBe); const stakerFullBalance = await helper.balance.getSubstrateFull(staker.address); @@ -615,12 +611,12 @@ await helper.admin.payoutStakers(palletAdmin, 100); [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); - expect(stake.amount).to.equal(calculateIncome(100n * nominal, 10n)); + expect(stake.amount).to.equal(calculateIncome(100n * nominal)); await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake.block) + LOCKING_PERIOD); await helper.admin.payoutStakers(palletAdmin, 100); [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); - expect(stake.amount).to.equal(calculateIncome(100n * nominal, 10n, 2)); + expect(stake.amount).to.equal(calculateIncome(100n * nominal, 2)); }); itSub.skip('can be paid 1000 rewards in a time', async ({helper}) => { @@ -653,16 +649,22 @@ }); }); -function calculateIncome(base: bigint, calcPeriod: bigint, iter = 0): bigint { +function calculateIncome(base: bigint, iter = 0, calcPeriod: bigint = UNLOCKING_PERIOD): bigint { const DAY = 7200n; const ACCURACY = 1_000_000_000n; + // 5n / 10_000n = 0.05% p/day const income = base + base * (ACCURACY * (calcPeriod * 5n) / (10_000n * DAY)) / ACCURACY ; if (iter > 1) { - return calculateIncome(income, calcPeriod, iter - 1); + return calculateIncome(income, iter - 1, calcPeriod); } else return income; } +function rewardAvailableInBlock(stakedInBlock: bigint) { + if (stakedInBlock % LOCKING_PERIOD === 0n) return stakedInBlock + LOCKING_PERIOD; + return (stakedInBlock - stakedInBlock % LOCKING_PERIOD) + (LOCKING_PERIOD * 2n); +} + // Wait while promotion period less than specified block, to avoid boundary cases // 0 if this should be the beginning of the period. async function waitPromotionPeriodDoesntEnd(helper: DevUniqueHelper, waitBlockLessThan = LOCKING_PERIOD / 3n) { -- gitstuff