Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,648 changes: 1,325 additions & 1,323 deletions Cargo.lock

Large diffs are not rendered by default.

234 changes: 117 additions & 117 deletions Cargo.toml

Large diffs are not rendered by default.

18 changes: 16 additions & 2 deletions pallets/parachain-staking/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,16 +603,31 @@ benchmarks! {
}

claim_rewards {
let treasury_account = T::TreasuryAccount::get();
let reward_amount = T::MinCollatorCandidateStake::get();

let beneficiary = account("beneficiary", 0, 0);
let amount = T::MinCollatorCandidateStake::get();
T::Currency::make_free_balance_be(&beneficiary, amount);
Rewards::<T>::insert(&beneficiary, amount);

let initial_issuance = T::Currency::total_issuance();
let initial_treasury_balance = T::Currency::free_balance(&treasury_account);

assert_eq!(pallet_balances::Pallet::<T>::usable_balance(&beneficiary), amount.into());
let origin = RawOrigin::Signed(beneficiary.clone());
}: _(origin)
verify {
assert!(Rewards::<T>::get(&beneficiary).is_zero());
assert_eq!(pallet_balances::Pallet::<T>::usable_balance(&beneficiary), (amount + amount).into());
assert_eq!(
pallet_balances::Pallet::<T>::usable_balance(&beneficiary),
(amount + reward_amount).into()
);
assert_eq!(
T::Currency::free_balance(&treasury_account),
initial_treasury_balance - reward_amount
);
assert_eq!(T::Currency::total_issuance(), initial_issuance);
}

execute_scheduled_reward_change {
Expand Down Expand Up @@ -645,7 +660,6 @@ benchmarks! {
impl_benchmark_test_suite!(
Pallet,
crate::mock::ExtBuilder::default()
.with_balances(vec![(u64::MAX, 1000 * crate::mock::MILLI_KILT)])
.with_collators(vec![(u64::MAX, 1000 * crate::mock::MILLI_KILT)])
.build(),
crate::mock::Test,
Expand Down
28 changes: 24 additions & 4 deletions pallets/parachain-staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ use frame_support::pallet;

pub use crate::{default_weights::WeightInfo, pallet::*};
pub use module_pallet_staking_rpc_runtime_api::StakingRates;
pub use crate::types::AccountIdOf;

#[pallet]
pub mod pallet {
Expand All @@ -146,7 +147,7 @@ pub mod pallet {
pallet_prelude::*,
storage::bounded_btree_map::BoundedBTreeMap,
traits::{
Currency, EstimateNextSessionRotation, Get, Imbalance, LockIdentifier,
Currency, EstimateNextSessionRotation, Get, LockIdentifier,
LockableCurrency, OnUnbalanced, ReservableCurrency, StorageVersion, WithdrawReasons,
},
BoundedVec,
Expand Down Expand Up @@ -310,6 +311,11 @@ pub mod pallet {
type WeightInfo: WeightInfo;

const BLOCKS_PER_YEAR: BlockNumberFor<Self>;

/// Used for getting the treasury account
#[pallet::constant]
type TreasuryAccount: Get<AccountIdOf<Self>>;

}

#[pallet::error]
Expand Down Expand Up @@ -404,6 +410,10 @@ pub mod pallet {
UnstakingIsEmpty,
/// Cannot claim rewards if empty.
RewardsNotFound,
/// Treasury balance is insufficient for the operation.
TreasuryBalanceInsufficient,
/// Failed to transfer from treasury.
TreasuryTransferFailed,
}

#[pallet::event]
Expand Down Expand Up @@ -1721,11 +1731,21 @@ pub mod pallet {
let rewards = Rewards::<T>::get(&target);
ensure!(!rewards.is_zero(), Error::<T>::RewardsNotFound);

// mint into target and reset rewards
let rewards = T::Currency::deposit_into_existing(&target, rewards)?;
let treasury_account_id = T::TreasuryAccount::get();
let treasury_balance = T::Currency::free_balance(&treasury_account_id);
ensure!(treasury_balance >= rewards, Error::<T>::TreasuryBalanceInsufficient);

T::Currency::transfer(
&treasury_account_id,
&target,
rewards,
frame_support::traits::ExistenceRequirement::KeepAlive,
)
.map_err(|_| Error::<T>::TreasuryTransferFailed)?;

Rewards::<T>::remove(&target);

Self::deposit_event(Event::Rewarded(target, rewards.peek()));
Self::deposit_event(Event::Rewarded(target, rewards));

Ok(())
}
Expand Down
12 changes: 11 additions & 1 deletion pallets/parachain-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub(crate) const MAX_COLLATOR_STAKE: Balance = 200_000 * 1000 * MILLI_KILT;
pub(crate) const BLOCKS_PER_ROUND: BlockNumber = 5;
pub(crate) const DECIMALS: Balance = 1000 * MILLI_KILT;
pub(crate) const TREASURY_ACC: AccountId = u64::MAX;
pub(crate) const TREASURY_INITIAL_BALANCE_UNITS: u128 = 400_000;
pub(crate) const TREASURY_INITIAL_BALANCE: u128 = TREASURY_INITIAL_BALANCE_UNITS * 1000 * MILLI_KILT;

// Configure a mock runtime to test the pallet.
construct_runtime!(
Expand Down Expand Up @@ -153,6 +155,11 @@ impl OnUnbalanced<NegativeImbalanceOf<Test>> for ToBeneficiary {
}
}

parameter_types! {
pub const TreasuryAccount: AccountId = TREASURY_ACC;
}


impl Config for Test {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
Expand All @@ -176,6 +183,7 @@ impl Config for Test {
type CollatorRewardRateDecay = CollatorRewardRateDecay;
type WeightInfo = ();
const BLOCKS_PER_YEAR: BlockNumber = 5 * 60 * 24 * 36525 / 100;
type TreasuryAccount = TreasuryAccount;
}

impl_opaque_keys! {
Expand Down Expand Up @@ -296,7 +304,9 @@ impl ExtBuilder {
.build_storage()
.expect("Frame system builds valid default genesis config");

pallet_balances::GenesisConfig::<Test> { balances: self.balances.clone() }
let mut balances = self.balances.clone();
balances.push((TREASURY_ACC, TREASURY_INITIAL_BALANCE));
pallet_balances::GenesisConfig::<Test> { balances }
.assimilate_storage(&mut t)
.expect("Pallet balances storage can be assimilated");

Expand Down
46 changes: 26 additions & 20 deletions pallets/parachain-staking/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{
mock::{
almost_equal, events, last_event, roll_to, roll_to_claim_rewards, AccountId, Balance,
Balances, BlockNumber, ExtBuilder, RuntimeEvent as MetaEvent, RuntimeOrigin as Origin,
Session, StakePallet, System, Test, BLOCKS_PER_ROUND, DECIMALS, TREASURY_ACC,
Session, StakePallet, System, Test, BLOCKS_PER_ROUND, DECIMALS, TREASURY_ACC, TREASURY_INITIAL_BALANCE_UNITS,
},
set::OrderedSet,
types::{
Expand Down Expand Up @@ -1429,7 +1429,8 @@ fn coinbase_rewards_few_blocks_detailed_check() {
.execute_with(|| {
let inflation = StakePallet::inflation_config();
let total_issuance = <Test as Config>::Currency::total_issuance();
assert_eq!(total_issuance, 160_000_000 * DECIMALS);
const EXPECTED_TOTAL_ISSUANCE: BalanceOf<Test> = 160_000_000 + TREASURY_INITIAL_BALANCE_UNITS;
assert_eq!(total_issuance, EXPECTED_TOTAL_ISSUANCE * DECIMALS);

// compute rewards
let c_staking_rate = Perquintill::from_rational(16_000_000 * DECIMALS, total_issuance);
Expand Down Expand Up @@ -1568,9 +1569,11 @@ fn coinbase_rewards_many_blocks_simple_check() {
.with_inflation(10, 15, 40, 15, 5)
.build()
.execute_with(|| {

let inflation = StakePallet::inflation_config();
let total_issuance = <Test as Config>::Currency::total_issuance();
assert_eq!(total_issuance, 160_000_000 * DECIMALS);
const EXPECTED_TOTAL_ISSUANCE: BalanceOf<Test> = 160_000_000 + TREASURY_INITIAL_BALANCE_UNITS;
assert_eq!(total_issuance, EXPECTED_TOTAL_ISSUANCE * DECIMALS);
let end_block: BlockNumber = num_of_years * Test::BLOCKS_PER_YEAR as BlockNumber;
// set round robin authoring
let authors: Vec<Option<AccountId>> =
Expand Down Expand Up @@ -3299,13 +3302,14 @@ fn network_reward_multiple_blocks() {
let total_collator_stake =
max_stake.saturating_mul(<Test as Config>::MinCollators::get().into());
assert_eq!(total_collator_stake, StakePallet::total_collator_stake().collators);
assert!(Balances::free_balance(&TREASURY_ACC).is_zero());
let initial_treasury_balance: Balance = Balances::free_balance(&TREASURY_ACC);

let total_issuance = <Test as Config>::Currency::total_issuance();

// total issuance should not increase when not noting authors because we haven't
// reached NetworkRewardStart yet
roll_to(10, vec![None]);
assert!(Balances::free_balance(&TREASURY_ACC).is_zero());
assert_eq!(initial_treasury_balance, Balances::free_balance(&TREASURY_ACC));
assert_eq!(total_issuance, <Test as Config>::Currency::total_issuance());

// set current block to one block before NetworkRewardStart
Expand All @@ -3314,12 +3318,12 @@ fn network_reward_multiple_blocks() {

// network rewards should only appear 1 block after start
roll_to(network_reward_start, vec![None]);
assert!(Balances::free_balance(&TREASURY_ACC).is_zero());
assert_eq!(initial_treasury_balance, Balances::free_balance(&TREASURY_ACC));
assert_eq!(total_issuance, <Test as Config>::Currency::total_issuance());

// should mint to treasury now
roll_to(network_reward_start + 1, vec![None]);
let network_reward = Balances::free_balance(&TREASURY_ACC);
let network_reward = Balances::free_balance(&TREASURY_ACC).saturating_sub(initial_treasury_balance);
assert!(!network_reward.is_zero());
assert_eq!(
total_issuance + network_reward,
Expand All @@ -3332,15 +3336,15 @@ fn network_reward_multiple_blocks() {

// should mint exactly the same amount
roll_to(network_reward_start + 2, vec![None]);
assert_eq!(2 * network_reward, Balances::free_balance(&TREASURY_ACC));
assert_eq!(2 * network_reward, Balances::free_balance(&TREASURY_ACC).saturating_sub(initial_treasury_balance));
assert_eq!(
total_issuance + 2 * network_reward,
<Test as Config>::Currency::total_issuance()
);

// should mint exactly the same amount in each block
roll_to(network_reward_start + 100, vec![None]);
assert_eq!(100 * network_reward, Balances::free_balance(&TREASURY_ACC));
assert_eq!(100 * network_reward, Balances::free_balance(&TREASURY_ACC).saturating_sub(initial_treasury_balance));
assert_eq!(
total_issuance + 100 * network_reward,
<Test as Config>::Currency::total_issuance()
Expand All @@ -3350,7 +3354,7 @@ fn network_reward_multiple_blocks() {
// based on MaxCollatorCandidateStake and MaxSelectedCandidates
assert_ok!(StakePallet::init_leave_candidates(Origin::signed(1)));
roll_to(network_reward_start + 101, vec![None]);
assert_eq!(101 * network_reward, Balances::free_balance(&TREASURY_ACC));
assert_eq!(101 * network_reward, Balances::free_balance(&TREASURY_ACC).saturating_sub(initial_treasury_balance));
assert_eq!(
total_issuance + 101 * network_reward,
<Test as Config>::Currency::total_issuance()
Expand All @@ -3375,9 +3379,10 @@ fn network_reward_increase_max_candidate_stake() {
let total_issuance = <Test as Config>::Currency::total_issuance();
System::set_block_number(network_reward_start);

let initial_treasury_balance: Balance = Balances::free_balance(&TREASURY_ACC);
// should mint to treasury now
roll_to(network_reward_start + 1, vec![None]);
let reward_before = Balances::free_balance(&TREASURY_ACC);
let reward_before = Balances::free_balance(&TREASURY_ACC).saturating_sub(initial_treasury_balance);
assert!(!reward_before.is_zero());
assert_eq!(
total_issuance + reward_before,
Expand All @@ -3389,7 +3394,7 @@ fn network_reward_increase_max_candidate_stake() {
let reward_after = 2 * reward_before;
assert_ok!(StakePallet::set_max_candidate_stake(Origin::root(), max_stake_doubled));
roll_to(network_reward_start + 2, vec![None]);
assert_eq!(reward_before + reward_after, Balances::free_balance(&TREASURY_ACC));
assert_eq!(reward_before + reward_after, Balances::free_balance(&TREASURY_ACC).saturating_sub(initial_treasury_balance));
assert_eq!(
reward_before + reward_after + total_issuance,
<Test as Config>::Currency::total_issuance()
Expand All @@ -3414,9 +3419,10 @@ fn network_reward_increase_max_collator_count() {
let total_issuance = <Test as Config>::Currency::total_issuance();
System::set_block_number(network_reward_start);

let initial_treasury_balance: Balance = Balances::free_balance(&TREASURY_ACC);
// should mint to treasury now
roll_to(network_reward_start + 1, vec![None]);
let reward_before = Balances::free_balance(&TREASURY_ACC);
let reward_before = Balances::free_balance(&TREASURY_ACC).saturating_sub(initial_treasury_balance);
assert!(!reward_before.is_zero());
assert_eq!(
total_issuance + reward_before,
Expand All @@ -3430,7 +3436,7 @@ fn network_reward_increase_max_collator_count() {
<Test as Config>::MinCollators::get() * 3
));
roll_to(network_reward_start + 2, vec![None]);
assert_eq!(reward_before + reward_after, Balances::free_balance(&TREASURY_ACC));
assert_eq!(reward_before + reward_after, Balances::free_balance(&TREASURY_ACC).saturating_sub(initial_treasury_balance));
assert_eq!(
reward_before + reward_after + total_issuance,
<Test as Config>::Currency::total_issuance()
Expand Down Expand Up @@ -4083,9 +4089,9 @@ fn api_get_staking_rates() {
.build()
.execute_with(|| {
let mut rates = StakingRates {
collator_staking_rate: Perquintill::from_percent(50),
collator_reward_rate: Perquintill::from_percent(5),
delegator_staking_rate: Perquintill::from_percent(25),
collator_staking_rate: Perquintill::from_percent(25),
collator_reward_rate: Perquintill::from_percent(10),
delegator_staking_rate: Perquintill::from_float(0.125),
delegator_reward_rate: Perquintill::from_percent(8),
};
// collators exceed max staking rate
Expand All @@ -4096,10 +4102,10 @@ fn api_get_staking_rates() {
assert_ok!(StakePallet::candidate_stake_less(Origin::signed(2), stake / 2));
// delegator stakes more to exceed
assert_ok!(StakePallet::delegator_stake_more(Origin::signed(3), 1, stake));
rates.collator_staking_rate = Perquintill::from_percent(25);
rates.collator_staking_rate = Perquintill::from_float(0.125);
rates.collator_reward_rate = Perquintill::from_percent(10);
rates.delegator_staking_rate = Perquintill::from_percent(50);
rates.delegator_reward_rate = Perquintill::from_percent(4);
rates.delegator_staking_rate = Perquintill::from_percent(25);
rates.delegator_reward_rate = Perquintill::from_percent(8);
assert_eq!(rates, StakePallet::get_staking_rates());
});
}
2 changes: 1 addition & 1 deletion runtime/amplitude/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -960,8 +960,8 @@ impl parachain_staking::Config for Runtime {
type NetworkRewardBeneficiary = Treasury;
type CollatorRewardRateDecay = CollatorRewardRateDecay;
type WeightInfo = weights::parachain_staking::SubstrateWeight<Runtime>;

const BLOCKS_PER_YEAR: BlockNumber = BLOCKS_PER_YEAR;
type TreasuryAccount = AmplitudeTreasuryAccount;
}

parameter_types! {
Expand Down
2 changes: 1 addition & 1 deletion runtime/foucoco/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -936,8 +936,8 @@ impl parachain_staking::Config for Runtime {
type NetworkRewardBeneficiary = Treasury;
type CollatorRewardRateDecay = CollatorRewardRateDecay;
type WeightInfo = weights::parachain_staking::SubstrateWeight<Runtime>;

const BLOCKS_PER_YEAR: BlockNumber = BLOCKS_PER_YEAR;
type TreasuryAccount = FoucocoTreasuryAccount;
}

impl pallet_sudo::Config for Runtime {
Expand Down
2 changes: 1 addition & 1 deletion runtime/pendulum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -962,8 +962,8 @@ impl parachain_staking::Config for Runtime {
type NetworkRewardBeneficiary = Treasury;
type CollatorRewardRateDecay = CollatorRewardRateDecay;
type WeightInfo = weights::parachain_staking::SubstrateWeight<Runtime>;

const BLOCKS_PER_YEAR: BlockNumber = BLOCKS_PER_YEAR;
type TreasuryAccount = PendulumTreasuryAccount;
}

parameter_types! {
Expand Down
Loading