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

feat: 6 sec. blocks support for pallet_staking #992

Merged
merged 10 commits into from
Feb 5, 2025
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ license = 'Apache-2.0'
name = "hydra-dx-math"
description = "A collection of utilities to make performing liquidity pool calculations more convenient."
repository = 'https://github.com/galacticcouncil/hydradx-math'
version = "8.2.0"
version = "9.0.0"

[dependencies]
primitive-types = { workspace = true }
Expand Down
17 changes: 14 additions & 3 deletions math/src/staking/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::types::Balance;
use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub};
use sp_arithmetic::{traits::Saturating, FixedPointNumber, FixedU128, Perbill, Permill};
use sp_std::num::NonZeroU128;
use sp_std::ops::Div;

type Period = u128;
type Point = u128;
Expand Down Expand Up @@ -53,8 +52,20 @@ pub fn calculate_slashed_points(
/// Parameters:
/// - `period_length`: length of the one period in blocks
/// - `block_number`: block number to calculate period for
pub fn calculate_period_number(period_length: NonZeroU128, block_number: u128) -> Period {
block_number.div(&period_length.get())
/// - `six_sec_block_since`: block number when staking switched to 6 sec. blocks and period
/// `period_length` should be doubled
pub fn calculate_period_number(
period_length: NonZeroU128,
block_number: u128,
six_sec_block_since: NonZeroU128,
) -> Period {
if block_number.le(&Into::<u128>::into(six_sec_block_since)) {
return block_number.saturating_div(period_length.get());
}

Into::<u128>::into(six_sec_block_since)
.saturating_add(block_number)
.saturating_div(period_length.get().saturating_mul(2))
}

/// Function calculates total amount of `Points` user have accumulated until now.
Expand Down
47 changes: 43 additions & 4 deletions math/src/staking/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,24 +85,63 @@ fn calculate_slashed_points_should_work_when_pramas_stake_weight_is_not_zero() {
#[test]
fn calculate_period_number_should_work_when_period_length_is_not_zero() {
assert_eq!(
calculate_period_number(NonZeroU128::try_from(1_u128).unwrap(), 12_341_u128),
calculate_period_number(
NonZeroU128::try_from(1_u128).unwrap(),
12_341_u128,
NonZeroU128::try_from(12_341_u128).unwrap()
),
12_341_u128
);

assert_eq!(
calculate_period_number(NonZeroU128::try_from(1_000_u128).unwrap(), 12_341_u128,),
calculate_period_number(
NonZeroU128::try_from(1_000_u128).unwrap(),
12_341_u128,
NonZeroU128::try_from(12_342_u128).unwrap()
),
12_u128
);

assert_eq!(
calculate_period_number(NonZeroU128::try_from(1_000_u128).unwrap(), 1_u128),
calculate_period_number(
NonZeroU128::try_from(1_000_u128).unwrap(),
1_u128,
NonZeroU128::try_from(1).unwrap()
),
0_u128
);

assert_eq!(
calculate_period_number(NonZeroU128::try_from(82_u128).unwrap(), 12_341_u128),
calculate_period_number(
NonZeroU128::try_from(82_u128).unwrap(),
12_341_u128,
NonZeroU128::try_from(12_341_u128).unwrap()
),
150_u128
);

// 41 blocks per period until block 5_001, 82 blocks per period since
// 5_001 / 41 + (12_341 - 5_001) / 82 = 121.xxx + 89.xxx = 211
assert_eq!(
calculate_period_number(
NonZeroU128::try_from(41_u128).unwrap(),
12_341_u128,
NonZeroU128::try_from(5_001_u128).unwrap()
),
211_u128
);

// 2_617 blocks per period until block 89_789_124, 5_234 blocks per period since
// 89_789_124_u128 / 2_617 + (678_789_789 - 89_789_124) / 5_234 = 34_309.xxx + 112_533.xxx =
// 146_843
assert_eq!(
calculate_period_number(
NonZeroU128::try_from(2_617_u128).unwrap(),
678_789_789_u128,
NonZeroU128::try_from(89_789_124_u128).unwrap()
),
146_843_u128
);
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion pallets/staking/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pallet-staking"
version = "4.0.1"
version = "4.1.0"
authors = ['GalacticCouncil']
edition = "2021"
license = "Apache-2.0"
Expand Down
8 changes: 8 additions & 0 deletions pallets/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ use sp_runtime::{
use sp_runtime::{DispatchError, FixedPointNumber, FixedU128};
use sp_std::num::NonZeroU128;

pub mod migrations;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -239,6 +241,11 @@ pub mod pallet {
OptionQuery,
>;

#[pallet::storage]
/// Block number when we switched to 6 sec. blocks.
#[pallet::getter(fn six_sec_blocks_since)]
pub(super) type SixSecBlocksSince<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
Expand Down Expand Up @@ -918,6 +925,7 @@ impl<T: Config> Pallet<T> {
Some(math::calculate_period_number(
NonZeroU128::try_from(T::PeriodLength::get().saturated_into::<u128>()).ok()?,
block.saturated_into(),
NonZeroU128::try_from(Self::six_sec_blocks_since().saturated_into::<u128>()).ok()?,
))
}

Expand Down
60 changes: 60 additions & 0 deletions pallets/staking/src/migrations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use crate::pallet;
use frame_support::{traits::OnRuntimeUpgrade, weights::Weight};
use sp_core::Get;
use sp_runtime::traits::BlockNumberProvider;

// This migration sets SixSecBlocksSince which is used to correctly calculate the periods in staking
// after the migration to 6s block time
pub struct SetSixSecBlocksSince<T: pallet::Config>(sp_std::marker::PhantomData<T>);
impl<T: pallet::Config> OnRuntimeUpgrade for SetSixSecBlocksSince<T> {
fn on_runtime_upgrade() -> Weight {
let current_block_height = T::BlockNumberProvider::current_block_number();

crate::SixSecBlocksSince::<T>::mutate(|block_height| {
if *block_height == 0u32.into() {
*block_height = current_block_height
}
});

log::info!("SixSecBlocksSince set to: {:?}", current_block_height);
T::DbWeight::get().reads_writes(1, 1)
}
}

#[cfg(all(feature = "try-runtime", test))]
mod test {
use super::*;
use crate::migrations::SetSixSecBlocksSince;
use crate::tests::mock::{set_block_number, ExtBuilder, Staking, Test};
use frame_system::pallet_prelude::BlockNumberFor;

#[test]
fn set_six_blocks_since_executes_when_storage_not_set() {
ExtBuilder::default().build().execute_with(|| {
// Arrange
set_block_number(500);

// Act
SetSixSecBlocksSince::<Test>::on_runtime_upgrade();

// Assert
assert_eq!(Staking::six_sec_blocks_since(), 500u32 as BlockNumberFor<Test>);
});
}

#[test]
fn set_six_blocks_since_does_not_execute_when_storage_is_set() {
ExtBuilder::default().build().execute_with(|| {
// Arrange
set_block_number(500);
SetSixSecBlocksSince::<Test>::on_runtime_upgrade();

// Act
set_block_number(1000);
SetSixSecBlocksSince::<Test>::on_runtime_upgrade();

// Assert
assert_eq!(Staking::six_sec_blocks_since(), 500u32 as BlockNumberFor<Test>);
});
}
}
2 changes: 2 additions & 0 deletions pallets/staking/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ impl ExtBuilder {

let mut r: sp_io::TestExternalities = t.into();
r.execute_with(|| {
pallet_staking::SixSecBlocksSince::<Test>::put(1_000_000_000);

if self.initial_block_number.is_zero() {
set_block_number(1);
} else {
Expand Down
2 changes: 1 addition & 1 deletion runtime/hydradx/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1435,7 +1435,7 @@ impl pallet_bonds::Config for Runtime {
parameter_types! {
pub const StakingPalletId: PalletId = PalletId(*b"staking#");
pub const MinStake: Balance = 1_000 * UNITS;
pub const PeriodLength: BlockNumber = DAYS;
pub const PeriodLength: BlockNumber = 7_200; // 1d based on 12s blocks, pallet accounts for migration to 6s blocks
pub const TimePointsW:Permill = Permill::from_percent(100);
pub const ActionPointsW: Perbill = Perbill::from_percent(20);
pub const TimePointsPerPeriod: u8 = 1;
Expand Down
5 changes: 4 additions & 1 deletion runtime/hydradx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,10 @@ pub type Executive = frame_executive::Executive<
pub mod migrations {
use super::*;

pub type Migrations = (pallet_dca::migrations::MultiplySchedulesPeriodBy2<Runtime>);
pub type Migrations = (
pallet_dca::migrations::MultiplySchedulesPeriodBy2<Runtime>,
pallet_staking::migrations::SetSixSecBlocksSince<Runtime>,
);
}

impl<C> frame_system::offchain::SendTransactionTypes<C> for Runtime
Expand Down
Loading