git.delta.rocks / unique-network / refs/commits / 78a9ca040ab8

difftreelog

Merge pull request #727 from UniqueNetwork/feature/shortTimingsAppPromotion

ut-akuznetsov2022-11-22parents: #17cf786 #d6ab0fe.patch.diff
in: master
Feature/short timings app promotion

2 files changed

modifiedruntime/common/config/pallets/app_promotion.rsdiffbeforeafterboth
before · runtime/common/config/pallets/app_promotion.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use crate::{18	runtime_common::config::pallets::{TreasuryAccountId, RelayChainBlockNumberProvider},19	Runtime, Balances, BlockNumber, Unique, RuntimeEvent, EvmContractHelpers,20};2122use frame_support::{parameter_types, PalletId};23use sp_arithmetic::Perbill;24use up_common::{25	constants::{UNIQUE, RELAY_DAYS},26	types::Balance,27};2829#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]30parameter_types! {31	pub const AppPromotionId: PalletId = PalletId(*b"appstake");32	pub const RecalculationInterval: BlockNumber = 20;33	pub const PendingInterval: BlockNumber = 10;34	pub const Nominal: Balance = UNIQUE;35	// pub const Day: BlockNumber = DAYS;36	pub IntervalIncome: Perbill = Perbill::from_rational(RecalculationInterval::get(), RELAY_DAYS) * Perbill::from_rational(5u32, 10_000);37}3839#[cfg(any(feature = "unique-runtime", feature = "quartz-runtime"))]40parameter_types! {41	pub const AppPromotionId: PalletId = PalletId(*b"appstake");42	pub const RecalculationInterval: BlockNumber = RELAY_DAYS;43	pub const PendingInterval: BlockNumber = 7 * RELAY_DAYS;44	pub const Nominal: Balance = UNIQUE;45	// pub const Day: BlockNumber = RELAY_DAYS;46	pub IntervalIncome: Perbill = Perbill::from_rational(5u32, 10_000);47}4849impl pallet_app_promotion::Config for Runtime {50	type PalletId = AppPromotionId;51	type CollectionHandler = Unique;52	type ContractHandler = EvmContractHelpers;53	type Currency = Balances;54	type WeightInfo = pallet_app_promotion::weights::SubstrateWeight<Self>;55	type TreasuryAccountId = TreasuryAccountId;56	type RelayBlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;57	type RecalculationInterval = RecalculationInterval;58	type PendingInterval = PendingInterval;59	// type Day = Day;60	type Nominal = Nominal;61	type IntervalIncome = IntervalIncome;62	type RuntimeEvent = RuntimeEvent;63}
after · runtime/common/config/pallets/app_promotion.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use crate::{18	runtime_common::config::pallets::{TreasuryAccountId, RelayChainBlockNumberProvider},19	Runtime, Balances, BlockNumber, Unique, RuntimeEvent, EvmContractHelpers,20};2122use frame_support::{parameter_types, PalletId};23use sp_arithmetic::Perbill;24use up_common::{25	constants::{UNIQUE, RELAY_DAYS},26	types::Balance,27};2829#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]30parameter_types! {31	pub const AppPromotionId: PalletId = PalletId(*b"appstake");32	pub const RecalculationInterval: BlockNumber = 8;33	pub const PendingInterval: BlockNumber = 4;34	pub const Nominal: Balance = UNIQUE;35	// pub const Day: BlockNumber = DAYS;36	pub IntervalIncome: Perbill = Perbill::from_rational(RecalculationInterval::get(), RELAY_DAYS) * Perbill::from_rational(5u32, 10_000);37}3839#[cfg(any(feature = "unique-runtime", feature = "quartz-runtime"))]40parameter_types! {41	pub const AppPromotionId: PalletId = PalletId(*b"appstake");42	pub const RecalculationInterval: BlockNumber = RELAY_DAYS;43	pub const PendingInterval: BlockNumber = 7 * RELAY_DAYS;44	pub const Nominal: Balance = UNIQUE;45	// pub const Day: BlockNumber = RELAY_DAYS;46	pub IntervalIncome: Perbill = Perbill::from_rational(5u32, 10_000);47}4849impl pallet_app_promotion::Config for Runtime {50	type PalletId = AppPromotionId;51	type CollectionHandler = Unique;52	type ContractHandler = EvmContractHelpers;53	type Currency = Balances;54	type WeightInfo = pallet_app_promotion::weights::SubstrateWeight<Self>;55	type TreasuryAccountId = TreasuryAccountId;56	type RelayBlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;57	type RecalculationInterval = RecalculationInterval;58	type PendingInterval = PendingInterval;59	// type Day = Day;60	type Nominal = Nominal;61	type IntervalIncome = IntervalIncome;62	type RuntimeEvent = RuntimeEvent;63}
modifiedtests/src/app-promotion.test.tsdiffbeforeafterboth
--- 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) {