From 629dcfdc7495faf0427df20fb58e47fb05bccd01 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 16 May 2023 14:17:42 +0200 Subject: [PATCH] feat: add block rewards to altair and centrifuge runtimes (#1342) * feat: add ED funding to rewards pallet * feat: apply reward genesis config to dev runtime * tests: apply rewards ED to block rewards * tests: add sanity intgr block rewards check * feat: add block rewards to altair runtime * feat: add block rewards to cfg runtime * docs: improve blk rw migraton com * feat: reduce collator kick threshold to 2 hours * Revert "feat: reduce collator kick threshold to 2 hours" This reverts commit afc4d54d57474f014807d49f2091bb2637e114ff. * fix: re-enable transfer keep alive * fix: chain_spec * refactor: move rewards migration * feat: add session key migration * fix: mixed up tokens in spec * refactor: rm dev migrations * bench: fix block rewards * refactor: move migrations to sep file * refactor: block rewards pallet id * refactor: improve pallet genesis build err log * refactor: remove rewards domain concept (#1344) * refactor: remove rewards domain concept * refactor: rm dev migrations * refactor: remove DOM * bench: fix block rewards * fix: RewardsApi * refactor: rename LiquidityRewardsBase * tests: add block rewards RAPI int * clippy: remove unused * fmt: taplo * fix: dev chainspec after renaming * refactor: apply suggestion from code review * Update runtime/centrifuge/src/lib.rs Co-authored-by: Frederik Gartenmeister --------- Co-authored-by: Frederik Gartenmeister --- Cargo.lock | 8 + libs/types/src/ids.rs | 1 + pallets/block-rewards/src/benchmarking.rs | 10 +- pallets/block-rewards/src/lib.rs | 38 +--- pallets/block-rewards/src/migrations.rs | 15 +- pallets/block-rewards/src/mock.rs | 28 +-- pallets/block-rewards/src/tests.rs | 84 +++----- pallets/liquidity-rewards/src/lib.rs | 24 +-- pallets/liquidity-rewards/src/mock.rs | 6 +- pallets/liquidity-rewards/src/tests.rs | 3 +- pallets/rewards/Cargo.toml | 2 + pallets/rewards/src/lib.rs | 93 ++++++--- .../rewards/src/migrations/new_instance.rs | 82 ++++++++ pallets/rewards/src/mock.rs | 9 +- pallets/rewards/src/tests.rs | 76 ++++--- pallets/rewards/src/tests/command_based.rs | 58 +++--- pallets/rewards/src/tests/common.rs | 195 +++++++----------- .../rewards/src/tests/currency_movement.rs | 133 ++++++------ runtime/altair/Cargo.toml | 10 + runtime/altair/src/lib.rs | 104 +++++++++- runtime/altair/src/migrations.rs | 147 +++++++++++++ runtime/altair/src/weights/mod.rs | 3 + .../src/weights/pallet_block_rewards.rs | 58 ++++++ .../src/weights/pallet_collator_selection.rs | 108 ++++++++++ runtime/altair/src/weights/pallet_session.rs | 49 +++++ runtime/centrifuge/Cargo.toml | 10 + runtime/centrifuge/src/lib.rs | 104 +++++++++- runtime/centrifuge/src/migrations.rs | 144 +++++++++++++ runtime/centrifuge/src/weights/mod.rs | 2 + .../src/weights/pallet_block_rewards.rs | 58 ++++++ .../centrifuge/src/weights/pallet_session.rs | 49 +++++ runtime/common/Cargo.toml | 2 + runtime/common/src/apis/rewards.rs | 18 +- runtime/development/src/lib.rs | 63 ++---- .../src/rewards/block/env.rs | 13 ++ .../src/rewards/block/invariants.rs | 12 +- .../src/rewards/block/session_advances.rs | 15 +- .../src/runtime_apis/rewards.rs | 85 ++++---- src/chain_spec.rs | 46 ++++- src/rpc/rewards.rs | 27 +-- 40 files changed, 1417 insertions(+), 575 deletions(-) create mode 100644 pallets/rewards/src/migrations/new_instance.rs create mode 100644 runtime/altair/src/migrations.rs create mode 100644 runtime/altair/src/weights/pallet_block_rewards.rs create mode 100644 runtime/altair/src/weights/pallet_collator_selection.rs create mode 100644 runtime/altair/src/weights/pallet_session.rs create mode 100644 runtime/centrifuge/src/migrations.rs create mode 100644 runtime/centrifuge/src/weights/pallet_block_rewards.rs create mode 100644 runtime/centrifuge/src/weights/pallet_session.rs diff --git a/Cargo.lock b/Cargo.lock index eda6f95db9..377bd0b7fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,6 +186,7 @@ dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-primitives-core", @@ -209,6 +210,7 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-block-rewards", "pallet-collator-allowlist", "pallet-collator-selection", "pallet-collective", @@ -231,6 +233,7 @@ dependencies = [ "pallet-proxy", "pallet-randomness-collective-flip", "pallet-restricted-tokens", + "pallet-rewards", "pallet-scheduler", "pallet-session", "pallet-timestamp", @@ -1063,6 +1066,7 @@ dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-primitives-core", @@ -1086,6 +1090,7 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-block-rewards", "pallet-bridge", "pallet-claims", "pallet-collator-allowlist", @@ -1111,6 +1116,7 @@ dependencies = [ "pallet-proxy", "pallet-randomness-collective-flip", "pallet-restricted-tokens", + "pallet-rewards", "pallet-scheduler", "pallet-session", "pallet-timestamp", @@ -7812,6 +7818,7 @@ dependencies = [ "frame-support", "frame-system", "lazy_static", + "log", "num-traits", "orml-tokens", "orml-traits", @@ -10567,6 +10574,7 @@ dependencies = [ "pallet-treasury", "parity-scale-codec 3.4.0", "scale-info", + "serde", "smallvec", "sp-api", "sp-arithmetic", diff --git a/libs/types/src/ids.rs b/libs/types/src/ids.rs index 39f15c3f5e..8f20fba12f 100644 --- a/libs/types/src/ids.rs +++ b/libs/types/src/ids.rs @@ -32,6 +32,7 @@ pub const CROWDLOAN_CLAIM_PALLET_ID: PalletId = PalletId(*b"cc/claim"); pub const TREASURY_PALLET_ID: PalletId = PalletId(*b"py/trsry"); pub const NFT_SALES_PALLET_ID: PalletId = PalletId(*b"pal/nfts"); pub const STAKE_POT_PALLET_ID: PalletId = PalletId(*b"PotStake"); +pub const BLOCK_REWARDS_PALLET_ID: PalletId = PalletId(*b"cfg/blrw"); // Other ids pub const CHAIN_BRIDGE_HASH_ID: [u8; 13] = *b"cent_nft_hash"; diff --git a/pallets/block-rewards/src/benchmarking.rs b/pallets/block-rewards/src/benchmarking.rs index ac11c8bde0..e1b750dce3 100644 --- a/pallets/block-rewards/src/benchmarking.rs +++ b/pallets/block-rewards/src/benchmarking.rs @@ -33,10 +33,7 @@ benchmarks! { assert!(T::Rewards::is_ready(T::StakeGroupId::get())); assert!( !T::Rewards::compute_reward( - ( - T::Domain::get(), - T::StakeCurrencyId::get(), - ), + T::StakeCurrencyId::get(), &beneficiary, ).unwrap().is_zero() ); @@ -44,8 +41,11 @@ benchmarks! { }: _(RawOrigin::Signed(caller), beneficiary.clone()) verify { + let num_collators: u128 = BlockRewards::::next_session_changes().collator_count.unwrap_or( + BlockRewards::::active_session_data().collator_count + ).into(); // Does not get entire reward since another collator is auto-staked via genesis config - assert_eq!(::Currency::balance(CurrencyId::Native.into(), &beneficiary).saturating_sub(before), (REWARD / 2).into()); + assert_eq!(::Currency::balance(CurrencyId::Native.into(), &beneficiary).saturating_sub(before), (REWARD / (num_collators + 1)).into()); } set_collator_reward { diff --git a/pallets/block-rewards/src/lib.rs b/pallets/block-rewards/src/lib.rs index e6dea1fce6..fc4af91359 100644 --- a/pallets/block-rewards/src/lib.rs +++ b/pallets/block-rewards/src/lib.rs @@ -104,7 +104,6 @@ pub struct SessionChanges { total_reward: Option, } -pub(crate) type DomainIdOf = <::Domain as TypedGet>::Type; pub(crate) type NegativeImbalanceOf = <::Currency as CurrencyT< ::AccountId, >>::NegativeImbalance; @@ -131,9 +130,6 @@ pub mod pallet { + Into<<::Currency as CurrencyT>::Balance> + MaybeSerializeDeserialize; - /// Domain identification used by this pallet - type Domain: TypedGet; - /// Type used to handle group weights. type Weight: Parameter + MaxEncodedLen + EnsureAdd + Unsigned + FixedPointOperand + Default; @@ -142,11 +138,8 @@ pub mod pallet { + AccountRewards< Self::AccountId, Balance = Self::Balance, - CurrencyId = (DomainIdOf, ::CurrencyId), - > + CurrencyGroupChange< - GroupId = u32, - CurrencyId = (DomainIdOf, ::CurrencyId), - >; + CurrencyId = ::CurrencyId, + > + CurrencyGroupChange::CurrencyId>; /// The type used to handle currency minting and burning for collators. type Currency: Mutate::CurrencyId, Balance = Self::Balance> @@ -258,12 +251,9 @@ pub mod pallet { #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - T::Rewards::attach_currency( - (T::Domain::get(), T::StakeCurrencyId::get()), - T::StakeGroupId::get(), - ) - .map_err(|e| log::error!("Failed to attach currency to collator group: {:?}", e)) - .ok(); + T::Rewards::attach_currency(T::StakeCurrencyId::get(), T::StakeGroupId::get()).expect( + "Should be able to attach default block rewards staking currency to collator group", + ); ActiveSessionData::::mutate(|session_data| { session_data.collator_count = self.collators.len().saturated_into(); @@ -274,10 +264,7 @@ pub mod pallet { // Enables rewards already in genesis session. for collator in &self.collators { Pallet::::do_init_collator(collator) - .map_err(|e| { - log::error!("Failed to init genesis collators for rewards: {:?}", e); - }) - .ok(); + .expect("Should not panic when initiating genesis collators for block rewards"); } } } @@ -291,8 +278,7 @@ pub mod pallet { pub fn claim_reward(origin: OriginFor, account_id: T::AccountId) -> DispatchResult { ensure_signed(origin)?; - T::Rewards::claim_reward((T::Domain::get(), T::StakeCurrencyId::get()), &account_id) - .map(|_| ()) + T::Rewards::claim_reward(T::StakeCurrencyId::get(), &account_id).map(|_| ()) } /// Admin method to set the reward amount for a collator used for the @@ -369,18 +355,14 @@ impl Pallet { /// Account pub(crate) fn do_init_collator(who: &T::AccountId) -> DispatchResult { T::Currency::mint_into(T::StakeCurrencyId::get(), who, T::StakeAmount::get())?; - T::Rewards::deposit_stake( - (T::Domain::get(), T::StakeCurrencyId::get()), - who, - T::StakeAmount::get(), - ) + T::Rewards::deposit_stake(T::StakeCurrencyId::get(), who, T::StakeAmount::get()) } /// Withdraw currently staked amount for target address and immediately burn /// it. Disables receiving rewards onwards. pub(crate) fn do_exit_collator(who: &T::AccountId) -> DispatchResult { - let amount = T::Rewards::account_stake((T::Domain::get(), T::StakeCurrencyId::get()), who); - T::Rewards::withdraw_stake((T::Domain::get(), T::StakeCurrencyId::get()), who, amount)?; + let amount = T::Rewards::account_stake(T::StakeCurrencyId::get(), who); + T::Rewards::withdraw_stake(T::StakeCurrencyId::get(), who, amount)?; T::Currency::burn_from(T::StakeCurrencyId::get(), who, amount).map(|_| ()) } diff --git a/pallets/block-rewards/src/migrations.rs b/pallets/block-rewards/src/migrations.rs index 8160f19d73..2b01ffc4ce 100644 --- a/pallets/block-rewards/src/migrations.rs +++ b/pallets/block-rewards/src/migrations.rs @@ -17,7 +17,7 @@ use frame_support::{ pallet_prelude::{StorageVersion, Weight}, traits::{Get, OnRuntimeUpgrade}, }; -use sp_runtime::{traits::TypedGet, BoundedVec, SaturatedConversion}; +use sp_runtime::{BoundedVec, SaturatedConversion}; use sp_std::marker::PhantomData; #[cfg(feature = "try-runtime")] use { @@ -84,10 +84,7 @@ where weight.saturating_accrue(T::DbWeight::get().reads(2)); ::Rewards::attach_currency( - ( - ::Domain::get(), - ::StakeCurrencyId::get(), - ), + ::StakeCurrencyId::get(), ::StakeGroupId::get(), ) .map_err(|e| log::error!("Failed to attach currency to collator group: {:?}", e)) @@ -101,8 +98,7 @@ where weight.saturating_accrue(T::DbWeight::get().writes(1)); for collator in collators.iter() { - // TODO: Benching preferred to be precise. - // However, not necessarily needed as num of collators <= 10. + // NOTE: Benching not required as num of collators <= 10. Pallet::::do_init_collator(collator) .map_err(|e| { log::error!("Failed to init genesis collators for rewards: {:?}", e); @@ -142,10 +138,7 @@ where for collator in collators.iter() { assert!(!::Rewards::account_stake( - ( - ::Domain::get(), - ::StakeCurrencyId::get(), - ), + ::StakeCurrencyId::get(), collator, ) .is_zero()) diff --git a/pallets/block-rewards/src/mock.rs b/pallets/block-rewards/src/mock.rs index 21464a1075..70140abd3e 100644 --- a/pallets/block-rewards/src/mock.rs +++ b/pallets/block-rewards/src/mock.rs @@ -1,6 +1,5 @@ use cfg_traits::rewards::AccountRewards; use cfg_types::tokens::{CurrencyId, StakingCurrency::BlockRewards as BlockRewardsCurrency}; -use codec::MaxEncodedLen; use frame_support::{ parameter_types, traits::{ @@ -115,7 +114,7 @@ impl pallet_session::Config for Test { } parameter_types! { - pub const ExistentialDeposit: Balance = 0; + pub const ExistentialDeposit: Balance = 1; } impl pallet_balances::Config for Test { type AccountStore = System; @@ -182,16 +181,8 @@ impl pallet_restricted_tokens::Config for Test { type WeightInfo = (); } -#[derive( - scale_info::TypeInfo, Debug, Copy, codec::Encode, codec::Decode, PartialEq, Clone, MaxEncodedLen, -)] -pub enum RewardDomain { - Liquidity, - Block, -} - frame_support::parameter_types! { - pub const RewardsPalletId: PalletId = PalletId(*b"d/reward"); + pub const RewardsPalletId: PalletId = cfg_types::ids::BLOCK_REWARDS_PALLET_ID; pub const NativeToken: CurrencyId = CurrencyId::Native; #[derive(scale_info::TypeInfo)] @@ -201,7 +192,6 @@ frame_support::parameter_types! { impl pallet_rewards::Config for Test { type Currency = Tokens; type CurrencyId = CurrencyId; - type DomainId = RewardDomain; type GroupId = u32; type PalletId = RewardsPalletId; type RewardCurrency = NativeToken; @@ -227,7 +217,6 @@ frame_support::parameter_types! { pub const MaxChangesPerSession: u32 = 50; #[derive(scale_info::TypeInfo, Debug, PartialEq, Clone)] pub const MaxCollators: u32 = MAX_COLLATORS; - pub const BlockRewardsDomain: RewardDomain = RewardDomain::Block; pub const BlockRewardCurrency: CurrencyId = CurrencyId::Staking(BlockRewardsCurrency); pub const StakeAmount: Balance = cfg_types::consts::rewards::DEFAULT_COLLATOR_STAKE; pub const CollatorGroupId: u32 = cfg_types::ids::COLLATOR_GROUP_ID; @@ -240,7 +229,6 @@ impl pallet_block_rewards::Config for Test { type Beneficiary = RewardRemainderMock; type Currency = Tokens; type CurrencyId = CurrencyId; - type Domain = BlockRewardsDomain; type MaxChangesPerSession = MaxChangesPerSession; type MaxCollators = MaxCollators; type Rewards = Rewards; @@ -265,10 +253,7 @@ pub(crate) fn assert_staked(who: &AccountId) { pub(crate) fn assert_not_staked(who: &AccountId) { assert!(::Rewards::account_stake( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), who ) .is_zero()); @@ -378,6 +363,13 @@ impl ExtBuilder { .assimilate_storage(&mut storage) .expect("Session pallet's storage can be assimilated"); + pallet_rewards::GenesisConfig:: { + currency_id: CurrencyId::Native, + amount: ExistentialDeposit::get(), + } + .assimilate_storage(&mut storage) + .expect("Rewards pallet's storage can be assimilated"); + let mut ext = sp_io::TestExternalities::new(storage); ext.execute_with(|| { diff --git a/pallets/block-rewards/src/tests.rs b/pallets/block-rewards/src/tests.rs index 087360c3b6..921f4d6170 100644 --- a/pallets/block-rewards/src/tests.rs +++ b/pallets/block-rewards/src/tests.rs @@ -268,10 +268,7 @@ fn single_claim_reward() { ); assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &1 ), Ok(REWARD) @@ -280,14 +277,16 @@ fn single_claim_reward() { System::assert_last_event(mock::RuntimeEvent::Rewards( pallet_rewards::Event::RewardClaimed { group_id: ::StakeGroupId::get(), - domain_id: ::Domain::get(), currency_id: ::StakeCurrencyId::get(), account_id: 1, amount: REWARD, }, )); assert_eq!(Balances::total_balance(&TREASURY_ADDRESS), 9 * REWARD); - assert_eq!(Balances::total_issuance(), 10 * REWARD); + assert_eq!( + Balances::total_issuance(), + 10 * REWARD + ExistentialDeposit::get() + ); assert_eq!(Balances::free_balance(&1), REWARD); }); } @@ -306,15 +305,15 @@ fn collator_rewards_greater_than_remainder() { // Thus, equal distribution of total_reward to collator and Treasury. assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &1 ), Ok(REWARD) ); - assert_eq!(Balances::total_issuance(), 2 * REWARD); + assert_eq!( + Balances::total_issuance(), + 2 * REWARD + ExistentialDeposit::get() + ); assert_eq!(Balances::total_balance(&TREASURY_ADDRESS), REWARD); // EPOCH 1 -> EPOCH 2 @@ -324,16 +323,16 @@ fn collator_rewards_greater_than_remainder() { // Thus, equal distribution of total_reward to collator and Treasury. assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &1 ), Ok(2 * REWARD) ); assert_eq!(Balances::total_balance(&TREASURY_ADDRESS), 2 * REWARD); - assert_eq!(Balances::total_issuance(), 4 * REWARD); + assert_eq!( + Balances::total_issuance(), + 4 * REWARD + ExistentialDeposit::get() + ); // EPOCH 2 -> EPOCH 3 advance_session(); @@ -343,10 +342,7 @@ fn collator_rewards_greater_than_remainder() { // Additionally, 1 should not have higher claimable reward. assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &1 ), Ok(2 * REWARD) @@ -354,17 +350,17 @@ fn collator_rewards_greater_than_remainder() { for collator in [2, 3].iter() { assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), collator ), Ok(REWARD) ); } assert_eq!(Balances::total_balance(&TREASURY_ADDRESS), 2 * REWARD); - assert_eq!(Balances::total_issuance(), 6 * REWARD); + assert_eq!( + Balances::total_issuance(), + 6 * REWARD + ExistentialDeposit::get() + ); // EPOCH 3 -> EPOCH 4 advance_session(); @@ -374,36 +370,30 @@ fn collator_rewards_greater_than_remainder() { // and reseive less than collator_reward each. assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &3 ), Ok(REWARD + 2 * REWARD / 3) ); assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &4 ), Ok(2 * REWARD / 3) ); assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &5 ), Ok(2 * REWARD / 3) ); assert_eq!(Balances::total_balance(&TREASURY_ADDRESS), 2 * REWARD); - assert_eq!(Balances::total_issuance(), 8 * REWARD); + assert_eq!( + Balances::total_issuance(), + 8 * REWARD + ExistentialDeposit::get() + ); }); } @@ -417,10 +407,7 @@ fn late_claiming_works() { .execute_with(|| { assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &2 ), Ok(REWARD) @@ -429,7 +416,6 @@ fn late_claiming_works() { System::assert_last_event(mock::RuntimeEvent::Rewards( pallet_rewards::Event::RewardClaimed { group_id: ::StakeGroupId::get(), - domain_id: ::Domain::get(), currency_id: ::StakeCurrencyId::get(), account_id: 2, amount: REWARD, @@ -448,10 +434,7 @@ fn duplicate_claiming_works_but_ineffective() { .execute_with(|| { assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &2 ), Ok(REWARD) @@ -460,7 +443,6 @@ fn duplicate_claiming_works_but_ineffective() { System::assert_last_event(mock::RuntimeEvent::Rewards( pallet_rewards::Event::RewardClaimed { group_id: ::StakeGroupId::get(), - domain_id: ::Domain::get(), currency_id: ::StakeCurrencyId::get(), account_id: 2, amount: REWARD, @@ -469,10 +451,7 @@ fn duplicate_claiming_works_but_ineffective() { assert_eq!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get() - ), + ::StakeCurrencyId::get(), &2 ), Ok(0) @@ -481,7 +460,6 @@ fn duplicate_claiming_works_but_ineffective() { System::assert_last_event(mock::RuntimeEvent::Rewards( pallet_rewards::Event::RewardClaimed { group_id: ::StakeGroupId::get(), - domain_id: ::Domain::get(), currency_id: ::StakeCurrencyId::get(), account_id: 2, amount: 0, diff --git a/pallets/liquidity-rewards/src/lib.rs b/pallets/liquidity-rewards/src/lib.rs index a6376bf3ad..a5c583efb1 100644 --- a/pallets/liquidity-rewards/src/lib.rs +++ b/pallets/liquidity-rewards/src/lib.rs @@ -90,8 +90,6 @@ pub struct EpochChanges { currencies: BoundedBTreeMap, } -pub type DomainIdOf = <::Domain as TypedGet>::Type; - #[frame_support::pallet] pub mod pallet { use super::*; @@ -107,9 +105,6 @@ pub mod pallet { /// Type used to handle balances. type Balance: Balance + MaxEncodedLen + FixedPointOperand; - /// Domain identification used by this pallet - type Domain: TypedGet; - /// Type used to identify currencies. type CurrencyId: AssetId + MaxEncodedLen + Clone + Ord; @@ -121,14 +116,9 @@ pub mod pallet { /// The reward system used. type Rewards: GroupRewards - + AccountRewards< - Self::AccountId, - Balance = Self::Balance, - CurrencyId = (DomainIdOf, Self::CurrencyId), - > + CurrencyGroupChange< - GroupId = Self::GroupId, - CurrencyId = (DomainIdOf, Self::CurrencyId), - > + DistributedRewards; + + AccountRewards + + CurrencyGroupChange + + DistributedRewards; /// Max groups used by this pallet. /// If this limit is reached, the exceeded groups are either not @@ -220,7 +210,7 @@ pub mod pallet { } for (¤cy_id, &group_id) in &changes.currencies { - T::Rewards::attach_currency((T::Domain::get(), currency_id), group_id)?; + T::Rewards::attach_currency(currency_id, group_id)?; currency_changes += 1; } @@ -262,7 +252,7 @@ pub mod pallet { ) -> DispatchResult { let account_id = ensure_signed(origin)?; - T::Rewards::deposit_stake((T::Domain::get(), currency_id), &account_id, amount) + T::Rewards::deposit_stake(currency_id, &account_id, amount) } /// Withdraw a stake amount associated to a currency for the origin's @@ -278,7 +268,7 @@ pub mod pallet { ) -> DispatchResult { let account_id = ensure_signed(origin)?; - T::Rewards::withdraw_stake((T::Domain::get(), currency_id), &account_id, amount) + T::Rewards::withdraw_stake(currency_id, &account_id, amount) } /// Claims the reward the associated to a currency. @@ -289,7 +279,7 @@ pub mod pallet { pub fn claim_reward(origin: OriginFor, currency_id: T::CurrencyId) -> DispatchResult { let account_id = ensure_signed(origin)?; - T::Rewards::claim_reward((T::Domain::get(), currency_id), &account_id).map(|_| ()) + T::Rewards::claim_reward(currency_id, &account_id).map(|_| ()) } /// Admin method to set the reward amount used for the next epochs. diff --git a/pallets/liquidity-rewards/src/mock.rs b/pallets/liquidity-rewards/src/mock.rs index ae2cbb0ecc..315ff7b9de 100644 --- a/pallets/liquidity-rewards/src/mock.rs +++ b/pallets/liquidity-rewards/src/mock.rs @@ -8,7 +8,6 @@ use sp_runtime::{ use crate as pallet_liquidity_rewards; -pub const DOMAIN: u8 = 23; pub const INITIAL_EPOCH_DURATION: u64 = 23; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -59,13 +58,11 @@ frame_support::parameter_types! { #[derive(scale_info::TypeInfo, Debug, PartialEq, Clone)] pub const MaxChangesPerEpoch: u32 = 50; - - pub const LiquidityDomain: u8 = DOMAIN; } impl cfg_mocks::pallet_mock_rewards::Config for Test { type Balance = u64; - type CurrencyId = (u8, u32); + type CurrencyId = u32; type GroupId = u32; } @@ -73,7 +70,6 @@ impl pallet_liquidity_rewards::Config for Test { type AdminOrigin = EnsureRoot; type Balance = u64; type CurrencyId = u32; - type Domain = LiquidityDomain; type GroupId = u32; type InitialEpochDuration = ConstU64; type MaxChangesPerEpoch = MaxChangesPerEpoch; diff --git a/pallets/liquidity-rewards/src/tests.rs b/pallets/liquidity-rewards/src/tests.rs index 003120dfee..fedc9aa68d 100644 --- a/pallets/liquidity-rewards/src/tests.rs +++ b/pallets/liquidity-rewards/src/tests.rs @@ -147,8 +147,7 @@ fn currency_changes() { Some(&GROUP_A) ); - MockRewards::mock_attach_currency(|(domain, currency_id), group_id| { - assert_eq!(domain, DOMAIN); + MockRewards::mock_attach_currency(|currency_id, group_id| { assert_eq!(currency_id, CURRENCY_ID_A); assert_eq!(group_id, GROUP_A); Ok(()) diff --git a/pallets/rewards/Cargo.toml b/pallets/rewards/Cargo.toml index 2f4788a70b..e5d3d693dd 100644 --- a/pallets/rewards/Cargo.toml +++ b/pallets/rewards/Cargo.toml @@ -17,6 +17,7 @@ cfg-types = { path = "../../libs/types", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.37" } frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.37" } +log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.3.0", default-features = false, features = ["derive"] } sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.37" } @@ -42,6 +43,7 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "log/std", "sp-runtime/std", "sp-std/std", "cfg-traits/std", diff --git a/pallets/rewards/src/lib.rs b/pallets/rewards/src/lib.rs index d430741ca0..bceda8a053 100644 --- a/pallets/rewards/src/lib.rs +++ b/pallets/rewards/src/lib.rs @@ -34,9 +34,6 @@ //! //! - **Currency ID**: Identification of a token used to stake/unstake. This ID //! is associated to a group. -//! - **Domain ID**: Identification of a domain. A domain acts as a prefix for a -//! currency id. It allows to have the same currency in different reward -//! groups. //! - **Reward**: The amount given in native tokens to a proportional amount of //! currency staked. //! - **Group**: A shared resource where the reward is distributed. The accounts @@ -51,6 +48,12 @@ //! //! The Rewards pallet provides implementations for the Rewards trait. //! +//! ### Assumptions +//! +//! Each consuming reward system must have its unique instance of this pallet +//! independent of the underlying reward mechanism. E.g., one instance for Block +//! Rewards and another for Liquidity Rewards. +//! //! ### Functionality //! //! The exact reward functionality of this pallet is given by the mechanism used @@ -69,13 +72,16 @@ mod tests; pub mod issuance; pub mod mechanism; +pub mod migrations { + pub mod new_instance; +} use cfg_traits::rewards::{AccountRewards, CurrencyGroupChange, GroupRewards, RewardIssuance}; use codec::FullCodec; use frame_support::{ pallet_prelude::*, traits::{ - fungibles::{InspectHold, Mutate, MutateHold, Transfer}, + fungibles::{Inspect, InspectHold, Mutate, MutateHold, Transfer}, tokens::AssetId, }, PalletId, @@ -106,11 +112,8 @@ pub mod pallet { #[pallet::constant] type PalletId: Get; - /// Type used to identify domains. - type DomainId: TypeInfo + MaxEncodedLen + FullCodec + Copy + PartialEq + Debug; - /// Type used to identify currencies. - type CurrencyId: AssetId + MaxEncodedLen; + type CurrencyId: AssetId + MaxEncodedLen + MaybeSerializeDeserialize + Default; /// Identifier for the currency used to give the reward. type RewardCurrency: Get; @@ -120,7 +123,8 @@ pub mod pallet { /// Type used to handle currency transfers and reservations. type Currency: MutateHold> - + Mutate>; + + Mutate> + + Inspect>; /// Specify the internal reward mechanism used by this pallet. /// Check available mechanisms at [`mechanism`] module. @@ -138,6 +142,43 @@ pub mod pallet { #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); + #[pallet::genesis_config] + pub struct GenesisConfig, I: 'static = ()> + where + BalanceOf: MaybeSerializeDeserialize, + { + pub currency_id: T::CurrencyId, + pub amount: BalanceOf, + } + + #[cfg(feature = "std")] + impl, I: 'static> Default for GenesisConfig + where + BalanceOf: MaybeSerializeDeserialize, + { + fn default() -> Self { + Self { + currency_id: Default::default(), + amount: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl, I: 'static> GenesisBuild for GenesisConfig + where + BalanceOf: MaybeSerializeDeserialize, + { + fn build(&self) { + T::Currency::mint_into( + self.currency_id, + &T::PalletId::get().into_account_truncating(), + self.amount, + ) + .expect("Should not fail to mint ED for rewards sovereign pallet account"); + } + } + // -------------------------- // Storage // -------------------------- @@ -149,7 +190,7 @@ pub mod pallet { = StorageMap< _, Blake2_128Concat, - (T::DomainId, T::CurrencyId), + T::CurrencyId, (Option, RewardCurrencyOf), ValueQuery, >; @@ -169,7 +210,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Blake2_128Concat, - (T::DomainId, T::CurrencyId), + T::CurrencyId, RewardAccountOf, ValueQuery, >; @@ -185,27 +226,23 @@ pub mod pallet { }, StakeDeposited { group_id: T::GroupId, - domain_id: T::DomainId, currency_id: T::CurrencyId, account_id: T::AccountId, amount: BalanceOf, }, StakeWithdrawn { group_id: T::GroupId, - domain_id: T::DomainId, currency_id: T::CurrencyId, account_id: T::AccountId, amount: BalanceOf, }, RewardClaimed { group_id: T::GroupId, - domain_id: T::DomainId, currency_id: T::CurrencyId, account_id: T::AccountId, amount: BalanceOf, }, CurrencyAttached { - domain_id: T::DomainId, currency_id: T::CurrencyId, from: Option, to: T::GroupId, @@ -270,7 +307,7 @@ pub mod pallet { RewardCurrencyOf: FullCodec + Default, { type Balance = BalanceOf; - type CurrencyId = (T::DomainId, T::CurrencyId); + type CurrencyId = T::CurrencyId; fn deposit_stake( currency_id: Self::CurrencyId, @@ -282,18 +319,17 @@ pub mod pallet { Group::::try_mutate(group_id, |group| { StakeAccount::::try_mutate(account_id, currency_id, |account| { - if !T::Currency::can_hold(currency_id.1, account_id, amount) { + if !T::Currency::can_hold(currency_id, account_id, amount) { Err(TokenError::NoFunds)?; } T::RewardMechanism::deposit_stake(account, currency, group, amount)?; - T::Currency::hold(currency_id.1, account_id, amount)?; + T::Currency::hold(currency_id, account_id, amount)?; Self::deposit_event(Event::StakeDeposited { group_id, - domain_id: currency_id.0, - currency_id: currency_id.1, + currency_id, account_id: account_id.clone(), amount, }); @@ -320,12 +356,11 @@ pub mod pallet { T::RewardMechanism::withdraw_stake(account, currency, group, amount)?; - T::Currency::release(currency_id.1, account_id, amount, false)?; + T::Currency::release(currency_id, account_id, amount, false)?; Self::deposit_event(Event::StakeWithdrawn { group_id, - domain_id: currency_id.0, - currency_id: currency_id.1, + currency_id, account_id: account_id.clone(), amount, }); @@ -372,8 +407,7 @@ pub mod pallet { Self::deposit_event(Event::RewardClaimed { group_id, - domain_id: currency_id.0, - currency_id: currency_id.1, + currency_id, account_id: account_id.clone(), amount: reward, }); @@ -396,7 +430,7 @@ pub mod pallet { RewardGroupOf: FullCodec + Default, RewardCurrencyOf: FullCodec + Default, { - type CurrencyId = (T::DomainId, T::CurrencyId); + type CurrencyId = T::CurrencyId; type GroupId = T::GroupId; fn attach_currency( @@ -423,8 +457,7 @@ pub mod pallet { } Self::deposit_event(Event::CurrencyAttached { - domain_id: currency_id.0, - currency_id: currency_id.1, + currency_id, from: *group_id, to: next_group_id, }); @@ -444,9 +477,7 @@ pub mod pallet { where RewardAccountOf: FullCodec + Default, { - pub fn list_currencies( - account_id: &T::AccountId, - ) -> sp_std::vec::Vec<(T::DomainId, T::CurrencyId)> { + pub fn list_currencies(account_id: &T::AccountId) -> sp_std::vec::Vec { StakeAccount::::iter_prefix(account_id) .map(|(currency_id, _)| currency_id) .collect() diff --git a/pallets/rewards/src/migrations/new_instance.rs b/pallets/rewards/src/migrations/new_instance.rs new file mode 100644 index 0000000000..cb2a51bef2 --- /dev/null +++ b/pallets/rewards/src/migrations/new_instance.rs @@ -0,0 +1,82 @@ +// Copyright 2021 Centrifuge Foundation (centrifuge.io). +// +// This file is part of the Centrifuge chain project. +// Centrifuge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version (see http://www.gnu.org/licenses). +// Centrifuge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +use frame_support::traits::{ + fungibles::{Inspect, Mutate}, + Get, OnRuntimeUpgrade, +}; +use sp_runtime::traits::AccountIdConversion; +use sp_std::marker::PhantomData; +#[cfg(feature = "try-runtime")] +use {frame_support::inherent::Vec, sp_std::vec}; + +use crate::{BalanceOf, Config}; + +pub struct FundExistentialDeposit(PhantomData<(T, I, Currency, ED)>); + +fn pallet_is_funded() -> bool +where + T: Config, + I: 'static, + Currency: Get<>::CurrencyId>, + ED: Get>, +{ + let balance = <>::Currency as Inspect>::balance( + Currency::get(), + &>::PalletId::get().into_account_truncating(), + ); + balance >= ED::get() +} + +impl OnRuntimeUpgrade for FundExistentialDeposit +where + T: frame_system::Config + Config, + I: 'static, + Currency: Get<>::CurrencyId>, + ED: Get>, +{ + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + assert!(!pallet_is_funded::()); + + log::info!("💶 Rewards: Pre funding ED checks successful"); + Ok(vec![]) + } + + fn on_runtime_upgrade() -> frame_support::weights::Weight { + if !pallet_is_funded::() { + log::info!("💶 Rewards: Initiating ED funding to sovereign pallet account"); + T::Currency::mint_into( + Currency::get(), + &T::PalletId::get().into_account_truncating(), + ED::get(), + ) + .map_err(|_| log::error!("💶 Rewards: Failed to mint ED for sovereign pallet account",)) + .ok(); + + T::DbWeight::get().reads_writes(1, 1) + } else { + log::info!( + "💶 Rewards: ED funding for sovereign pallet account not required anymore. This probably should be removed" + ); + T::DbWeight::get().reads_writes(1, 0) + } + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_pre_state: Vec) -> Result<(), &'static str> { + assert!(pallet_is_funded::()); + + log::info!("💶 Rewards: Post funding ED checks successful"); + Ok(()) + } +} diff --git a/pallets/rewards/src/mock.rs b/pallets/rewards/src/mock.rs index a9c6bf48de..c2eb53c487 100644 --- a/pallets/rewards/src/mock.rs +++ b/pallets/rewards/src/mock.rs @@ -94,10 +94,10 @@ pub enum CurrencyId { M, } -#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen, RuntimeDebug)] -pub enum DomainId { - D1, - D2, +impl Default for CurrencyId { + fn default() -> Self { + CurrencyId::Reward + } } orml_traits::parameter_type_with_key! { @@ -148,7 +148,6 @@ macro_rules! pallet_rewards_config { impl pallet_rewards::Config for Runtime { type Currency = Tokens; type CurrencyId = CurrencyId; - type DomainId = DomainId; type GroupId = u32; type PalletId = RewardsPalletId; type RewardCurrency = RewardCurrency; diff --git a/pallets/rewards/src/tests.rs b/pallets/rewards/src/tests.rs index 031eecc3e3..23b1316f43 100644 --- a/pallets/rewards/src/tests.rs +++ b/pallets/rewards/src/tests.rs @@ -11,10 +11,10 @@ const GROUP_1: u32 = 1; const GROUP_2: u32 = 2; const GROUP_3: u32 = 3; -const DOM_1_CURRENCY_X: (DomainId, CurrencyId) = (DomainId::D1, CurrencyId::A); -const DOM_1_CURRENCY_Y: (DomainId, CurrencyId) = (DomainId::D1, CurrencyId::B); -const DOM_1_CURRENCY_Z: (DomainId, CurrencyId) = (DomainId::D1, CurrencyId::C); -const DOM_1_CURRENCY_M: (DomainId, CurrencyId) = (DomainId::D1, CurrencyId::M); +const CURRENCY_X: CurrencyId = CurrencyId::A; +const CURRENCY_Y: CurrencyId = CurrencyId::B; +const CURRENCY_Z: CurrencyId = CurrencyId::C; +const CURRENCY_M: CurrencyId = CurrencyId::M; const STAKE_A: u64 = 100; const STAKE_B: u64 = 200; @@ -124,15 +124,15 @@ mod mechanism { #[test] fn all_in() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Y, GROUP_2)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Z, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_Y, GROUP_2)); + assert_ok!($pallet::attach_currency(CURRENCY_Z, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_Y, &USER_B, STAKE_B)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_Y, &USER_B, STAKE_B)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), 0); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_Y, &USER_B), 0); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_Y, &USER_B), 0); // DISTRIBUTION 1 assert_ok!($pallet::distribute_reward( @@ -140,11 +140,11 @@ mod mechanism { [GROUP_1, GROUP_2, GROUP_3] )); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_Z, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_Z, &USER_A, STAKE_A)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), 0); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_Y, &USER_B), 0); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_Z, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_Y, &USER_B), 0); + assert_ok!($pallet::claim_reward(CURRENCY_Z, &USER_A), 0); // DISTRIBUTION 2 assert_ok!($pallet::distribute_reward( @@ -153,19 +153,15 @@ mod mechanism { )); // MOVEMENT Z - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Z, GROUP_2)); + assert_ok!($pallet::attach_currency(CURRENCY_Z, GROUP_2)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), REWARD / 2); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_Y, &USER_B), REWARD / 2); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_Z, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), REWARD / 2); + assert_ok!($pallet::claim_reward(CURRENCY_Y, &USER_B), REWARD / 2); + assert_ok!($pallet::claim_reward(CURRENCY_Z, &USER_A), 0); - assert_ok!($pallet::withdraw_stake( - DOM_1_CURRENCY_Z, - &USER_A, - STAKE_A / 2 - )); + assert_ok!($pallet::withdraw_stake(CURRENCY_Z, &USER_A, STAKE_A / 2)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_Z, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_Z, &USER_A), 0); // DISTRIBUTION 3 assert_ok!($pallet::distribute_reward( @@ -173,21 +169,21 @@ mod mechanism { [GROUP_1, GROUP_2, GROUP_3] )); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_1)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), REWARD / 2); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), REWARD / 2); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_Y, &USER_B), + $pallet::claim_reward(CURRENCY_Y, &USER_B), (REWARD / 2) * STAKE_B / (STAKE_A / 2 + STAKE_B) ); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_Z, &USER_A), + $pallet::claim_reward(CURRENCY_Z, &USER_A), (REWARD / 2) * (STAKE_A / 2) / (STAKE_A / 2 + STAKE_B) ); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_A)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_M, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_M, &USER_A), 0); // DISTRIBUTION 4 assert_ok!($pallet::distribute_reward( @@ -196,18 +192,18 @@ mod mechanism { )); // MOVEMENT X - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_2)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_2)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), REWARD / 2); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), REWARD / 2); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_Y, &USER_B), + $pallet::claim_reward(CURRENCY_Y, &USER_B), (REWARD / 2) * STAKE_B / (STAKE_A / 2 + STAKE_B) ); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_Z, &USER_A), + $pallet::claim_reward(CURRENCY_Z, &USER_A), (REWARD / 2) * (STAKE_A / 2) / (STAKE_A / 2 + STAKE_B) ); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_M, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_M, &USER_A), 0); // DISTRIBUTION 5 assert_ok!($pallet::distribute_reward( @@ -216,18 +212,18 @@ mod mechanism { )); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::claim_reward(CURRENCY_X, &USER_A), (REWARD / 2) * STAKE_A / (STAKE_A + STAKE_B + STAKE_A / 2) ); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_Y, &USER_B), + $pallet::claim_reward(CURRENCY_Y, &USER_B), (REWARD / 2) * STAKE_B / (STAKE_A + STAKE_B + STAKE_A / 2) ); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_Z, &USER_A), + $pallet::claim_reward(CURRENCY_Z, &USER_A), (REWARD / 2) * (STAKE_A / 2) / (STAKE_A + STAKE_B + STAKE_A / 2) ); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_M, &USER_A), REWARD / 2); + assert_ok!($pallet::claim_reward(CURRENCY_M, &USER_A), REWARD / 2); }); } }; diff --git a/pallets/rewards/src/tests/command_based.rs b/pallets/rewards/src/tests/command_based.rs index 0798308839..7236d2cb36 100644 --- a/pallets/rewards/src/tests/command_based.rs +++ b/pallets/rewards/src/tests/command_based.rs @@ -11,10 +11,10 @@ type Group = u32; #[derive(Clone)] enum Command { - AttachCurrency((DomainId, CurrencyId), Group), - Stake((DomainId, CurrencyId), Account, Balance), - Unstake((DomainId, CurrencyId), Account, Balance), - Claim((DomainId, CurrencyId), Account), + AttachCurrency(CurrencyId, Group), + Stake(CurrencyId, Account, Balance), + Unstake(CurrencyId, Account, Balance), + Claim(CurrencyId, Account), Distribute(Vec, Balance), } @@ -37,23 +37,23 @@ impl Default for TestState { impl TestState where Rewards: DistributedRewards - + AccountRewards, + + AccountRewards, { fn apply_command(&mut self, command: Command) -> DispatchResult { match command { - Command::AttachCurrency(dom_curr, group) => { - Rewards1::attach_currency(dom_curr, group)?; + Command::AttachCurrency(currency, group) => { + Rewards1::attach_currency(currency, group)?; } - Command::Stake(dom_curr, account, amount) => { - Rewards::deposit_stake(dom_curr, &account, amount)?; + Command::Stake(currency, account, amount) => { + Rewards::deposit_stake(currency, &account, amount)?; self.accounts_used.insert(account); } - Command::Unstake(dom_curr, account, amount) => { - Rewards::withdraw_stake(dom_curr, &account, amount)?; + Command::Unstake(currency, account, amount) => { + Rewards::withdraw_stake(currency, &account, amount)?; self.accounts_used.insert(account); } - Command::Claim(dom_curr, account) => { - Rewards::claim_reward(dom_curr, &account)?; + Command::Claim(currency, account) => { + Rewards::claim_reward(currency, &account)?; self.accounts_used.insert(account); } Command::Distribute(groups, reward) => { @@ -80,7 +80,7 @@ where fn evaluate_sample(commands: impl IntoIterator) where Rewards: DistributedRewards - + AccountRewards, + + AccountRewards, { new_test_ext().execute_with(|| { let mut state = TestState::::default(); @@ -105,31 +105,31 @@ where /// | claim | A, B | 2 | 4 | /// | distribute | - | 2 | 2 | /// -/// It uses 1 group, 1 domain and 1 currency. +/// It uses 1 group and 1 currency. /// It uses the `base` mechanism. #[test] fn silly_sample_for_fuzzer() { - const DOM_CURR: (DomainId, CurrencyId) = (DomainId::D1, CurrencyId::A); + const CURR: CurrencyId = CurrencyId::A; const AMOUNT_A1: u64 = 100; const AMOUNT_B1: u64 = 200; const AMOUNT_A2: u64 = 300; const AMOUNT_B2: u64 = 400; let commands = [ - Command::AttachCurrency(DOM_CURR, GROUP_1), - Command::Stake(DOM_CURR, USER_A, AMOUNT_A1), - Command::Stake(DOM_CURR, USER_A, AMOUNT_A2), - Command::Stake(DOM_CURR, USER_B, AMOUNT_B1), - Command::Stake(DOM_CURR, USER_B, AMOUNT_B2), + Command::AttachCurrency(CURR, GROUP_1), + Command::Stake(CURR, USER_A, AMOUNT_A1), + Command::Stake(CURR, USER_A, AMOUNT_A2), + Command::Stake(CURR, USER_B, AMOUNT_B1), + Command::Stake(CURR, USER_B, AMOUNT_B2), Command::Distribute(vec![GROUP_1], REWARD), - Command::Claim(DOM_CURR, USER_A), - Command::Claim(DOM_CURR, USER_B), - Command::Unstake(DOM_CURR, USER_A, AMOUNT_A1), - Command::Unstake(DOM_CURR, USER_A, AMOUNT_A2), - Command::Unstake(DOM_CURR, USER_B, AMOUNT_B1), - Command::Unstake(DOM_CURR, USER_B, AMOUNT_B2), - Command::Claim(DOM_CURR, USER_A), - Command::Claim(DOM_CURR, USER_B), + Command::Claim(CURR, USER_A), + Command::Claim(CURR, USER_B), + Command::Unstake(CURR, USER_A, AMOUNT_A1), + Command::Unstake(CURR, USER_A, AMOUNT_A2), + Command::Unstake(CURR, USER_B, AMOUNT_B1), + Command::Unstake(CURR, USER_B, AMOUNT_B2), + Command::Claim(CURR, USER_A), + Command::Claim(CURR, USER_B), Command::Distribute(vec![GROUP_1], REWARD), ]; diff --git a/pallets/rewards/src/tests/common.rs b/pallets/rewards/src/tests/common.rs index 63076a495b..751bfac520 100644 --- a/pallets/rewards/src/tests/common.rs +++ b/pallets/rewards/src/tests/common.rs @@ -11,8 +11,8 @@ macro_rules! stake_common_tests { new_test_ext().execute_with(|| { // DISTRIBUTION 0 - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_1)); assert_eq!( free_balance(CurrencyId::A, &USER_A), USER_INITIAL_BALANCE - STAKE_1 @@ -20,7 +20,7 @@ macro_rules! stake_common_tests { assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); // DISTRIBUTION 1 - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_2)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_2)); assert_eq!( free_balance(CurrencyId::A, &USER_A), USER_INITIAL_BALANCE - (STAKE_1 + STAKE_2) @@ -31,9 +31,9 @@ macro_rules! stake_common_tests { #[test] fn all() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); assert_ok!($pallet::deposit_stake( - DOM_1_CURRENCY_X, + CURRENCY_X, &USER_A, USER_INITIAL_BALANCE )); @@ -43,17 +43,17 @@ macro_rules! stake_common_tests { #[test] fn nothing() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, 0)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, 0)); }); } #[test] fn insufficient_balance() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); assert_noop!( - $pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, USER_INITIAL_BALANCE + 1), + $pallet::deposit_stake(CURRENCY_X, &USER_A, USER_INITIAL_BALANCE + 1), TokenError::NoFunds ); }); @@ -76,13 +76,9 @@ macro_rules! unstake_common_tests { new_test_ext().execute_with(|| { // DISTRIBUTION 0 - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_1)); - assert_ok!($pallet::withdraw_stake( - DOM_1_CURRENCY_X, - &USER_A, - UNSTAKE_1 - )); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_1)); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, UNSTAKE_1)); assert_eq!( free_balance(CurrencyId::A, &USER_A), USER_INITIAL_BALANCE - STAKE_1 + UNSTAKE_1 @@ -90,11 +86,7 @@ macro_rules! unstake_common_tests { assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); // DISTRIBUTION 1 - assert_ok!($pallet::withdraw_stake( - DOM_1_CURRENCY_X, - &USER_A, - UNSTAKE_2 - )); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, UNSTAKE_2)); assert_eq!(free_balance(CurrencyId::A, &USER_A), USER_INITIAL_BALANCE); }); } @@ -102,16 +94,16 @@ macro_rules! unstake_common_tests { #[test] fn insufficient_balance() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); assert_noop!( - $pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, 1), + $pallet::withdraw_stake(CURRENCY_X, &USER_A, 1), TokenError::NoFunds ); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, 1000)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, 1000)); assert_noop!( - $pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, 2000), + $pallet::withdraw_stake(CURRENCY_X, &USER_A, 2000), TokenError::NoFunds ); }); @@ -120,25 +112,25 @@ macro_rules! unstake_common_tests { #[test] fn exact() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, STAKE_A)); }); } #[test] fn nothing() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, 0)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, 0)); }); } #[test] fn several_users() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); assert_eq!( free_balance(CurrencyId::A, &USER_A), USER_INITIAL_BALANCE - STAKE_A @@ -146,24 +138,24 @@ macro_rules! unstake_common_tests { assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); // DISTRIBUTION 1 - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_B, STAKE_B)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_B, STAKE_B)); assert_eq!( free_balance(CurrencyId::A, &USER_B), USER_INITIAL_BALANCE - STAKE_B ); - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, STAKE_A)); assert_eq!(free_balance(CurrencyId::A, &USER_A), USER_INITIAL_BALANCE); - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_B, STAKE_B)); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_B, STAKE_B)); assert_eq!(free_balance(CurrencyId::A, &USER_B), USER_INITIAL_BALANCE); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); // DISTRIBUTION 2 assert_noop!( - $pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, 1), + $pallet::withdraw_stake(CURRENCY_X, &USER_A, 1), TokenError::NoFunds ); assert_noop!( - $pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_B, 1), + $pallet::withdraw_stake(CURRENCY_X, &USER_B, 1), TokenError::NoFunds ); }); @@ -182,19 +174,19 @@ macro_rules! currency_common_tests { fn use_without_group() { new_test_ext().execute_with(|| { assert_noop!( - $pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, 0), + $pallet::deposit_stake(CURRENCY_X, &USER_A, 0), Error::::CurrencyWithoutGroup ); assert_noop!( - $pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, 0), + $pallet::withdraw_stake(CURRENCY_X, &USER_A, 0), Error::::CurrencyWithoutGroup ); assert_noop!( - $pallet::compute_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::compute_reward(CURRENCY_X, &USER_A), Error::::CurrencyWithoutGroup ); assert_noop!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::claim_reward(CURRENCY_X, &USER_A), Error::::CurrencyWithoutGroup ); }); @@ -203,9 +195,9 @@ macro_rules! currency_common_tests { #[test] fn move_same_group_error() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); assert_noop!( - $pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1), + $pallet::attach_currency(CURRENCY_X, GROUP_1), Error::::CurrencyInSameGroup ); }); @@ -215,53 +207,22 @@ macro_rules! currency_common_tests { fn move_max_times() { new_test_ext().execute_with(|| { // First attach only attach the currency, does not move it. - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, 0)); + assert_ok!($pallet::attach_currency(CURRENCY_X, 0)); type Mechanism = >::RewardMechanism; type MaxMovements = ::MaxCurrencyMovements; // Waste all correct movements. for i in 0..::get() { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, i + 1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, i + 1)); } assert_noop!( - $pallet::attach_currency(DOM_1_CURRENCY_X, MaxCurrencyMovements::get() + 1), + $pallet::attach_currency(CURRENCY_X, MaxCurrencyMovements::get() + 1), Error::::CurrencyMaxMovementsReached ); }); } - - #[test] - fn different_domains() { - new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency( - (DomainId::D1, CurrencyId::A), - GROUP_1 - )); - assert_ok!($pallet::attach_currency( - (DomainId::D2, CurrencyId::A), - GROUP_1 - )); - - assert_ok!($pallet::deposit_stake( - (DomainId::D1, CurrencyId::A), - &USER_A, - STAKE_A - )); - - // There is enough reserved CurrencyId::A for USER_A, but in other domain. - assert_noop!( - $pallet::withdraw_stake((DomainId::D2, CurrencyId::A), &USER_A, STAKE_A), - TokenError::NoFunds - ); - assert_ok!($pallet::withdraw_stake( - (DomainId::D1, CurrencyId::A), - &USER_A, - STAKE_A - )); - }); - } } }; } @@ -275,19 +236,19 @@ macro_rules! claim_common_tests { #[test] fn nothing() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), 0); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), 0); assert_eq!( free_balance(CurrencyId::A, &USER_A), USER_INITIAL_BALANCE - STAKE_A ); assert_eq!(free_balance(CurrencyId::Reward, &USER_A), 0); - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), 0); assert_eq!(free_balance(CurrencyId::A, &USER_A), USER_INITIAL_BALANCE); assert_eq!(free_balance(CurrencyId::Reward, &USER_A), 0); }); @@ -296,9 +257,9 @@ macro_rules! claim_common_tests { #[test] fn basic() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); if $kind != MechanismKind::Base { @@ -310,44 +271,44 @@ macro_rules! claim_common_tests { choose_balance($kind, REWARD, REWARD * 2, REWARD) ); - assert_ok!($pallet::compute_reward(DOM_1_CURRENCY_X, &USER_A), REWARD); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), REWARD); + assert_ok!($pallet::compute_reward(CURRENCY_X, &USER_A), REWARD); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), REWARD); assert_eq!(free_balance(CurrencyId::Reward, &USER_A), REWARD); assert_eq!(rewards_account(), choose_balance($kind, 0, REWARD, 0)); - assert_ok!($pallet::compute_reward(DOM_1_CURRENCY_X, &USER_A), 0); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::compute_reward(CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), 0); }); } #[test] fn basic_with_unstake() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, STAKE_A)); let reward = choose_balance($kind, REWARD, 0, 0); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); - assert_ok!($pallet::compute_reward(DOM_1_CURRENCY_X, &USER_A), reward); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), reward); + assert_ok!($pallet::compute_reward(CURRENCY_X, &USER_A), reward); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), reward); assert_eq!(free_balance(CurrencyId::Reward, &USER_A), reward); assert_eq!(rewards_account(), choose_balance($kind, 0, REWARD, 0)); - assert_ok!($pallet::compute_reward(DOM_1_CURRENCY_X, &USER_A), 0); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::compute_reward(CURRENCY_X, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), 0); }); } #[test] fn distribute_claim_distribute_claim() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); if $kind != MechanismKind::Base { assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); @@ -361,8 +322,8 @@ macro_rules! claim_common_tests { choose_balance($kind, REWARD, REWARD * 2, REWARD) ); - assert_ok!($pallet::compute_reward(DOM_1_CURRENCY_X, &USER_A), REWARD); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), REWARD); + assert_ok!($pallet::compute_reward(CURRENCY_X, &USER_A), REWARD); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), REWARD); } assert_eq!(free_balance(CurrencyId::Reward, &USER_A), REWARD * 5); @@ -373,8 +334,8 @@ macro_rules! claim_common_tests { #[test] fn accumulative_claim() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); if $kind != MechanismKind::Base { assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); @@ -390,8 +351,8 @@ macro_rules! claim_common_tests { ); let reward = REWARD * 5; - assert_ok!($pallet::compute_reward(DOM_1_CURRENCY_X, &USER_A), reward); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), reward); + assert_ok!($pallet::compute_reward(CURRENCY_X, &USER_A), reward); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), reward); assert_eq!(free_balance(CurrencyId::Reward, &USER_A), reward); assert_eq!(rewards_account(), choose_balance($kind, 0, REWARD, 0)); @@ -406,22 +367,22 @@ macro_rules! claim_common_tests { fn claim_several_users() { new_test_ext().execute_with(|| { // DISTRIBUTION 0 - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); // DISTRIBUTION 1 - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_B, STAKE_B)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_B, STAKE_B)); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::claim_reward(CURRENCY_X, &USER_A), choose_balance($kind, REWARD, 0, 0) ); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_B), 0); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_B), 0); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); // DISTRIBUTION 2 assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::claim_reward(CURRENCY_X, &USER_A), choose_balance( $kind, REWARD * STAKE_A / (STAKE_A + STAKE_B), @@ -430,31 +391,31 @@ macro_rules! claim_common_tests { ) ); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_B), + $pallet::claim_reward(CURRENCY_X, &USER_B), choose_balance($kind, REWARD * STAKE_B / (STAKE_A + STAKE_B), 0, 0) ); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); // DISTRIBUTION 3 - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::claim_reward(CURRENCY_X, &USER_A), REWARD * STAKE_A / (STAKE_A + STAKE_B) ); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_B), + $pallet::claim_reward(CURRENCY_X, &USER_B), REWARD * STAKE_B / (STAKE_A + STAKE_B) ); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); // DISTRIBUTION 4 assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::claim_reward(CURRENCY_X, &USER_A), choose_balance($kind, REWARD * STAKE_A / (STAKE_A + STAKE_B), 0, 0) ); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_B), + $pallet::claim_reward(CURRENCY_X, &USER_B), choose_balance( $kind, REWARD * STAKE_B / (STAKE_A + STAKE_B), diff --git a/pallets/rewards/src/tests/currency_movement.rs b/pallets/rewards/src/tests/currency_movement.rs index 1f568a6983..882ac0dddd 100644 --- a/pallets/rewards/src/tests/currency_movement.rs +++ b/pallets/rewards/src/tests/currency_movement.rs @@ -5,13 +5,13 @@ macro_rules! currency_movement_tests { use super::*; fn currency_movement_initial_state() { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Y, GROUP_2)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Z, GROUP_3)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_B, STAKE_A)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_Y, &USER_B, STAKE_B)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_Z, &USER_B, STAKE_C)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_Y, GROUP_2)); + assert_ok!($pallet::attach_currency(CURRENCY_Z, GROUP_3)); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_1)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_B, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_Y, &USER_B, STAKE_B)); + assert_ok!($pallet::deposit_stake(CURRENCY_Z, &USER_B, STAKE_C)); assert_ok!($pallet::distribute_reward( REWARD, [GROUP_1, GROUP_2, GROUP_3] @@ -20,24 +20,24 @@ macro_rules! currency_movement_tests { fn check_last_claim< Reward: DistributedRewards - + AccountRewards, + + AccountRewards, >( kind: MechanismKind, group_id: u32, - domain_currency_id: (DomainId, CurrencyId), + currency_id: CurrencyId, base_expected: u64, deferred_expected: u64, gap_expected: u64, ) { assert_ok!( - Reward::claim_reward(domain_currency_id, &USER_A), + Reward::claim_reward(currency_id, &USER_A), choose_balance(kind, base_expected, 0, 0), ); if kind != MechanismKind::Base { assert_ok!(Reward::distribute_reward(REWARD, [group_id])); assert_ok!( - Reward::claim_reward(domain_currency_id, &USER_A), + Reward::claim_reward(currency_id, &USER_A), match kind { MechanismKind::Base => unreachable!(), MechanismKind::Deferred => deferred_expected, @@ -52,8 +52,8 @@ macro_rules! currency_movement_tests { new_test_ext().execute_with(|| { currency_movement_initial_state(); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_M, &USER_A), 0); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::claim_reward(CURRENCY_M, &USER_A), 0); }); } @@ -62,10 +62,10 @@ macro_rules! currency_movement_tests { new_test_ext().execute_with(|| { currency_movement_initial_state(); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_M)); - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_M, &USER_A), 0); + assert_ok!($pallet::claim_reward(CURRENCY_M, &USER_A), 0); }); } @@ -74,14 +74,14 @@ macro_rules! currency_movement_tests { new_test_ext().execute_with(|| { currency_movement_initial_state(); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_M)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_2])); check_last_claim::<$pallet>( $kind, GROUP_2, - DOM_1_CURRENCY_M, + CURRENCY_M, REWARD * STAKE_M / (STAKE_M + STAKE_B), REWARD * STAKE_M / (STAKE_M + STAKE_B), REWARD * STAKE_M / (STAKE_M + STAKE_B), @@ -94,14 +94,14 @@ macro_rules! currency_movement_tests { new_test_ext().execute_with(|| { currency_movement_initial_state(); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_M)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! check_last_claim::<$pallet>( $kind, GROUP_2, - DOM_1_CURRENCY_M, + CURRENCY_M, REWARD * STAKE_M / (STAKE_M + STAKE_A), REWARD * STAKE_M / (STAKE_M + STAKE_A), REWARD * STAKE_M / (STAKE_M + STAKE_B), @@ -114,15 +114,15 @@ macro_rules! currency_movement_tests { new_test_ext().execute_with(|| { currency_movement_initial_state(); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_M)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::withdraw_stake(CURRENCY_M, &USER_A, STAKE_M)); check_last_claim::<$pallet>( $kind, GROUP_2, - DOM_1_CURRENCY_M, + CURRENCY_M, REWARD * STAKE_M / (STAKE_M + STAKE_A), 0, 0, @@ -135,15 +135,15 @@ macro_rules! currency_movement_tests { new_test_ext().execute_with(|| { currency_movement_initial_state(); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_M)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_3)); // MOVEMENT HERE!! + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_3)); // MOVEMENT HERE!! check_last_claim::<$pallet>( $kind, GROUP_3, - DOM_1_CURRENCY_M, + CURRENCY_M, REWARD * STAKE_M / (STAKE_M + STAKE_A), REWARD * STAKE_M / (STAKE_M + STAKE_A), REWARD * STAKE_M / (STAKE_M + STAKE_C), @@ -156,16 +156,16 @@ macro_rules! currency_movement_tests { new_test_ext().execute_with(|| { currency_movement_initial_state(); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_M)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_3)); // MOVEMENT HERE!! - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_3)); // MOVEMENT HERE!! + assert_ok!($pallet::withdraw_stake(CURRENCY_M, &USER_A, STAKE_M)); check_last_claim::<$pallet>( $kind, GROUP_3, - DOM_1_CURRENCY_M, + CURRENCY_M, REWARD * STAKE_M / (STAKE_M + STAKE_A), 0, 0, @@ -176,11 +176,11 @@ macro_rules! currency_movement_tests { #[test] fn stake_distribute_cross_move_claim() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Y, GROUP_2)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_Y, GROUP_2)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_Y, &USER_A, STAKE_B)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_Y, &USER_A, STAKE_B)); assert_ok!($pallet::distribute_reward_with_weights( REWARD, [(GROUP_1, 1u32), (GROUP_2, 4u32)] @@ -192,25 +192,22 @@ macro_rules! currency_movement_tests { )); } - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_2)); // MOVEMENT HERE!! - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Y, GROUP_1)); // MOVEMENT HERE!! + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::attach_currency(CURRENCY_Y, GROUP_1)); // MOVEMENT HERE!! - assert_ok!($pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), REWARD / 5); - assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_Y, &USER_A), - 4 * (REWARD / 5) - ); + assert_ok!($pallet::claim_reward(CURRENCY_X, &USER_A), REWARD / 5); + assert_ok!($pallet::claim_reward(CURRENCY_Y, &USER_A), 4 * (REWARD / 5)); }); } #[test] fn correct_lost_reward_after_move() { new_test_ext().execute_with(|| { - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_M)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_M)); assert_ok!($pallet::distribute_reward(REWARD, [GROUP_1])); if $kind != MechanismKind::Base { @@ -218,22 +215,22 @@ macro_rules! currency_movement_tests { } assert_ok!( - $pallet::compute_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::compute_reward(CURRENCY_X, &USER_A), REWARD * STAKE_A / (STAKE_A + STAKE_M) ); assert_ok!( - $pallet::compute_reward(DOM_1_CURRENCY_M, &USER_A), + $pallet::compute_reward(CURRENCY_M, &USER_A), REWARD * STAKE_M / (STAKE_M + STAKE_A) ); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_2)); // MOVEMENT HERE!! assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_X, &USER_A), + $pallet::claim_reward(CURRENCY_X, &USER_A), REWARD * STAKE_A / (STAKE_A + STAKE_M) ); assert_ok!( - $pallet::claim_reward(DOM_1_CURRENCY_M, &USER_A), + $pallet::claim_reward(CURRENCY_M, &USER_A), REWARD * STAKE_M / (STAKE_M + STAKE_A) ); @@ -245,38 +242,38 @@ macro_rules! currency_movement_tests { fn associate_different_currencies() { new_test_ext().execute_with(|| { let expected_currency_ids = vec![ - &(DomainId::D1, CurrencyId::A), - &(DomainId::D1, CurrencyId::B), - &(DomainId::D1, CurrencyId::C), - &(DomainId::D1, CurrencyId::M), + &CurrencyId::A, + &CurrencyId::B, + &CurrencyId::C, + &CurrencyId::M, ]; - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_X, GROUP_1)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Y, GROUP_1)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_Z, GROUP_1)); - assert_ok!($pallet::attach_currency(DOM_1_CURRENCY_M, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_X, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_Y, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_Z, GROUP_1)); + assert_ok!($pallet::attach_currency(CURRENCY_M, GROUP_1)); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_X, &USER_A, STAKE_A)); assert!(expected_currency_ids[0..1] .iter() .all(|x| $pallet::list_currencies(&USER_A).contains(x))); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_Y, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_Y, &USER_A, STAKE_A)); assert!(expected_currency_ids[0..2] .iter() .all(|x| $pallet::list_currencies(&USER_A).contains(x))); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_Z, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_Z, &USER_A, STAKE_A)); assert!(expected_currency_ids[0..3] .iter() .all(|x| $pallet::list_currencies(&USER_A).contains(x))); - assert_ok!($pallet::deposit_stake(DOM_1_CURRENCY_M, &USER_A, STAKE_A)); + assert_ok!($pallet::deposit_stake(CURRENCY_M, &USER_A, STAKE_A)); assert!(expected_currency_ids .iter() .all(|x| $pallet::list_currencies(&USER_A).contains(x))); - assert_ok!($pallet::withdraw_stake(DOM_1_CURRENCY_X, &USER_A, STAKE_A)); + assert_ok!($pallet::withdraw_stake(CURRENCY_X, &USER_A, STAKE_A)); assert_eq!($pallet::list_currencies(&USER_A).len(), 4); }); } diff --git a/runtime/altair/Cargo.toml b/runtime/altair/Cargo.toml index 5b5cf0277f..771d98406b 100644 --- a/runtime/altair/Cargo.toml +++ b/runtime/altair/Cargo.toml @@ -20,6 +20,7 @@ static_assertions = "1.1.0" cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } +cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37", optional = true } cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } @@ -91,6 +92,7 @@ cfg-primitives = { path = "../../libs/primitives", default-features = false } cfg-traits = { path = "../../libs/traits", default-features = false } cfg-types = { path = "../../libs/types", default-features = false } pallet-anchors = { path = "../../pallets/anchors", default-features = false } +pallet-block-rewards = { path = "../../pallets/block-rewards", default-features = false } pallet-collator-allowlist = { path = "../../pallets/collator-allowlist", default-features = false } pallet-crowdloan-claim = { path = "../../pallets/crowdloan-claim", default-features = false } pallet-crowdloan-reward = { path = "../../pallets/crowdloan-reward", default-features = false } @@ -104,6 +106,7 @@ pallet-permissions = { path = "../../pallets/permissions", default-features = fa pallet-pool-registry = { path = "../../pallets/pool-registry", default-features = false } pallet-pool-system = { path = "../../pallets/pool-system", default-features = false } pallet-restricted-tokens = { path = "../../pallets/restricted-tokens", default-features = false } +pallet-rewards = { path = "../../pallets/rewards", default-features = false } runtime-common = { path = "../common", default-features = false } [build-dependencies] @@ -118,6 +121,7 @@ std = [ "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-parachain-system/std", + "cumulus-pallet-session-benchmarking?/std", "cumulus-pallet-xcm/std", "cumulus-pallet-xcmp-queue/std", "cumulus-primitives-timestamp/std", @@ -137,6 +141,7 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", + "pallet-block-rewards/std", "pallet-collator-allowlist/std", "pallet-collator-selection/std", "pallet-collective/std", @@ -159,6 +164,7 @@ std = [ "pallet-proxy/std", "pallet-randomness-collective-flip/std", "pallet-restricted-tokens/std", + "pallet-rewards/std", "pallet-scheduler/std", "pallet-session/std", "pallet-timestamp/std", @@ -197,6 +203,7 @@ std = [ ] runtime-benchmarks = [ "cfg-types/runtime-benchmarks", + "cumulus-pallet-session-benchmarking/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", @@ -204,6 +211,7 @@ runtime-benchmarks = [ "hex-literal", "pallet-anchors/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-block-rewards/runtime-benchmarks", "pallet-collator-allowlist/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-collective/runtime-benchmarks", @@ -271,6 +279,7 @@ try-runtime = [ "pallet-aura/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", + "pallet-block-rewards/try-runtime", "pallet-collator-allowlist/try-runtime", "pallet-collator-selection/try-runtime", "pallet-collective/try-runtime", @@ -294,6 +303,7 @@ try-runtime = [ "pallet-randomness-collective-flip/try-runtime", "pallet-restricted-tokens/try-runtime", "pallet-restricted-tokens/try-runtime", + "pallet-rewards/try-runtime", "pallet-scheduler/try-runtime", "pallet-session/try-runtime", "pallet-timestamp/try-runtime", diff --git a/runtime/altair/src/lib.rs b/runtime/altair/src/lib.rs index 73e07d4bfa..271be9ba7c 100644 --- a/runtime/altair/src/lib.rs +++ b/runtime/altair/src/lib.rs @@ -31,7 +31,7 @@ use cfg_types::{ fixed_point::Rate, permissions::{PermissionRoles, PermissionScope, PermissionedCurrencyRole, PoolRole, Role}, time::TimeProvider, - tokens::{CustomMetadata, TrancheCurrency}, + tokens::{CustomMetadata, StakingCurrency, TrancheCurrency}, }; use codec::{Decode, Encode, MaxEncodedLen}; /// Constant values used within the runtime. @@ -81,7 +81,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdConversion, BlakeTwo256, Block as BlockT, ConvertInto, Zero}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, DispatchError, DispatchResult, Perbill, Permill, + ApplyExtrinsicResult, DispatchError, DispatchResult, FixedI128, Perbill, Permill, }; use sp_std::{marker::PhantomData, prelude::*}; #[cfg(any(feature = "std", test))] @@ -93,6 +93,7 @@ use xcm_executor::XcmExecutor; use crate::xcm::{XcmConfig, XcmOriginToTransactDispatchOrigin}; pub mod constants; +mod migrations; mod weights; pub mod xcm; @@ -105,6 +106,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); impl_opaque_keys! { pub struct SessionKeys { pub aura: Aura, + pub block_rewards: BlockRewards, } } @@ -339,10 +341,11 @@ impl pallet_session::Config for Runtime { type ValidatorId = ::AccountId; // we don't have stash and controller, thus we don't need the convert as well. type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type WeightInfo = pallet_session::weights::SubstrateWeight; + type WeightInfo = weights::pallet_session::WeightInfo; } parameter_types! { + #[derive(scale_info::TypeInfo, Debug, PartialEq, Eq, Clone)] pub const MaxAuthorities: u32 = 32; } @@ -471,7 +474,8 @@ impl InstanceFilter for ProxyType { // Specifically omitting ChainBridge // Specifically omitting Migration // Specifically omitting PoolRegistry `register`, `update`, `set_metadata` - RuntimeCall::PoolRegistry(pallet_pool_registry::Call::execute_update {..}) + RuntimeCall::PoolRegistry(pallet_pool_registry::Call::execute_update {..}) | + RuntimeCall::BlockRewards(..) ) } ProxyType::Governance => matches!( @@ -900,6 +904,7 @@ impl pallet_crowdloan_claim::Config for Runtime { // Parameterize collator selection pallet parameter_types! { pub const PotId: PalletId = cfg_types::ids::STAKE_POT_PALLET_ID; + #[derive(scale_info::TypeInfo, Debug, PartialEq, Eq, Clone)] pub const MaxCandidates: u32 = 100; pub const MinCandidates: u32 = 5; pub const MaxVoters: u32 = 1000; @@ -921,7 +926,7 @@ impl pallet_collator_selection::Config for Runtime { type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ValidatorRegistration = CollatorAllowlist; - type WeightInfo = pallet_collator_selection::weights::SubstrateWeight; + type WeightInfo = weights::pallet_collator_selection::WeightInfo; } parameter_types! { @@ -1106,6 +1111,63 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type XcmExecutor = XcmExecutor; } +// Block Rewards + +frame_support::parameter_types! { + // BlockRewards have exactly one group and currency + #[derive(scale_info::TypeInfo)] + pub const SingleCurrencyMovement: u32 = 1; + #[derive(scale_info::TypeInfo, Debug, PartialEq, Eq, Clone)] + pub const MaxChangesPerEpoch: u32 = 50; + pub const RewardsPalletId: PalletId = cfg_types::ids::BLOCK_REWARDS_PALLET_ID; + pub const RewardCurrency: CurrencyId = CurrencyId::Native; +} + +impl pallet_rewards::Config for Runtime { + type Currency = Tokens; + type CurrencyId = CurrencyId; + type GroupId = u32; + type PalletId = RewardsPalletId; + type RewardCurrency = RewardCurrency; + // Must not change this to ensure block rewards are minted + type RewardIssuance = + pallet_rewards::issuance::MintReward; + type RewardMechanism = pallet_rewards::mechanism::base::Mechanism< + Balance, + IBalance, + FixedI128, + SingleCurrencyMovement, + >; + type RuntimeEvent = RuntimeEvent; +} + +frame_support::parameter_types! { + pub const BlockRewardCurrency: CurrencyId = CurrencyId::Staking(StakingCurrency::BlockRewards); + pub const StakeAmount: Balance = cfg_types::consts::rewards::DEFAULT_COLLATOR_STAKE; + pub const CollatorGroupId: u32 = cfg_types::ids::COLLATOR_GROUP_ID; +} + +impl pallet_block_rewards::Config for Runtime { + type AdminOrigin = EnsureRootOr; + type AuthorityId = AuraId; + type Balance = Balance; + // Must not set this as long as we don't want to mint the rewards. + // By setting this to (), the remainder of TotalRewards - CollatorRewards + // will be dropped. Else it would be transferred to the configured Beneficiary. + type Beneficiary = (); + type Currency = Tokens; + type CurrencyId = CurrencyId; + type MaxChangesPerSession = MaxChangesPerEpoch; + type MaxCollators = MaxAuthorities; + type Rewards = BlockRewardsBase; + type RuntimeEvent = RuntimeEvent; + type StakeAmount = StakeAmount; + type StakeCurrencyId = BlockRewardCurrency; + type StakeGroupId = CollatorGroupId; + type Weight = u64; + type WeightInfo = weights::pallet_block_rewards::WeightInfo; +} + // PoolSystem & Loans parameter_types! { @@ -1447,6 +1509,8 @@ construct_runtime!( InterestAccrual: pallet_interest_accrual::{Pallet, Storage, Event, Config} = 101, Investments: pallet_investments::{Pallet, Call, Storage, Event} = 102, PoolRegistry: pallet_pool_registry::{Pallet, Call, Storage, Event} = 103, + BlockRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 104, + BlockRewards: pallet_block_rewards::{Pallet, Call, Storage, Event, Config} = 105, // XCM XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 120, @@ -1489,8 +1553,6 @@ pub type UncheckedExtrinsic = /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; -type UpgradeAltair1027 = pallet_loans_ref::migrations::v1::Migration; - /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -1498,7 +1560,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - UpgradeAltair1027, + crate::migrations::UpgradeAltair1027, >; #[cfg(not(feature = "disable-runtime-api"))] @@ -1665,6 +1727,23 @@ impl_runtime_apis! { } } + // RewardsApi + impl runtime_common::apis::RewardsApi for Runtime { + fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec { + match domain { + runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), + _ => vec![], + } + } + + fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option { + match domain { + runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), + _ => None, + } + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { @@ -1675,6 +1754,7 @@ impl_runtime_apis! { use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; let mut list = Vec::::new(); @@ -1704,9 +1784,11 @@ impl_runtime_apis! { list_benchmark!(list, extra, pallet_uniques, Uniques); list_benchmark!(list, extra, pallet_fees, Fees); list_benchmark!(list, extra, pallet_anchors, Anchor); + list_benchmark!(list, extra, pallet_block_rewards, BlockRewards); list_benchmark!(list, extra, pallet_crowdloan_claim, CrowdloanClaim); list_benchmark!(list, extra, pallet_crowdloan_reward, CrowdloanReward); list_benchmark!(list, extra, pallet_collator_allowlist, CollatorAllowlist); + list_benchmark!(list, extra, pallet_collator_selection, CollatorSelection); list_benchmark!(list, extra, pallet_migration_manager, Migration); list_benchmark!(list, extra, pallet_permissions, Permissions); list_benchmark!(list, extra, pallet_nft_sales, NftSales); @@ -1714,6 +1796,7 @@ impl_runtime_apis! { list_benchmark!(list, extra, pallet_pool_registry, PoolRegistry); list_benchmark!(list, extra, pallet_loans_ref, Loans); list_benchmark!(list, extra, pallet_interest_accrual, InterestAccrual); + list_benchmark!(list, extra, pallet_session, SessionBench::); list_benchmark!(list, extra, pallet_restricted_tokens, Tokens); let storage_info = AllPalletsWithSystem::storage_info(); @@ -1726,8 +1809,10 @@ impl_runtime_apis! { ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; use frame_system_benchmarking::Pallet as SystemBench; + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl frame_system_benchmarking::Config for Runtime {} + impl cumulus_pallet_session_benchmarking::Config for Runtime {} // you can whitelist any storage keys you do not want to track here let whitelist: Vec = vec![ @@ -1768,9 +1853,11 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_uniques, Uniques); add_benchmark!(params, batches, pallet_fees, Fees); add_benchmark!(params, batches, pallet_anchors, Anchors); + add_benchmark!(params, batches, pallet_block_rewards, BlockRewards); add_benchmark!(params, batches, pallet_crowdloan_claim, CrowdloanClaim); add_benchmark!(params, batches, pallet_crowdloan_reward, CrowdloanReward); add_benchmark!(params, batches, pallet_collator_allowlist, CollatorAllowlist); + add_benchmark!(params, batches, pallet_collator_selection, CollatorSelection); add_benchmark!(params, batches, pallet_migration_manager, Migration); add_benchmark!(params, batches, pallet_permissions, Permissions); add_benchmark!(params, batches, pallet_nft_sales, NftSales); @@ -1778,6 +1865,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_pool_registry, PoolRegistry); add_benchmark!(params, batches, pallet_loans_ref, Loans); add_benchmark!(params, batches, pallet_interest_accrual, InterestAccrual); + add_benchmark!(params, batches, pallet_session, SessionBench::); add_benchmark!(params, batches, pallet_restricted_tokens, Tokens); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } diff --git a/runtime/altair/src/migrations.rs b/runtime/altair/src/migrations.rs new file mode 100644 index 0000000000..4110b4eb25 --- /dev/null +++ b/runtime/altair/src/migrations.rs @@ -0,0 +1,147 @@ +// Copyright 2021 Centrifuge Foundation (centrifuge.io). +// +// This file is part of the Centrifuge chain project. +// Centrifuge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version (see http://www.gnu.org/licenses). +// Centrifuge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +use crate::{AccountId, BlockRewards, ExistentialDeposit, NativeToken, Runtime}; + +pub type UpgradeAltair1027 = ( + pallet_loans_ref::migrations::v1::Migration, + session_key_migration::ExtendSessionKeys, + pallet_block_rewards::migrations::InitBlockRewards< + Runtime, + init_block_rewards::CollatorRewards, + init_block_rewards::TotalRewards, + >, + pallet_rewards::migrations::new_instance::FundExistentialDeposit< + Runtime, + pallet_rewards::Instance1, + NativeToken, + ExistentialDeposit, + >, +); + +mod init_block_rewards { + use frame_support::parameter_types; + + use crate::{Balance, MaxCandidates, MILLI_AIR}; + + parameter_types! { + // = 12,000 AIR/month = 394.521 AIR/day = 98.63 AIR/session + // https://gov.centrifuge.io/t/adjustment-of-altair-collator-rewards/4844 + pub const CollatorRewards: Balance = 98_630 * MILLI_AIR; + // Only serves as a max bound of collator rewards + // E.g. the remainder of TotalRewards - CollatorRewards is not minted + // If we set this bound closer to the current number of collators (=10), + // we would have to increase it via governance when new collators join. + pub TotalRewards: Balance = CollatorRewards::get().saturating_mul(MaxCandidates::get().into()); + } +} + +mod session_key_migration { + use frame_support::{ + dispatch::GetStorageVersion, + inherent::Vec, + pallet_prelude::{StorageVersion, ValueQuery}, + storage_alias, + }; + use sp_runtime::impl_opaque_keys; + #[cfg(feature = "try-runtime")] + use { + codec::{Decode, Encode}, + frame_benchmarking::Zero, + }; + + use super::*; + use crate::{Aura, Session, SessionKeys}; + + pub struct ExtendSessionKeys; + + impl_opaque_keys! { + pub struct OldSessionKeys { + pub aura: Aura, + } + } + + #[storage_alias] + type QueuedKeys = + StorageValue, Vec<(AccountId, OldSessionKeys)>, ValueQuery>; + + impl frame_support::traits::OnRuntimeUpgrade for ExtendSessionKeys { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + let queued: Vec<(AccountId, OldSessionKeys)> = QueuedKeys::::get(); + + assert!( + !queued.len().is_zero(), + "Queued session keys must never be empty" + ); + + Ok(queued.encode()) + } + + fn on_runtime_upgrade() -> frame_support::weights::Weight { + use sp_runtime::SaturatedConversion; + + // We must not bump the storage version of pallet_session to stay in sync with + // Substrate. As this migration is tightly coupled to the initialization of + // BlockRewards, it should be sane to trigger the session migration based on the + // BlockRewards storage version. + if BlockRewards::on_chain_storage_version() == StorageVersion::new(0) { + Session::upgrade_keys::(|_, old_key| SessionKeys { + aura: old_key.aura.clone(), + block_rewards: old_key.aura, + }); + + let n: u64 = pallet_session::Validators::::get() + .len() + .saturated_into(); + + ::DbWeight::get() + .reads_writes(n.saturating_add(1), n) + } else { + ::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(pre_state: Vec) -> Result<(), &'static str> { + let pre_state: Vec<(AccountId, OldSessionKeys)> = + Decode::decode(&mut pre_state.as_slice()) + .expect("Pre state parameter should be generated by pre-upgrade hooks"); + + let queued: Vec<(AccountId, SessionKeys)> = + pallet_session::QueuedKeys::::get(); + + assert!( + pre_state.len() == queued.len(), + "Mismatch in number of session keys: pre {} vs post {}", + pre_state.len(), + queued.len() + ); + + pre_state.iter().zip(queued.into_iter()).for_each( + |((pre_acc, pre_session_key), (post_acc, post_session_key))| { + assert!(pre_acc == &post_acc, "Failed to match old validator key"); + assert!( + &pre_session_key.aura == &post_session_key.aura, + "Failed to match old aura key" + ); + assert!( + &pre_session_key.aura == &post_session_key.block_rewards, + "Block rewards key does not match aura one" + ); + }, + ); + + Ok(()) + } + } +} diff --git a/runtime/altair/src/weights/mod.rs b/runtime/altair/src/weights/mod.rs index bf455070d7..b8c66d321c 100644 --- a/runtime/altair/src/weights/mod.rs +++ b/runtime/altair/src/weights/mod.rs @@ -12,7 +12,9 @@ pub mod frame_system; pub mod pallet_anchors; pub mod pallet_balances; +pub mod pallet_block_rewards; pub mod pallet_collator_allowlist; +pub mod pallet_collator_selection; pub mod pallet_collective; pub mod pallet_crowdloan_claim; pub mod pallet_crowdloan_reward; @@ -31,6 +33,7 @@ pub mod pallet_preimage; pub mod pallet_proxy; pub mod pallet_restricted_tokens; pub mod pallet_scheduler; +pub mod pallet_session; pub mod pallet_timestamp; pub mod pallet_treasury; pub mod pallet_uniques; diff --git a/runtime/altair/src/weights/pallet_block_rewards.rs b/runtime/altair/src/weights/pallet_block_rewards.rs new file mode 100644 index 0000000000..90dd3b5768 --- /dev/null +++ b/runtime/altair/src/weights/pallet_block_rewards.rs @@ -0,0 +1,58 @@ + +//! Autogenerated weights for `pallet_block_rewards` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-03-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `Laptop.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("altair-local"), DB CACHE: 1024 + +// Executed Command: +// target/release/centrifuge-chain +// benchmark +// pallet +// --chain=altair_local +// --steps=50 +// --repeat=20 +// --pallet=pallet_block_rewards +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=/tmp/runtime/development/src/weights/pallet_block_rewards.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_block_rewards`. +pub struct WeightInfo(PhantomData); +impl pallet_block_rewards::weights::WeightInfo for WeightInfo { + // Storage: BlockRewardsBase Currencies (r:1 w:0) + // Storage: BlockRewardsBase Groups (r:1 w:0) + // Storage: BlockRewardsBase StakeAccounts (r:1 w:1) + // Storage: System Account (r:2 w:2) + fn claim_reward() -> Weight { + // Minimum execution time: 46_000 nanoseconds. + Weight::from_ref_time(48_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: BlockRewards NextSessionChanges (r:1 w:1) + fn set_collator_reward() -> Weight { + // Minimum execution time: 7_000 nanoseconds. + Weight::from_ref_time(7_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: BlockRewards NextSessionChanges (r:1 w:1) + // Storage: BlockRewards ActiveSessionData (r:1 w:0) + fn set_total_reward() -> Weight { + // Minimum execution time: 9_000 nanoseconds. + Weight::from_ref_time(9_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } +} diff --git a/runtime/altair/src/weights/pallet_collator_selection.rs b/runtime/altair/src/weights/pallet_collator_selection.rs new file mode 100644 index 0000000000..56e4d2a90f --- /dev/null +++ b/runtime/altair/src/weights/pallet_collator_selection.rs @@ -0,0 +1,108 @@ + +//! Autogenerated weights for `pallet_collator_selection` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-03-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `Laptop.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("altair-local"), DB CACHE: 1024 + +// Executed Command: +// target/release/centrifuge-chain +// benchmark +// pallet +// --chain=altair_local +// --steps=50 +// --repeat=20 +// --pallet=pallet_collator_selection +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=/tmp/runtime/development/src/weights/pallet_collator_selection.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_collator_selection`. +pub struct WeightInfo(PhantomData); +impl pallet_collator_selection::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:0) + // Storage: CollatorSelection Invulnerables (r:0 w:1) + /// The range of component `b` is `[1, 100]`. + fn set_invulnerables(b: u32, ) -> Weight { + // Minimum execution time: 18_000 nanoseconds. + Weight::from_ref_time(13_766_079 as u64) + // Standard Error: 18_962 + .saturating_add(Weight::from_ref_time(2_866_571 as u64).saturating_mul(b as u64)) + .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64))) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: CollatorSelection DesiredCandidates (r:0 w:1) + fn set_desired_candidates() -> Weight { + // Minimum execution time: 11_000 nanoseconds. + Weight::from_ref_time(12_000_000 as u64) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: CollatorSelection CandidacyBond (r:0 w:1) + fn set_candidacy_bond() -> Weight { + // Minimum execution time: 11_000 nanoseconds. + Weight::from_ref_time(12_000_000 as u64) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: CollatorSelection Candidates (r:1 w:1) + // Storage: CollatorSelection DesiredCandidates (r:1 w:0) + // Storage: CollatorSelection Invulnerables (r:1 w:0) + // Storage: Session NextKeys (r:1 w:0) + // Storage: CollatorSelection CandidacyBond (r:1 w:0) + // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) + /// The range of component `c` is `[1, 999]`. + fn register_as_candidate(c: u32, ) -> Weight { + // Minimum execution time: 41_000 nanoseconds. + Weight::from_ref_time(42_888_647 as u64) + // Standard Error: 1_823 + .saturating_add(Weight::from_ref_time(120_814 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: CollatorSelection Candidates (r:1 w:1) + // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) + /// The range of component `c` is `[6, 1000]`. + fn leave_intent(c: u32, ) -> Weight { + // Minimum execution time: 31_000 nanoseconds. + Weight::from_ref_time(24_963_536 as u64) + // Standard Error: 1_964 + .saturating_add(Weight::from_ref_time(118_803 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: System Account (r:2 w:2) + // Storage: System BlockWeight (r:1 w:1) + // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) + fn note_author() -> Weight { + // Minimum execution time: 34_000 nanoseconds. + Weight::from_ref_time(38_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + } + // Storage: CollatorSelection Candidates (r:1 w:1) + // Storage: CollatorSelection LastAuthoredBlock (r:1000 w:1) + // Storage: System Account (r:1 w:1) + // Storage: CollatorSelection Invulnerables (r:1 w:0) + // Storage: System BlockWeight (r:1 w:1) + /// The range of component `r` is `[1, 1000]`. + /// The range of component `c` is `[1, 1000]`. + fn new_session(_r: u32, c: u32, ) -> Weight { + // Minimum execution time: 15_000 nanoseconds. + Weight::from_ref_time(16_000_000 as u64) + // Standard Error: 632_608 + .saturating_add(Weight::from_ref_time(22_335_806 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + } +} diff --git a/runtime/altair/src/weights/pallet_session.rs b/runtime/altair/src/weights/pallet_session.rs new file mode 100644 index 0000000000..7fe4e157ca --- /dev/null +++ b/runtime/altair/src/weights/pallet_session.rs @@ -0,0 +1,49 @@ + +//! Autogenerated weights for `pallet_session` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-03-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `Laptop.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("altair-local"), DB CACHE: 1024 + +// Executed Command: +// target/release/centrifuge-chain +// benchmark +// pallet +// --chain=altair_local +// --steps=50 +// --repeat=20 +// --pallet=pallet_session +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=/tmp/runtime/development/src/weights/pallet_session.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_session`. +pub struct WeightInfo(PhantomData); +impl pallet_session::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:1) + // Storage: Session KeyOwner (r:1 w:1) + fn set_keys() -> Weight { + // Minimum execution time: 23_000 nanoseconds. + Weight::from_ref_time(23_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: Session NextKeys (r:1 w:1) + // Storage: Session KeyOwner (r:0 w:1) + fn purge_keys() -> Weight { + // Minimum execution time: 18_000 nanoseconds. + Weight::from_ref_time(19_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } +} diff --git a/runtime/centrifuge/Cargo.toml b/runtime/centrifuge/Cargo.toml index c666ba7849..4ecaac9b63 100644 --- a/runtime/centrifuge/Cargo.toml +++ b/runtime/centrifuge/Cargo.toml @@ -20,6 +20,7 @@ static_assertions = "1.1.0" cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } +cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37", optional = true } cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.37" } @@ -92,6 +93,7 @@ cfg-primitives = { path = "../../libs/primitives", default-features = false } cfg-traits = { path = "../../libs/traits", default-features = false } cfg-types = { path = "../../libs/types", default-features = false } pallet-anchors = { path = "../../pallets/anchors", default-features = false } +pallet-block-rewards = { path = "../../pallets/block-rewards", default-features = false } pallet-bridge = { path = "../../pallets/bridge", default-features = false } pallet-claims = { path = "../../pallets/claims", default-features = false } pallet-collator-allowlist = { path = "../../pallets/collator-allowlist", default-features = false } @@ -108,6 +110,7 @@ pallet-permissions = { path = "../../pallets/permissions", default-features = fa pallet-pool-registry = { path = "../../pallets/pool-registry", default-features = false } pallet-pool-system = { path = "../../pallets/pool-system", default-features = false } pallet-restricted-tokens = { path = "../../pallets/restricted-tokens", default-features = false } +pallet-rewards = { path = "../../pallets/rewards", default-features = false } runtime-common = { path = "../common", default-features = false } # bridge pallets @@ -127,6 +130,7 @@ std = [ "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", "cumulus-pallet-parachain-system/std", + "cumulus-pallet-session-benchmarking?/std", "cumulus-pallet-xcm/std", "cumulus-pallet-xcmp-queue/std", "cumulus-primitives-core/std", @@ -149,6 +153,7 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", + "pallet-block-rewards/std", "pallet-bridge/std", "pallet-claims/std", "pallet-collator-allowlist/std", @@ -174,6 +179,7 @@ std = [ "pallet-proxy/std", "pallet-randomness-collective-flip/std", "pallet-restricted-tokens/std", + "pallet-rewards/std", "pallet-scheduler/std", "pallet-session/std", "pallet-timestamp/std", @@ -213,6 +219,7 @@ runtime-benchmarks = [ "cfg-types/runtime-benchmarks", "chainbridge/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", + "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", @@ -224,6 +231,7 @@ runtime-benchmarks = [ "orml-xtokens/runtime-benchmarks", "pallet-anchors/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-block-rewards/runtime-benchmarks", "pallet-bridge/runtime-benchmarks", "pallet-collator-allowlist/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", @@ -284,6 +292,7 @@ try-runtime = [ "pallet-aura/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", + "pallet-block-rewards/try-runtime", "pallet-bridge/try-runtime", "pallet-claims/try-runtime", "pallet-collator-allowlist/try-runtime", @@ -309,6 +318,7 @@ try-runtime = [ "pallet-proxy/try-runtime", "pallet-randomness-collective-flip/try-runtime", "pallet-restricted-tokens/try-runtime", + "pallet-rewards/try-runtime", "pallet-scheduler/try-runtime", "pallet-session/try-runtime", "pallet-timestamp/try-runtime", diff --git a/runtime/centrifuge/src/lib.rs b/runtime/centrifuge/src/lib.rs index 5819296ff5..fba90c7990 100644 --- a/runtime/centrifuge/src/lib.rs +++ b/runtime/centrifuge/src/lib.rs @@ -32,7 +32,7 @@ use cfg_types::{ PermissionRoles, PermissionScope, PermissionedCurrencyRole, PoolRole, Role, UNION, }, time::TimeProvider, - tokens::{CustomMetadata, TrancheCurrency}, + tokens::{CustomMetadata, StakingCurrency, TrancheCurrency}, }; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ @@ -82,7 +82,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdConversion, BlakeTwo256, Block as BlockT, ConvertInto, Zero}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, Perbill, Permill, + ApplyExtrinsicResult, FixedI128, Perbill, Permill, }; use sp_std::prelude::*; #[cfg(any(feature = "std", test))] @@ -93,6 +93,7 @@ use xcm_executor::XcmExecutor; use crate::xcm::{XcmConfig, XcmOriginToTransactDispatchOrigin}; +mod migrations; mod weights; pub mod xcm; @@ -109,6 +110,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); impl_opaque_keys! { pub struct SessionKeys { pub aura: Aura, + pub block_rewards: BlockRewards, } } @@ -492,11 +494,11 @@ impl pallet_session::Config for Runtime { type ValidatorId = ::AccountId; // we don't have stash and controller, thus we don't need the convert as well. type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - // TODO: Wait for block rewards that fix this - type WeightInfo = pallet_session::weights::SubstrateWeight; + type WeightInfo = weights::pallet_session::WeightInfo; } parameter_types! { + #[derive(scale_info::TypeInfo, Debug, PartialEq, Eq, Clone)] pub const MaxAuthorities: u32 = 32; } @@ -614,7 +616,8 @@ impl InstanceFilter for ProxyType { // Specifically omitting OrmlTokens // Specifically omitting ChainBridge // Specifically omitting Migration - RuntimeCall::CollatorAllowlist(..) + RuntimeCall::CollatorAllowlist(..) | + RuntimeCall::BlockRewards(..) ) } ProxyType::Governance => matches!( @@ -1122,6 +1125,7 @@ impl pallet_crowdloan_claim::Config for Runtime { // Parameterize collator selection pallet parameter_types! { pub const PotId: PalletId = cfg_types::ids::STAKE_POT_PALLET_ID; + #[derive(scale_info::TypeInfo, Debug, PartialEq, Eq, Clone)] pub const MaxCandidates: u32 = 100; pub const MinCandidates: u32 = 5; pub const MaxVoters: u32 = 1000; @@ -1143,7 +1147,62 @@ impl pallet_collator_selection::Config for Runtime { type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ValidatorRegistration = CollatorAllowlist; - type WeightInfo = pallet_collator_selection::weights::SubstrateWeight; + type WeightInfo = weights::pallet_collator_selection::WeightInfo; +} + +// Block Rewards + +frame_support::parameter_types! { + // BlockRewards have exactly one group and currency + #[derive(scale_info::TypeInfo)] + pub const SingleCurrencyMovement: u32 = 1; + #[derive(scale_info::TypeInfo, Debug, PartialEq, Eq, Clone)] + pub const MaxChangesPerEpoch: u32 = 50; + pub const RewardsPalletId: PalletId = cfg_types::ids::BLOCK_REWARDS_PALLET_ID; + pub const RewardCurrency: CurrencyId = CurrencyId::Native; +} + +impl pallet_rewards::Config for Runtime { + type Currency = Tokens; + type CurrencyId = CurrencyId; + type GroupId = u32; + type PalletId = RewardsPalletId; + type RewardCurrency = RewardCurrency; + // Must not change this to ensure block rewards are minted + type RewardIssuance = + pallet_rewards::issuance::MintReward; + type RewardMechanism = pallet_rewards::mechanism::base::Mechanism< + Balance, + IBalance, + FixedI128, + SingleCurrencyMovement, + >; + type RuntimeEvent = RuntimeEvent; +} + +frame_support::parameter_types! { + pub const BlockRewardCurrency: CurrencyId = CurrencyId::Staking(StakingCurrency::BlockRewards); + pub const StakeAmount: Balance = cfg_types::consts::rewards::DEFAULT_COLLATOR_STAKE; + pub const CollatorGroupId: u32 = cfg_types::ids::COLLATOR_GROUP_ID; +} + +impl pallet_block_rewards::Config for Runtime { + type AdminOrigin = EnsureRootOr; + type AuthorityId = AuraId; + type Balance = Balance; + // Must not change this as long as we want to mint rewards into the treasury + type Beneficiary = Treasury; + type Currency = Tokens; + type CurrencyId = CurrencyId; + type MaxChangesPerSession = MaxChangesPerEpoch; + type MaxCollators = MaxAuthorities; + type Rewards = BlockRewardsBase; + type RuntimeEvent = RuntimeEvent; + type StakeAmount = StakeAmount; + type StakeCurrencyId = BlockRewardCurrency; + type StakeGroupId = CollatorGroupId; + type Weight = u64; + type WeightInfo = weights::pallet_block_rewards::WeightInfo; } // Pool config parameters @@ -1614,6 +1673,8 @@ construct_runtime!( CrowdloanReward: pallet_crowdloan_reward::{Pallet, Call, Storage, Event} = 97, Tokens: pallet_restricted_tokens::{Pallet, Call, Event} = 98, CollatorAllowlist: pallet_collator_allowlist::{Pallet, Call, Storage, Config, Event} = 99, + BlockRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 100, + BlockRewards: pallet_block_rewards::{Pallet, Call, Storage, Event, Config} = 101, // XCM XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 120, @@ -1666,8 +1727,6 @@ pub type UncheckedExtrinsic = /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; -type UpgradeCentrifuge1019 = pallet_loans_ref::migrations::v1::Migration; - /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -1675,7 +1734,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - UpgradeCentrifuge1019, + crate::migrations::UpgradeCentrifuge1019, >; #[cfg(not(feature = "disable-runtime-api"))] @@ -1843,6 +1902,23 @@ impl_runtime_apis! { } } + // RewardsApi + impl runtime_common::apis::RewardsApi for Runtime { + fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec { + match domain { + runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), + _ => vec![], + } + } + + fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option { + match domain { + runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), + _ => None, + } + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { @@ -1853,6 +1929,7 @@ impl_runtime_apis! { use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; let mut list = Vec::::new(); @@ -1872,14 +1949,17 @@ impl_runtime_apis! { list_benchmark!(list, extra, pallet_preimage, Preimage); list_benchmark!(list, extra, pallet_fees, Fees); list_benchmark!(list, extra, pallet_anchors, Anchor); + list_benchmark!(list, extra, pallet_block_rewards, BlockRewards); list_benchmark!(list, extra, pallet_migration_manager, Migration); list_benchmark!(list, extra, pallet_crowdloan_claim, CrowdloanClaim); list_benchmark!(list, extra, pallet_crowdloan_reward, CrowdloanReward); list_benchmark!(list, extra, pallet_collator_allowlist, CollatorAllowlist); + list_benchmark!(list, extra, pallet_collator_selection, CollatorSelection); list_benchmark!(list, extra, pallet_pool_registry, PoolRegistry); list_benchmark!(list, extra, pallet_pool_system, PoolSystem); list_benchmark!(list, extra, pallet_permissions, Permissions); list_benchmark!(list, extra, pallet_interest_accrual, InterestAccrual); + list_benchmark!(list, extra, pallet_session, SessionBench::); list_benchmark!(list, extra, pallet_uniques, Uniques); list_benchmark!(list, extra, pallet_keystore, Keystore); list_benchmark!(list, extra, pallet_restricted_tokens, Tokens); @@ -1897,8 +1977,11 @@ impl_runtime_apis! { ) -> Result, sp_runtime::RuntimeString>{ use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; use frame_system_benchmarking::Pallet as SystemBench; + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl frame_system_benchmarking::Config for Runtime {} + impl cumulus_pallet_session_benchmarking::Config for Runtime {} + // you can whitelist any storage keys you do not want to track here let whitelist: Vec = vec![ @@ -1936,10 +2019,12 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_preimage, Preimage); add_benchmark!(params, batches, pallet_fees, Fees); add_benchmark!(params, batches, pallet_anchors, Anchors); + add_benchmark!(params, batches, pallet_block_rewards, BlockRewards); add_benchmark!(params, batches, pallet_migration_manager, Migration); add_benchmark!(params, batches, pallet_crowdloan_claim, CrowdloanClaim); add_benchmark!(params, batches, pallet_crowdloan_reward, CrowdloanReward); add_benchmark!(params, batches, pallet_collator_allowlist, CollatorAllowlist); + add_benchmark!(params, batches, pallet_collator_selection, CollatorSelection); add_benchmark!(params, batches, pallet_pool_registry, PoolRegistry); add_benchmark!(params, batches, pallet_pool_system, PoolSystem); add_benchmark!(params, batches, pallet_permissions, Permissions); @@ -1947,6 +2032,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_uniques, Uniques); add_benchmark!(params, batches, pallet_keystore, Keystore); add_benchmark!(params, batches, pallet_restricted_tokens, Tokens); + add_benchmark!(params, batches, pallet_session, SessionBench::); add_benchmark!(params, batches, pallet_loans_ref, Loans); add_benchmark!(params, batches, pallet_collator_selection, CollatorSelection); add_benchmark!(params, batches, cumulus_pallet_xcmp_queue, XcmpQueue); diff --git a/runtime/centrifuge/src/migrations.rs b/runtime/centrifuge/src/migrations.rs new file mode 100644 index 0000000000..1052d4f33e --- /dev/null +++ b/runtime/centrifuge/src/migrations.rs @@ -0,0 +1,144 @@ +// Copyright 2021 Centrifuge Foundation (centrifuge.io). +// +// This file is part of the Centrifuge chain project. +// Centrifuge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version (see http://www.gnu.org/licenses). +// Centrifuge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +use crate::{AccountId, BlockRewards, ExistentialDeposit, NativeToken, Runtime}; + +pub type UpgradeCentrifuge1019 = ( + pallet_loans_ref::migrations::v1::Migration, + session_key_migration::ExtendSessionKeys, + pallet_block_rewards::migrations::InitBlockRewards< + Runtime, + init_block_rewards::CollatorRewards, + init_block_rewards::TotalRewards, + >, + pallet_rewards::migrations::new_instance::FundExistentialDeposit< + Runtime, + pallet_rewards::Instance1, + NativeToken, + ExistentialDeposit, + >, +); + +mod init_block_rewards { + use frame_support::parameter_types; + + use crate::{Balance, CFG, MILLI_CFG}; + + parameter_types! { + // = 16.65 CFG per epoch (12h) + // https://gov.centrifuge.io/t/rfc-add-a-block-reward-and-improve-collators-cycle/4766 + pub const CollatorRewards: Balance = 8_325 * MILLI_CFG; + // = 20,096 CFG per epoch (12h) + pub const TotalRewards: Balance = 10_048 * CFG; + } +} + +mod session_key_migration { + use frame_support::{ + dispatch::GetStorageVersion, + inherent::Vec, + pallet_prelude::{StorageVersion, ValueQuery}, + storage_alias, + }; + use sp_runtime::impl_opaque_keys; + #[cfg(feature = "try-runtime")] + use { + codec::{Decode, Encode}, + frame_benchmarking::Zero, + }; + + use super::*; + use crate::{Aura, Session, SessionKeys}; + + pub struct ExtendSessionKeys; + + impl_opaque_keys! { + pub struct OldSessionKeys { + pub aura: Aura, + } + } + + #[storage_alias] + type QueuedKeys = + StorageValue, Vec<(AccountId, OldSessionKeys)>, ValueQuery>; + + impl frame_support::traits::OnRuntimeUpgrade for ExtendSessionKeys { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + let queued: Vec<(AccountId, OldSessionKeys)> = QueuedKeys::::get(); + + assert!( + !queued.len().is_zero(), + "Queued session keys must never be empty" + ); + + Ok(queued.encode()) + } + + fn on_runtime_upgrade() -> frame_support::weights::Weight { + use sp_runtime::SaturatedConversion; + + // We must not bump the storage version of pallet_session to stay in sync with + // Substrate. As this migration is tightly coupled to the initialization of + // BlockRewards, it should be sane to trigger the session migration based on the + // BlockRewards storage version. + if BlockRewards::on_chain_storage_version() == StorageVersion::new(0) { + Session::upgrade_keys::(|_, old_key| SessionKeys { + aura: old_key.aura.clone(), + block_rewards: old_key.aura, + }); + + let n: u64 = pallet_session::Validators::::get() + .len() + .saturated_into(); + + ::DbWeight::get() + .reads_writes(n.saturating_add(1), n) + } else { + ::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(pre_state: Vec) -> Result<(), &'static str> { + let pre_state: Vec<(AccountId, OldSessionKeys)> = + Decode::decode(&mut pre_state.as_slice()) + .expect("Pre state parameter should be generated by pre-upgrade hooks"); + + let queued: Vec<(AccountId, SessionKeys)> = + pallet_session::QueuedKeys::::get(); + + assert!( + pre_state.len() == queued.len(), + "Mismatch in number of session keys: pre {} vs post {}", + pre_state.len(), + queued.len() + ); + + pre_state.iter().zip(queued.into_iter()).for_each( + |((pre_acc, pre_session_key), (post_acc, post_session_key))| { + assert!(pre_acc == &post_acc, "Failed to match old validator key"); + assert!( + &pre_session_key.aura == &post_session_key.aura, + "Failed to match old aura key" + ); + assert!( + &pre_session_key.aura == &post_session_key.block_rewards, + "Block rewards key does not match aura one" + ); + }, + ); + + Ok(()) + } + } +} diff --git a/runtime/centrifuge/src/weights/mod.rs b/runtime/centrifuge/src/weights/mod.rs index 702a509ec9..6c98da1c79 100644 --- a/runtime/centrifuge/src/weights/mod.rs +++ b/runtime/centrifuge/src/weights/mod.rs @@ -13,6 +13,7 @@ pub mod cumulus_pallet_xcmp_queue; pub mod frame_system; pub mod pallet_anchors; pub mod pallet_balances; +pub mod pallet_block_rewards; pub mod pallet_collator_allowlist; pub mod pallet_collator_selection; pub mod pallet_collective; @@ -34,6 +35,7 @@ pub mod pallet_preimage; pub mod pallet_proxy; pub mod pallet_restricted_tokens; pub mod pallet_scheduler; +pub mod pallet_session; pub mod pallet_timestamp; pub mod pallet_treasury; pub mod pallet_uniques; diff --git a/runtime/centrifuge/src/weights/pallet_block_rewards.rs b/runtime/centrifuge/src/weights/pallet_block_rewards.rs new file mode 100644 index 0000000000..13a6b30434 --- /dev/null +++ b/runtime/centrifuge/src/weights/pallet_block_rewards.rs @@ -0,0 +1,58 @@ + +//! Autogenerated weights for `pallet_block_rewards` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-03-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `Laptop.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("centrifuge-local"), DB CACHE: 1024 + +// Executed Command: +// target/release/centrifuge-chain +// benchmark +// pallet +// --chain=centrifuge_local +// --steps=50 +// --repeat=20 +// --pallet=pallet_block_rewards +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=/tmp/runtime/development/src/weights/pallet_block_rewards.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_block_rewards`. +pub struct WeightInfo(PhantomData); +impl pallet_block_rewards::weights::WeightInfo for WeightInfo { + // Storage: BlockRewardsBase Currencies (r:1 w:0) + // Storage: BlockRewardsBase Groups (r:1 w:0) + // Storage: BlockRewardsBase StakeAccounts (r:1 w:1) + // Storage: System Account (r:2 w:2) + fn claim_reward() -> Weight { + // Minimum execution time: 46_000 nanoseconds. + Weight::from_ref_time(48_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: BlockRewards NextSessionChanges (r:1 w:1) + fn set_collator_reward() -> Weight { + // Minimum execution time: 7_000 nanoseconds. + Weight::from_ref_time(7_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: BlockRewards NextSessionChanges (r:1 w:1) + // Storage: BlockRewards ActiveSessionData (r:1 w:0) + fn set_total_reward() -> Weight { + // Minimum execution time: 9_000 nanoseconds. + Weight::from_ref_time(9_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } +} diff --git a/runtime/centrifuge/src/weights/pallet_session.rs b/runtime/centrifuge/src/weights/pallet_session.rs new file mode 100644 index 0000000000..e57e4bd94d --- /dev/null +++ b/runtime/centrifuge/src/weights/pallet_session.rs @@ -0,0 +1,49 @@ + +//! Autogenerated weights for `pallet_session` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-03-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `Laptop.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("centrifuge-local"), DB CACHE: 1024 + +// Executed Command: +// target/release/centrifuge-chain +// benchmark +// pallet +// --chain=centrifuge_local +// --steps=50 +// --repeat=20 +// --pallet=pallet_session +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=/tmp/runtime/development/src/weights/pallet_session.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_session`. +pub struct WeightInfo(PhantomData); +impl pallet_session::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:1) + // Storage: Session KeyOwner (r:1 w:1) + fn set_keys() -> Weight { + // Minimum execution time: 23_000 nanoseconds. + Weight::from_ref_time(23_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: Session NextKeys (r:1 w:1) + // Storage: Session KeyOwner (r:0 w:1) + fn purge_keys() -> Weight { + // Minimum execution time: 18_000 nanoseconds. + Weight::from_ref_time(19_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } +} diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 073aa3cb26..1a2c48aeab 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -8,6 +8,7 @@ homepage = "https://centrifuge.io/" repository = "https://github.com/centrifuge/centrifuge-chain" [dependencies] +serde = { version = "1.0.119" } smallvec = "1.6.1" # Substrate dependencies @@ -63,6 +64,7 @@ std = [ "cfg-types/std", "orml-traits/std", "pallet-pool-system/std", + "serde/std", "scale-info/std", "xcm/std", ] diff --git a/runtime/common/src/apis/rewards.rs b/runtime/common/src/apis/rewards.rs index 09f2281e88..5eebabc2a6 100644 --- a/runtime/common/src/apis/rewards.rs +++ b/runtime/common/src/apis/rewards.rs @@ -10,21 +10,29 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -use codec::Codec; +use codec::{Codec, Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; use sp_api::decl_runtime_apis; +use sp_core::RuntimeDebug; use sp_std::vec::Vec; +#[derive(Encode, Decode, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub enum RewardDomain { + Block, + Liquidity, +} + decl_runtime_apis! { /// Runtime API for the rewards pallet. - pub trait RewardsApi + pub trait RewardsApi where AccountId: Codec, Balance: Codec, - DomainId: Codec, CurrencyId: Codec, { - fn list_currencies(account_id: AccountId) -> Vec<(DomainId, CurrencyId)>; + fn list_currencies(domain: RewardDomain, account_id: AccountId) -> Vec; - fn compute_reward(currency_id: (DomainId, CurrencyId), account_id: AccountId) -> Option; + fn compute_reward(domain: RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option; } } diff --git a/runtime/development/src/lib.rs b/runtime/development/src/lib.rs index 722a47892e..24fca41a31 100644 --- a/runtime/development/src/lib.rs +++ b/runtime/development/src/lib.rs @@ -25,8 +25,8 @@ pub use cfg_primitives::{ types::{PoolId, *}, }; use cfg_traits::{ - rewards::AccountRewards, CurrencyPrice, OrderManager, Permissions as PermissionsT, PoolInspect, - PoolNAV, PoolUpdateGuard, PreConditions, PriceValue, TrancheCurrency as _, + CurrencyPrice, OrderManager, Permissions as PermissionsT, PoolInspect, PoolNAV, + PoolUpdateGuard, PreConditions, PriceValue, TrancheCurrency as _, }; use cfg_types::{ consts::pools::*, @@ -88,8 +88,6 @@ use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use runtime_common::fees::{DealWithFees, WeightToFee}; pub use runtime_common::*; use scale_info::TypeInfo; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; use sp_api::impl_runtime_apis; use sp_core::{OpaqueMetadata, H160, H256, U256}; use sp_inherents::{CheckInherentsResult, InherentData}; @@ -1656,15 +1654,8 @@ impl< } } -#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub enum RewardDomain { - Liquidity, - Block, -} - frame_support::parameter_types! { - pub const RewardsPalletId: PalletId = PalletId(*b"d/reward"); + pub const RewardsPalletId: PalletId = cfg_types::ids::BLOCK_REWARDS_PALLET_ID; pub const RewardCurrency: CurrencyId = CurrencyId::Native; #[derive(scale_info::TypeInfo)] @@ -1674,7 +1665,6 @@ frame_support::parameter_types! { impl pallet_rewards::Config for Runtime { type Currency = Tokens; type CurrencyId = CurrencyId; - type DomainId = RewardDomain; type GroupId = u32; type PalletId = RewardsPalletId; type RewardCurrency = RewardCurrency; @@ -1698,7 +1688,6 @@ frame_support::parameter_types! { impl pallet_rewards::Config for Runtime { type Currency = Tokens; type CurrencyId = CurrencyId; - type DomainId = RewardDomain; type GroupId = u32; type PalletId = RewardsPalletId; type RewardCurrency = RewardCurrency; @@ -1721,27 +1710,23 @@ frame_support::parameter_types! { pub const MaxChangesPerEpoch: u32 = 50; pub const InitialEpochDuration: BlockNumber = 1 * MINUTES; - - pub const LiquidityDomain: RewardDomain = RewardDomain::Liquidity; } impl pallet_liquidity_rewards::Config for Runtime { type AdminOrigin = EnsureRootOr; type Balance = Balance; type CurrencyId = CurrencyId; - type Domain = LiquidityDomain; type GroupId = u32; type InitialEpochDuration = InitialEpochDuration; type MaxChangesPerEpoch = MaxChangesPerEpoch; type MaxGroups = MaxGroups; - type Rewards = Rewards; + type Rewards = LiquidityRewardsBase; type RuntimeEvent = RuntimeEvent; type Weight = u64; type WeightInfo = (); } frame_support::parameter_types! { - pub const BlockRewardsDomain: RewardDomain = RewardDomain::Block; pub const BlockRewardCurrency: CurrencyId = CurrencyId::Staking(BlockRewardsCurrency); pub const StakeAmount: Balance = cfg_types::consts::rewards::DEFAULT_COLLATOR_STAKE; pub const CollatorGroupId: u32 = cfg_types::ids::COLLATOR_GROUP_ID; @@ -1754,7 +1739,6 @@ impl pallet_block_rewards::Config for Runtime { type Beneficiary = Treasury; type Currency = Tokens; type CurrencyId = CurrencyId; - type Domain = BlockRewardsDomain; type MaxChangesPerSession = MaxChangesPerEpoch; type MaxCollators = MaxAuthorities; type Rewards = BlockRewardsBase; @@ -1839,11 +1823,11 @@ construct_runtime!( Nfts: pallet_nft::{Pallet, Call, Event} = 103, Keystore: pallet_keystore::{Pallet, Call, Storage, Event} = 104, Investments: pallet_investments::{Pallet, Call, Storage, Event} = 105, - Rewards: pallet_rewards::::{Pallet, Storage, Event} = 106, + LiquidityRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 106, LiquidityRewards: pallet_liquidity_rewards::{Pallet, Call, Storage, Event} = 107, Connectors: pallet_connectors::{Pallet, Call, Storage, Event} = 108, PoolRegistry: pallet_pool_registry::{Pallet, Call, Storage, Event} = 109, - BlockRewardsBase: pallet_rewards::::{Pallet, Storage, Event} = 110, + BlockRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 110, BlockRewards: pallet_block_rewards::{Pallet, Call, Storage, Event, Config} = 111, TransferAllowList: pallet_transfer_allowlist::{Pallet, Call, Storage, Event} = 112, @@ -1924,13 +1908,6 @@ pub type UncheckedExtrinsic = pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic; -parameter_types! { - // = 16.65 CFG per epoch (12h) - pub const CollatorRewards: Balance = 8_325 * MILLI_CFG; - // = 20,096 CFG per epoch (12h) - pub const TotalRewards: Balance = 10_048 * CFG; -} - /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -1941,10 +1918,7 @@ pub type Executive = frame_executive::Executive< UpgradeDev1020, >; -type UpgradeDev1020 = ( - pallet_block_rewards::migrations::InitBlockRewards, - pallet_loans_ref::migrations::v1::Migration, -); +type UpgradeDev1020 = (); impl fp_self_contained::SelfContainedCall for RuntimeCall { type SignedInfo = H160; @@ -2197,20 +2171,19 @@ impl_runtime_apis! { } // RewardsApi - impl runtime_common::apis::RewardsApi for Runtime { - fn list_currencies(account_id: AccountId) -> Vec<(RewardDomain, CurrencyId)> { - pallet_rewards::Pallet::::list_currencies(&account_id) - .into_iter().chain( - pallet_rewards::Pallet::::list_currencies(&account_id).into_iter() - ).collect() + impl runtime_common::apis::RewardsApi for Runtime { + fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec { + match domain { + runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), + runtime_common::apis::RewardDomain::Liquidity => pallet_rewards::Pallet::::list_currencies(&account_id), + } } - fn compute_reward(currency_id: (RewardDomain, CurrencyId), account_id: AccountId) -> Option { - as AccountRewards>::compute_reward(currency_id, &account_id) - .or_else(|_| - as AccountRewards>::compute_reward(currency_id, &account_id) - ) - .ok() + fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option { + match domain { + runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), + runtime_common::apis::RewardDomain::Liquidity => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), + } } } diff --git a/runtime/integration-tests/src/rewards/block/env.rs b/runtime/integration-tests/src/rewards/block/env.rs index ed0af865f5..ef367bb3c7 100644 --- a/runtime/integration-tests/src/rewards/block/env.rs +++ b/runtime/integration-tests/src/rewards/block/env.rs @@ -17,6 +17,7 @@ use tokio::runtime::Handle; use crate::{ chain::centrifuge::{CollatorSelection, Runtime, PARA_ID}, + rewards::block::invariants::assert_all_staked, utils::{ accounts::Keyring, env::test_env_with_centrifuge_storage, @@ -66,3 +67,15 @@ async fn env_works() { && !invulnerables.iter().any(|invulnerable| invulnerable == j))); }); } + +#[tokio::test] +async fn genesis_collators_are_staked() { + let mut genesis = Storage::default(); + default_genesis_block_rewards(&mut genesis); + let mut env = test_env_with_centrifuge_storage(Handle::current(), genesis); + + // Ensure default collators are neither candidates nor invulnerables + env.with_state(Chain::Para(PARA_ID), || { + assert_all_staked(&[Keyring::Admin.to_account_id()]); + }); +} diff --git a/runtime/integration-tests/src/rewards/block/invariants.rs b/runtime/integration-tests/src/rewards/block/invariants.rs index 8c5bd7fa03..5fcf7326ce 100644 --- a/runtime/integration-tests/src/rewards/block/invariants.rs +++ b/runtime/integration-tests/src/rewards/block/invariants.rs @@ -98,13 +98,10 @@ pub(crate) fn assert_session_invariants( } /// Verifies that each provided account address is staked for block rewards. -fn assert_all_staked(v: &[AccountId]) { +pub(crate) fn assert_all_staked(v: &[AccountId]) { assert!(v.iter().all(|acc| { !::Rewards::account_stake( - ( - ::Domain::get(), - ::StakeCurrencyId::get(), - ), + ::StakeCurrencyId::get(), acc, ) .is_zero() @@ -116,10 +113,7 @@ fn assert_all_staked(v: &[AccountId]) { fn assert_all_not_staked(v: &[AccountId]) { assert!(v.iter().all(|acc| { ::Rewards::account_stake( - ( - ::Domain::get(), - ::StakeCurrencyId::get(), - ), + ::StakeCurrencyId::get(), acc, ) .is_zero() diff --git a/runtime/integration-tests/src/rewards/block/session_advances.rs b/runtime/integration-tests/src/rewards/block/session_advances.rs index effd189372..957b5e537a 100644 --- a/runtime/integration-tests/src/rewards/block/session_advances.rs +++ b/runtime/integration-tests/src/rewards/block/session_advances.rs @@ -128,10 +128,7 @@ async fn collator_list_synchronized() { for collator in collator_accounts[0..2].iter() { assert!( !::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get(), - ), + ::StakeCurrencyId::get(), collator.into(), ) .unwrap() @@ -141,10 +138,7 @@ async fn collator_list_synchronized() { for collator in collator_accounts[2..].iter() { assert!( ::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get(), - ), + ::StakeCurrencyId::get(), collator.into(), ) .unwrap() @@ -159,10 +153,7 @@ async fn collator_list_synchronized() { for collator in collator_accounts[2..].iter() { assert!( !::Rewards::compute_reward( - ( - ::Domain::get(), - ::StakeCurrencyId::get(), - ), + ::StakeCurrencyId::get(), collator.into(), ) .unwrap() diff --git a/runtime/integration-tests/src/runtime_apis/rewards.rs b/runtime/integration-tests/src/runtime_apis/rewards.rs index 6ff23bf2a3..91989a0441 100644 --- a/runtime/integration-tests/src/runtime_apis/rewards.rs +++ b/runtime/integration-tests/src/runtime_apis/rewards.rs @@ -10,78 +10,77 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -use cfg_primitives::{AccountId, CFG}; -use cfg_traits::rewards::{AccountRewards, CurrencyGroupChange, DistributedRewards}; +use cfg_primitives::{AccountId, Balance, CFG}; +use cfg_traits::rewards::{AccountRewards, CurrencyGroupChange, DistributedRewards, GroupRewards}; use cfg_types::tokens::CurrencyId; use development_runtime::apis::RewardsApi; use frame_support::assert_ok; +use runtime_common::apis::RewardDomain; use sp_core::{sr25519, Pair}; use sp_runtime::traits::IdentifyAccount; use tokio::runtime::Handle; use super::ApiEnv; +use crate::utils::accounts::Keyring; #[tokio::test] -async fn test() { +async fn liquidity_rewards_runtime_api_works() { + rewards_runtime_api_works::(RewardDomain::Liquidity) + .await; +} + +#[tokio::test] +async fn block_rewards_runtime_api_works() { + rewards_runtime_api_works::(RewardDomain::Block).await; +} + +type GroupId = u32; + +async fn rewards_runtime_api_works(domain: RewardDomain) +where + Rewards: CurrencyGroupChange + + AccountRewards + + DistributedRewards + + GroupRewards, +{ + let staker = Keyring::Alice.to_account_id(); + let expected_reward = 200 * CFG; ApiEnv::new(Handle::current()) .startup(|| { - let currencies = vec![( - (development_runtime::RewardDomain::Block, CurrencyId::Native), - 1, - )]; - let stake_accounts = vec![( - sp_runtime::AccountId32::from( - ::from_string("//Alice", None) - .unwrap() - .public() - .into_account(), - ), - (development_runtime::RewardDomain::Block, CurrencyId::Native), - 100 * CFG, - )]; - let rewards = vec![(1, 200 * CFG)]; + let currencies = vec![(CurrencyId::Native, 1u32)]; + let stake_accounts = vec![(staker.clone(), CurrencyId::Native, 100 * CFG)]; + let rewards = vec![(1, expected_reward)]; - for ((domain_id, currency_id), group_id) in currencies { - ::attach_currency( - (domain_id, currency_id), - group_id, - ) - .unwrap(); + for (currency_id, group_id) in currencies { + ::attach_currency(currency_id, group_id) + .expect("Attaching currency should work"); } - for (account_id, (domain_id, currency_id), amount) in stake_accounts { - >::deposit_stake( - (domain_id, currency_id), + for (account_id, currency_id, amount) in stake_accounts { + >::deposit_stake( + currency_id, &account_id, amount, ) - .unwrap(); + .expect("Depositing stake should work"); } for (group_id, amount) in rewards { - ::distribute_reward( - amount, - [group_id], - ) - .unwrap(); + ::distribute_reward(amount, [group_id]) + .expect("Distributing rewards should work"); } }) .with_api(|api, latest| { - let account_id = sp_runtime::AccountId32::from( - ::from_string("//Alice", None) - .unwrap() - .public() - .into_account(), - ); - - let currencies = api.list_currencies(&latest, account_id.clone()).unwrap(); + let currencies = api + .list_currencies(&latest, domain.clone(), staker.clone()) + .expect("There should be staked currencies"); assert_eq!(currencies.clone().len(), 1); let currency_id = currencies[0]; let reward = api - .compute_reward(&latest, currency_id, account_id) + .compute_reward(&latest, domain, currency_id, staker) .unwrap(); - assert_eq!(reward, Some(200 * CFG)); + assert_eq!(reward, Some(expected_reward)); }); } diff --git a/src/chain_spec.rs b/src/chain_spec.rs index 01e7a6694c..7f80522702 100644 --- a/src/chain_spec.rs +++ b/src/chain_spec.rs @@ -22,7 +22,7 @@ // module level. #![allow(clippy::derive_partial_eq_without_eq)] -use altair_runtime::constants::currency::AIR; +use altair_runtime::constants::currency::{AIR, MILLI_AIR}; use cfg_primitives::{currency_decimals, parachains, Balance, CFG, MILLI_CFG}; use cfg_types::{ fee_keys::FeeKey, @@ -78,13 +78,19 @@ impl Extensions { } pub fn get_altair_session_keys(keys: altair_runtime::AuraId) -> altair_runtime::SessionKeys { - altair_runtime::SessionKeys { aura: keys } + altair_runtime::SessionKeys { + aura: keys.clone(), + block_rewards: keys, + } } pub fn get_centrifuge_session_keys( keys: centrifuge_runtime::AuraId, ) -> centrifuge_runtime::SessionKeys { - centrifuge_runtime::SessionKeys { aura: keys } + centrifuge_runtime::SessionKeys { + aura: keys.clone(), + block_rewards: keys, + } } pub fn get_development_session_keys( @@ -876,6 +882,19 @@ fn centrifuge_genesis( }, treasury: Default::default(), interest_accrual: Default::default(), + block_rewards: centrifuge_runtime::BlockRewardsConfig { + collators: initial_authorities + .iter() + .cloned() + .map(|(acc, _)| acc) + .collect(), + collator_reward: 8_325 * MILLI_CFG, + total_reward: 10_048 * CFG, + }, + block_rewards_base: centrifuge_runtime::BlockRewardsBaseConfig { + currency_id: CurrencyId::Native, + amount: centrifuge_runtime::ExistentialDeposit::get(), + }, } } @@ -941,6 +960,19 @@ fn altair_genesis( candidacy_bond: 1 * AIR, ..Default::default() }, + block_rewards: altair_runtime::BlockRewardsConfig { + collators: initial_authorities + .iter() + .cloned() + .map(|(acc, _)| acc) + .collect(), + collator_reward: 98_630 * MILLI_AIR, + total_reward: 98_630 * MILLI_AIR * 100, + }, + block_rewards_base: altair_runtime::BlockRewardsBaseConfig { + currency_id: CurrencyId::Native, + amount: altair_runtime::ExistentialDeposit::get(), + }, collator_allowlist: Default::default(), session: altair_runtime::SessionConfig { keys: initial_authorities @@ -1107,6 +1139,14 @@ fn development_genesis( evm_chain_id: development_runtime::EVMChainIdConfig { chain_id: 999_999 }, ethereum: Default::default(), evm: Default::default(), + block_rewards_base: development_runtime::BlockRewardsBaseConfig { + currency_id: CurrencyId::Native, + amount: development_runtime::ExistentialDeposit::get(), + }, + liquidity_rewards_base: development_runtime::LiquidityRewardsBaseConfig { + currency_id: CurrencyId::Native, + amount: development_runtime::ExistentialDeposit::get(), + }, } } diff --git a/src/rpc/rewards.rs b/src/rpc/rewards.rs index 7cd1b55d4c..6d6af7d088 100644 --- a/src/rpc/rewards.rs +++ b/src/rpc/rewards.rs @@ -2,7 +2,7 @@ use std::{fmt::Debug, sync::Arc}; use codec::Codec; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; -use runtime_common::apis::RewardsApi as RewardsRuntimeApi; +use runtime_common::apis::{RewardDomain, RewardsApi as RewardsRuntimeApi}; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_runtime::{generic::BlockId, traits::Block as BlockT}; @@ -10,18 +10,20 @@ use sp_runtime::{generic::BlockId, traits::Block as BlockT}; use crate::rpc::{invalid_params_error, runtime_error}; #[rpc(client, server)] -pub trait RewardsApi { +pub trait RewardsApi { #[method(name = "rewards_listCurrencies")] fn list_currencies( &self, + domain: RewardDomain, account_id: AccountId, at: Option, - ) -> RpcResult>; + ) -> RpcResult>; #[method(name = "rewards_computeReward")] fn compute_reward( &self, - currency_id: (RewardDomain, CurrencyId), + domain: RewardDomain, + currency_id: CurrencyId, account_id: AccountId, at: Option, ) -> RpcResult; @@ -41,22 +43,22 @@ impl Rewards { } } -impl - RewardsApiServer for Rewards +impl + RewardsApiServer for Rewards where Block: BlockT, C: Send + Sync + 'static + ProvideRuntimeApi + HeaderBackend, - C::Api: RewardsRuntimeApi, + C::Api: RewardsRuntimeApi, AccountId: Codec, Balance: Codec + Copy, - RewardDomain: Codec + Copy + Debug, CurrencyId: Codec + Copy + Debug, { fn list_currencies( &self, + domain: RewardDomain, account_id: AccountId, at: Option, - ) -> RpcResult> { + ) -> RpcResult> { let api = self.client.runtime_api(); let at = if let Some(hash) = at { @@ -65,13 +67,14 @@ where BlockId::hash(self.client.info().best_hash) }; - api.list_currencies(&at, account_id) + api.list_currencies(&at, domain, account_id) .map_err(|e| runtime_error("Unable to list currencies", e)) } fn compute_reward( &self, - currency_id: (RewardDomain, CurrencyId), + domain: RewardDomain, + currency_id: CurrencyId, account_id: AccountId, at: Option, ) -> RpcResult { @@ -83,7 +86,7 @@ where BlockId::hash(self.client.info().best_hash) }; - api.compute_reward(&at, currency_id, account_id) + api.compute_reward(&at, domain, currency_id, account_id) .map_err(|e| runtime_error("Unable to compute reward", e))? .ok_or_else(|| invalid_params_error("Reward not found")) }