Skip to content

Commit

Permalink
Tier config recalculation at the start of each era
Browse files Browse the repository at this point in the history
  • Loading branch information
Dinonard committed Apr 29, 2024
1 parent 19b60fa commit f37a415
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 13 deletions.
13 changes: 6 additions & 7 deletions pallets/dapp-staking-v3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1902,13 +1902,6 @@ pub mod pallet {

era_info.migrate_to_next_era(Some(protocol_state.subperiod()));

// Re-calculate tier configuration for the upcoming new period
let tier_params = StaticTierParams::<T>::get();
let average_price = T::NativePriceProvider::average_price();
let new_tier_config =
TierConfig::<T>::get().calculate_new(average_price, &tier_params);
TierConfig::<T>::put(new_tier_config);

// Update historical cleanup marker.
// Must be called with the new period number.
Self::update_cleanup_marker(protocol_state.period_number());
Expand Down Expand Up @@ -1958,6 +1951,12 @@ pub mod pallet {
}
EraRewards::<T>::insert(&era_span_index, span);

// Re-calculate tier configuration for the upcoming new era
let tier_params = StaticTierParams::<T>::get();
let average_price = T::NativePriceProvider::average_price();
let new_tier_config = TierConfig::<T>::get().calculate_new(average_price, &tier_params);
TierConfig::<T>::put(new_tier_config);

Self::deposit_event(Event::<T>::NewEra { era: next_era });
if let Some(period_event) = maybe_period_event {
Self::deposit_event(period_event);
Expand Down
8 changes: 5 additions & 3 deletions pallets/dapp-staking-v3/src/test/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,14 @@ impl pallet_balances::Config for Test {
pub struct DummyPriceProvider;
impl PriceProvider for DummyPriceProvider {
fn average_price() -> FixedU128 {
FixedU128::from_rational(1, 10)
NATIVE_PRICE.with(|v| v.borrow().clone())
}
}

thread_local! {
pub(crate) static DOES_PAYOUT_SUCCEED: RefCell<bool> = RefCell::new(false);
pub(crate) static BLOCK_BEFORE_NEW_ERA: RefCell<EraNumber> = RefCell::new(0);
pub(crate) static NATIVE_PRICE: RefCell<FixedU128> = RefCell::new(FixedU128::from_rational(1, 100));
}

pub struct DummyStakingRewardHandler;
Expand Down Expand Up @@ -310,7 +311,7 @@ impl ExtBuilder {
.unwrap(),
};

// Init tier config, based on the initial params
// Init tier config, based on the initial params. Needs to be adjusted to the init price.
let init_tier_config = TiersConfiguration::<
<Test as Config>::NumberOfTiers,
<Test as Config>::TierSlots,
Expand All @@ -320,7 +321,8 @@ impl ExtBuilder {
reward_portion: tier_params.reward_portion.clone(),
tier_thresholds: tier_params.tier_thresholds.clone(),
_phantom: Default::default(),
};
}
.calculate_new(NATIVE_PRICE.with(|v| v.borrow().clone()), &tier_params);

pallet_dapp_staking::StaticTierParams::<Test>::put(tier_params);
pallet_dapp_staking::TierConfig::<Test>::put(init_tier_config.clone());
Expand Down
68 changes: 65 additions & 3 deletions pallets/dapp-staking-v3/src/test/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ use frame_support::{
fungible::Unbalanced as FunUnbalanced, Currency, Get, OnFinalize, OnInitialize,
ReservableCurrency,
},
BoundedVec,
};
use sp_runtime::traits::Zero;
use sp_runtime::{traits::Zero, FixedU128};

use astar_primitives::{
dapp_staking::{CycleConfiguration, EraNumber, SmartContractHandle},
Expand Down Expand Up @@ -2324,11 +2325,72 @@ fn force_with_safeguard_on_fails() {
})
}

#[test]
fn tier_config_recalculation_works() {
ExtBuilder::build().execute_with(|| {
let init_price = NATIVE_PRICE.with(|v| v.borrow().clone());
let init_tier_config = TierConfig::<Test>::get();

// 1. Advance to a new era, while keeping native price the same. Expect no change in the tier config
assert_ok!(DappStaking::force(RuntimeOrigin::root(), ForcingType::Era));
run_for_blocks(1);

assert_eq!(
init_tier_config,
TierConfig::<Test>::get(),
"Native price didn't change so tier config should remain the same."
);

// 2. Increase the native price, and expect number of tiers to be increased.
NATIVE_PRICE.with(|v| *v.borrow_mut() = init_price * FixedU128::from(3));

assert_ok!(DappStaking::force(RuntimeOrigin::root(), ForcingType::Era));
run_for_blocks(1);

let new_tier_config = TierConfig::<Test>::get();
assert!(
new_tier_config.number_of_slots > init_tier_config.number_of_slots,
"Price has increased, therefore number of slots must increase."
);
assert_eq!(
init_tier_config.slots_per_tier.len(),
new_tier_config.slots_per_tier.len(),
"Sanity check."
);
for idx in 0..init_tier_config.slots_per_tier.len() {
assert!(init_tier_config.slots_per_tier[idx] < new_tier_config.slots_per_tier[idx]);
}

// 3. Decrease the native price, and expect number of tiers to be increased.
NATIVE_PRICE.with(|v| *v.borrow_mut() = init_price * FixedU128::from_rational(1, 2));

assert_ok!(DappStaking::force(RuntimeOrigin::root(), ForcingType::Era));
run_for_blocks(1);

let new_tier_config = TierConfig::<Test>::get();
assert!(
new_tier_config.number_of_slots < init_tier_config.number_of_slots,
"Price has decreased, therefore number of slots must decrease."
);
assert_eq!(
init_tier_config.slots_per_tier.len(),
new_tier_config.slots_per_tier.len(),
"Sanity check."
);
for idx in 0..init_tier_config.slots_per_tier.len() {
assert!(init_tier_config.slots_per_tier[idx] > new_tier_config.slots_per_tier[idx]);
}
})
}

#[test]
fn get_dapp_tier_assignment_and_rewards_basic_example_works() {
ExtBuilder::build().execute_with(|| {
// This test will rely on the configuration inside the mock file.
// If that changes, this test will have to be updated as well.
// Tier config is specially adapter for this test.
TierConfig::<Test>::mutate(|config| {
config.number_of_slots = 40;
config.slots_per_tier = BoundedVec::try_from(vec![2, 5, 13, 20]).unwrap();
});

// Scenario:
// - 1st tier is filled up, with one dApp satisfying the threshold but not making it due to lack of tier capacity
Expand Down

0 comments on commit f37a415

Please sign in to comment.