Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tier config recalculation at the start of each era #1230

Merged
Merged
Show file tree
Hide file tree
Changes from 2 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
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, 10));
}

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.
Dinonard marked this conversation as resolved.
Show resolved Hide resolved
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
Loading