From 80c52675bd6e0a2d39454e76d96fa7b412931f70 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 15:14:35 +0800 Subject: [PATCH 01/13] feat: add utility batch test and zero delay impl --- parachain/Cargo.lock | 1 + .../pallets/parachain-staking/Cargo.toml | 2 + .../src/delegation_requests.rs | 2 +- .../pallets/parachain-staking/src/lib.rs | 6 + .../parachain-staking/src/mock_zero_delay.rs | 537 ++++++++++++++++++ .../parachain-staking/src/tests_zero_delay.rs | 141 +++++ parachain/runtime/litentry/src/lib.rs | 6 +- parachain/runtime/paseo/src/lib.rs | 6 +- 8 files changed, 694 insertions(+), 7 deletions(-) create mode 100644 parachain/pallets/parachain-staking/src/mock_zero_delay.rs create mode 100644 parachain/pallets/parachain-staking/src/tests_zero_delay.rs diff --git a/parachain/Cargo.lock b/parachain/Cargo.lock index ec83f64fe5..2bd3adeeaf 100644 --- a/parachain/Cargo.lock +++ b/parachain/Cargo.lock @@ -8559,6 +8559,7 @@ dependencies = [ "pallet-authorship", "pallet-balances", "pallet-session", + "pallet-utility", "parity-scale-codec", "scale-info", "serde", diff --git a/parachain/pallets/parachain-staking/Cargo.toml b/parachain/pallets/parachain-staking/Cargo.toml index 849eb168d5..1ddcb30c07 100644 --- a/parachain/pallets/parachain-staking/Cargo.toml +++ b/parachain/pallets/parachain-staking/Cargo.toml @@ -35,6 +35,7 @@ substrate-fixed = { workspace = true } similar-asserts = { workspace = true } sp-core = { workspace = true, features = ["std"] } sp-io = { workspace = true, features = ["std"] } +pallet-utility = { workspace = true, features = ["std"] } [features] default = ["std"] @@ -49,6 +50,7 @@ std = [ "pallet-balances/std", "pallet-session/std", "parity-scale-codec/std", + "pallet-utility/std", "scale-info/std", "serde/std", "sp-core/std", diff --git a/parachain/pallets/parachain-staking/src/delegation_requests.rs b/parachain/pallets/parachain-staking/src/delegation_requests.rs index f03868b477..415fe278ee 100644 --- a/parachain/pallets/parachain-staking/src/delegation_requests.rs +++ b/parachain/pallets/parachain-staking/src/delegation_requests.rs @@ -144,7 +144,7 @@ impl Pallet { ensure!(decrease_amount <= max_subtracted_amount, >::DelegatorBondBelowMin); let now = >::get().current; - let when = now.saturating_add(T::RevokeDelegationDelay::get()); + let when = now.saturating_add(T::DelegationBondLessDelay::get()); scheduled_requests.push(ScheduledRequest { delegator: delegator.clone(), action: DelegationAction::Decrease(decrease_amount), diff --git a/parachain/pallets/parachain-staking/src/lib.rs b/parachain/pallets/parachain-staking/src/lib.rs index 3e3f0cbe07..4cce06162b 100644 --- a/parachain/pallets/parachain-staking/src/lib.rs +++ b/parachain/pallets/parachain-staking/src/lib.rs @@ -75,6 +75,12 @@ pub mod set; #[cfg(test)] mod tests; +// Dedicated test for unbond delay = 0 +#[cfg(test)] +mod mock_zero_delay; +#[cfg(test)] +mod tests_zero_delay; + pub use inflation::{InflationInfo, Range}; pub use weights::WeightInfo; diff --git a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs new file mode 100644 index 0000000000..657bfc29a9 --- /dev/null +++ b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs @@ -0,0 +1,537 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry 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. +// +// Litentry 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. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +//! Inspired by: +//! - Moonbeam `pallet_parachain_staking` + +use crate as pallet_parachain_staking; +use crate::{pallet, AwardedPts, Config, InflationInfo, Points, Range}; +use frame_support::{ + construct_runtime, derive_impl, parameter_types, + traits::{OnFinalize, OnInitialize}, +}; +use sp_runtime::{BuildStorage, Perbill, Percent}; + +pub type AccountId = u64; +pub type Balance = u128; + +// Configure a mock runtime to test the pallet. +construct_runtime!( + pub enum Test + { + System: frame_system, + Balances: pallet_balances, + ParachainStaking: pallet_parachain_staking, + Utility: pallet_utility, + } +); + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for Test { + type Block = frame_system::mocking::MockBlock; + type AccountData = pallet_balances::AccountData; +} + +parameter_types! { + pub const ExistentialDeposit: Balance = 1; +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] +impl pallet_balances::Config for Test { + type Balance = Balance; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; +} + +impl pallet_utility::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + +parameter_types! { + pub const MinBlocksPerRound: u32 = 3; + pub const DefaultBlocksPerRound: u32 = 5; + pub const LeaveCandidatesDelay: u32 = 0; + pub const CandidateBondLessDelay: u32 = 0; + pub const LeaveDelegatorsDelay: u32 = 0; + pub const RevokeDelegationDelay: u32 = 0; + pub const DelegationBondLessDelay: u32 = 0; + pub const RewardPaymentDelay: u32 = 2; + pub const MinSelectedCandidates: u32 = 5; + pub const MaxTopDelegationsPerCandidate: u32 = 4; + pub const MaxBottomDelegationsPerCandidate: u32 = 4; + pub const MaxDelegationsPerDelegator: u32 = 4; + pub const DefaultCollatorCommission: Perbill = Perbill::from_percent(20); + pub const DefaultParachainBondReservePercent: Percent = Percent::from_percent(30); + pub const MinCollatorStk: u128 = 10; + pub const MinDelegatorStk: u128 = 5; + pub const MinDelegation: u128 = 3; +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; + type DefaultBlocksPerRound = DefaultBlocksPerRound; + type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; + type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; + type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type DefaultCollatorCommission = DefaultCollatorCommission; + type DefaultParachainBondReservePercent = DefaultParachainBondReservePercent; + type MinCollatorStk = MinCollatorStk; + type MinCandidateStk = MinCollatorStk; + type MinDelegatorStk = MinDelegatorStk; + type MinDelegation = MinDelegation; + type OnCollatorPayout = (); + type OnNewRound = (); + type WeightInfo = (); + type IssuanceAdapter = (); + type OnAllDelegationRemoved = (); +} + +impl pallet_parachain_staking::OnAllDelegationRemoved for () { + fn on_all_delegation_removed( + _delegator: &::AccountId, + ) -> Result<(), &str> { + Ok(()) + } +} + +pub(crate) struct ExtBuilder { + // endowed accounts with balances + balances: Vec<(AccountId, Balance)>, + // [collator, amount] + collators: Vec<(AccountId, Balance)>, + // [delegator, collator, delegation_amount] + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + // inflation config + inflation: InflationInfo, +} + +impl Default for ExtBuilder { + fn default() -> ExtBuilder { + ExtBuilder { + balances: vec![], + delegations: vec![], + collators: vec![], + inflation: InflationInfo { + expect: Range { min: 700, ideal: 700, max: 700 }, + // not used + annual: Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50), + }, + // unrealistically high parameterization, only for testing + round: Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }, + }, + } + } +} + +impl ExtBuilder { + pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub(crate) fn with_candidates(mut self, collators: Vec<(AccountId, Balance)>) -> Self { + self.collators = collators; + self + } + + pub(crate) fn with_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance)>, + ) -> Self { + self.delegations = + delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); + self + } + + pub(crate) fn with_auto_compounding_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + ) -> Self { + self.delegations = delegations; + self + } + + #[allow(dead_code)] + pub(crate) fn with_inflation(mut self, inflation: InflationInfo) -> Self { + self.inflation = inflation; + self + } + + pub(crate) fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { balances: self.balances } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + pallet_parachain_staking::GenesisConfig:: { + candidates: self.collators, + delegations: self.delegations, + inflation_config: self.inflation, + } + .assimilate_storage(&mut t) + .expect("Parachain Staking's storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } +} + +/// Rolls forward one block. Returns the new block number. +pub(crate) fn roll_one_block() -> u64 { + ParachainStaking::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + ParachainStaking::on_initialize(System::block_number()); + System::block_number() +} + +/// Rolls to the desired block. Returns the number of blocks played. +pub(crate) fn roll_to(n: u64) -> u64 { + let mut num_blocks = 0; + let mut block = System::block_number(); + while block < n { + block = roll_one_block(); + num_blocks += 1; + } + num_blocks +} + +/// Rolls block-by-block to the beginning of the specified round. +/// This will complete the block in which the round change occurs. +/// Returns the number of blocks played. +pub(crate) fn roll_to_round_begin(round: u64) -> u64 { + let block = (round - 1) * DefaultBlocksPerRound::get() as u64; + roll_to(block) +} + +/// Rolls block-by-block to the end of the specified round. +/// The block following will be the one in which the specified round change occurs. +pub(crate) fn roll_to_round_end(round: u64) -> u64 { + let block = round * DefaultBlocksPerRound::get() as u64 - 1; + roll_to(block) +} + +pub(crate) fn last_event() -> RuntimeEvent { + System::events().pop().expect("Event expected").event +} + +pub(crate) fn events() -> Vec> { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map( + |e| if let RuntimeEvent::ParachainStaking(inner) = e { Some(inner) } else { None }, + ) + .collect::>() +} + +/// Assert input equal to the last event emitted +#[macro_export] +macro_rules! assert_last_event { + ($event:expr) => { + match &$event { + e => assert_eq!(*e, $crate::mock::last_event()), + } + }; +} + +/// Compares the system events with passed in events +/// Prints highlighted diff iff assert_eq fails +#[macro_export] +macro_rules! assert_eq_events { + ($events:expr) => { + match &$events { + e => similar_asserts::assert_eq!(*e, $crate::mock::events()), + } + }; +} + +/// Compares the last N system events with passed in events, where N is the length of events passed +/// in. +/// +/// Prints highlighted diff iff assert_eq fails. +/// The last events from frame_system will be taken in order to match the number passed to this +/// macro. If there are insufficient events from frame_system, they will still be compared; the +/// output may or may not be helpful. +/// +/// Examples: +/// If frame_system has events [A, B, C, D, E] and events [C, D, E] are passed in, the result would +/// be a successful match ([C, D, E] == [C, D, E]). +/// +/// If frame_system has events [A, B, C, D] and events [B, C] are passed in, the result would be an +/// error and a hopefully-useful diff will be printed between [C, D] and [B, C]. +/// +/// Note that events are filtered to only match parachain-staking (see events()). +#[macro_export] +macro_rules! assert_eq_last_events { + ($events:expr $(,)?) => { + assert_tail_eq!($events, $crate::mock::events()); + }; + ($events:expr, $($arg:tt)*) => { + assert_tail_eq!($events, $crate::mock::events(), $($arg)*); + }; +} + +/// Assert that one array is equal to the tail of the other. A more generic and testable version of +/// assert_eq_last_events. +#[macro_export] +macro_rules! assert_tail_eq { + ($tail:expr, $arr:expr $(,)?) => { + if $tail.len() != 0 { + // 0-length always passes + + if $tail.len() > $arr.len() { + similar_asserts::assert_eq!($tail, $arr); // will fail + } + + let len_diff = $arr.len() - $tail.len(); + similar_asserts::assert_eq!($tail, $arr[len_diff..]); + } + }; + ($tail:expr, $arr:expr, $($arg:tt)*) => { + if $tail.len() != 0 { + // 0-length always passes + + if $tail.len() > $arr.len() { + similar_asserts::assert_eq!($tail, $arr, $($arg)*); // will fail + } + + let len_diff = $arr.len() - $tail.len(); + similar_asserts::assert_eq!($tail, $arr[len_diff..], $($arg)*); + } + }; +} + +/// Panics if an event is not found in the system log of events +#[macro_export] +macro_rules! assert_event_emitted { + ($event:expr) => { + match &$event { + e => { + assert!( + $crate::mock::events().iter().find(|x| *x == e).is_some(), + "Event {:?} was not found in events: \n {:?}", + e, + $crate::mock::events() + ); + }, + } + }; +} + +/// Panics if an event is found in the system log of events +#[macro_export] +macro_rules! assert_event_not_emitted { + ($event:expr) => { + match &$event { + e => { + assert!( + $crate::mock::events().iter().find(|x| *x == e).is_none(), + "Event {:?} was found in events: \n {:?}", + e, + $crate::mock::events() + ); + }, + } + }; +} + +// Same storage changes as EventHandler::note_author impl +pub(crate) fn set_author(round: u32, acc: u64, pts: u32) { + >::mutate(round, |p| *p += pts); + >::mutate(round, acc, |p| *p += pts); +} + +#[test] +fn geneses() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 1100), + (4, 1100), + (5, 1100), + (6, 1100), + (7, 100), + (8, 9), + (9, 4), + ]) + .with_candidates(vec![(1, 500), (2, 200)]) + .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + // collators + assert_eq!(Balances::reserved_balance(&1), 500); + assert_eq!(Balances::free_balance(&1), 500); + assert!(ParachainStaking::is_candidate(&1)); + assert_eq!(Balances::reserved_balance(&2), 200); + assert_eq!(Balances::free_balance(&2), 100); + assert!(ParachainStaking::is_candidate(&2)); + // delegators + for x in 3..7 { + assert!(ParachainStaking::is_delegator(&x)); + assert_eq!(Balances::free_balance(&x), 1000); + assert_eq!(Balances::reserved_balance(&x), 100); + } + // uninvolved + for x in 7..10 { + assert!(!ParachainStaking::is_delegator(&x)); + } + assert_eq!(Balances::free_balance(&7), 100); + assert_eq!(Balances::reserved_balance(&7), 0); + assert_eq!(Balances::free_balance(&8), 9); + assert_eq!(Balances::reserved_balance(&8), 0); + assert_eq!(Balances::free_balance(&9), 4); + assert_eq!(Balances::reserved_balance(&9), 0); + }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + // collators + for x in 1..5 { + assert!(ParachainStaking::is_candidate(&x)); + assert_eq!(Balances::free_balance(&x), 80); + assert_eq!(Balances::reserved_balance(&x), 20); + } + assert!(ParachainStaking::is_candidate(&5)); + assert_eq!(Balances::free_balance(&5), 90); + assert_eq!(Balances::reserved_balance(&5), 10); + // delegators + for x in 6..11 { + assert!(ParachainStaking::is_delegator(&x)); + assert_eq!(Balances::free_balance(&x), 90); + assert_eq!(Balances::reserved_balance(&x), 10); + } + }); +} + +#[test] +fn roll_to_round_begin_works() { + ExtBuilder::default().build().execute_with(|| { + // these tests assume blocks-per-round of 5, as established by DefaultBlocksPerRound + assert_eq!(System::block_number(), 1); // we start on block 1 + + let num_blocks = roll_to_round_begin(1); + assert_eq!(System::block_number(), 1); // no-op, we're already on this round + assert_eq!(num_blocks, 0); + + let num_blocks = roll_to_round_begin(2); + assert_eq!(System::block_number(), 5); + assert_eq!(num_blocks, 4); + + let num_blocks = roll_to_round_begin(3); + assert_eq!(System::block_number(), 10); + assert_eq!(num_blocks, 5); + }); +} + +#[test] +fn roll_to_round_end_works() { + ExtBuilder::default().build().execute_with(|| { + // these tests assume blocks-per-round of 5, as established by DefaultBlocksPerRound + assert_eq!(System::block_number(), 1); // we start on block 1 + + let num_blocks = roll_to_round_end(1); + assert_eq!(System::block_number(), 4); + assert_eq!(num_blocks, 3); + + let num_blocks = roll_to_round_end(2); + assert_eq!(System::block_number(), 9); + assert_eq!(num_blocks, 5); + + let num_blocks = roll_to_round_end(3); + assert_eq!(System::block_number(), 14); + assert_eq!(num_blocks, 5); + }); +} + +#[test] +fn assert_tail_eq_works() { + assert_tail_eq!(vec![1, 2], vec![0, 1, 2]); + + assert_tail_eq!(vec![1], vec![1]); + + assert_tail_eq!( + vec![0u32; 0], // 0 length array + vec![0u32; 1] // 1-length array + ); + + assert_tail_eq!(vec![0u32, 0], vec![0u32, 0]); +} + +#[test] +#[should_panic] +fn assert_tail_eq_panics_on_non_equal_tail() { + assert_tail_eq!(vec![2, 2], vec![0, 1, 2]); +} + +#[test] +#[should_panic] +fn assert_tail_eq_panics_on_empty_arr() { + assert_tail_eq!(vec![2, 2], vec![0u32; 0]); +} + +#[test] +#[should_panic] +fn assert_tail_eq_panics_on_longer_tail() { + assert_tail_eq!(vec![1, 2, 3], vec![1, 2]); +} + +#[test] +#[should_panic] +fn assert_tail_eq_panics_on_unequal_elements_same_length_array() { + assert_tail_eq!(vec![1, 2, 3], vec![0, 1, 2]); +} diff --git a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs new file mode 100644 index 0000000000..6d166b9530 --- /dev/null +++ b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs @@ -0,0 +1,141 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry 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. +// +// Litentry 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. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . +use crate::mock_zero_delay::{ExtBuilder, RuntimeCall, RuntimeOrigin, Test, Utility}; +use frame_support::assert_ok; + +use crate::Call as ParachainStakingCall; + +#[test] +fn batch_unstake_and_leave_delegators_works_if_zero_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 130), (2, 110)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + // can execute immediately + assert_ok!(Utility::batch_all( + RuntimeOrigin::signed(2), + vec![ + RuntimeCall::ParachainStaking( + ParachainStakingCall::schedule_leave_delegators {} + ), + RuntimeCall::ParachainStaking(ParachainStakingCall::execute_leave_delegators { + delegator: 2 + }), + ] + )); + }); +} + +#[test] +fn batch_unstake_and_leave_candidates_works_if_zero_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 110)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + // can execute immediately + assert_ok!(Utility::batch_all( + RuntimeOrigin::signed(1), + vec![ + RuntimeCall::ParachainStaking( + ParachainStakingCall::schedule_leave_candidates {} + ), + RuntimeCall::ParachainStaking(ParachainStakingCall::execute_leave_candidates { + candidate: 1 + }), + ] + )); + }); +} + +#[test] +fn batch_unstake_and_delegator_bond_less_works_if_zero_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 130), (2, 110)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + // can execute immediately + assert_ok!(Utility::batch_all( + RuntimeOrigin::signed(2), + vec![ + RuntimeCall::ParachainStaking( + ParachainStakingCall::schedule_delegator_bond_less { + candidate: 1, + less: 1 + } + ), + RuntimeCall::ParachainStaking( + ParachainStakingCall::execute_delegation_request { + delegator: 2, + candidate: 1 + } + ), + ] + )); + }); +} + +#[test] +fn batch_unstake_and_revoke_delegation_works_if_zero_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 130), (2, 110)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + // can execute immediately + assert_ok!(Utility::batch_all( + RuntimeOrigin::signed(2), + vec![ + RuntimeCall::ParachainStaking( + ParachainStakingCall::schedule_revoke_delegation { collator: 1 } + ), + RuntimeCall::ParachainStaking( + ParachainStakingCall::execute_delegation_request { + delegator: 2, + candidate: 1 + } + ), + ] + )); + }); +} + +#[test] +fn batch_unstake_and_candidate_bond_less_works_if_zero_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 110)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // can execute immediately + assert_ok!(Utility::batch_all( + RuntimeOrigin::signed(1), + vec![ + RuntimeCall::ParachainStaking( + ParachainStakingCall::schedule_candidate_bond_less { less: 1 } + ), + RuntimeCall::ParachainStaking( + ParachainStakingCall::execute_candidate_bond_less { candidate: 1 } + ), + ] + )); + }); +} diff --git a/parachain/runtime/litentry/src/lib.rs b/parachain/runtime/litentry/src/lib.rs index 94d830f6bd..54a6690f60 100644 --- a/parachain/runtime/litentry/src/lib.rs +++ b/parachain/runtime/litentry/src/lib.rs @@ -992,11 +992,11 @@ impl pallet_parachain_staking::Config for Runtime { /// Rounds before the candidate bond increase/decrease can be executed type CandidateBondLessDelay = ConstU32<{ prod_or_fast!(8, 1) }>; /// Rounds before the delegator exit can be executed - type LeaveDelegatorsDelay = ConstU32<{ prod_or_fast!(8, 1) }>; + type LeaveDelegatorsDelay = ConstU32<{ prod_or_fast!(0, 0) }>; /// Rounds before the delegator revocation can be executed - type RevokeDelegationDelay = ConstU32<{ prod_or_fast!(8, 1) }>; + type RevokeDelegationDelay = ConstU32<{ prod_or_fast!(0, 0) }>; /// Rounds before the delegator bond increase/decrease can be executed - type DelegationBondLessDelay = ConstU32<{ prod_or_fast!(8, 1) }>; + type DelegationBondLessDelay = ConstU32<{ prod_or_fast!(0, 0) }>; /// Rounds before the reward is paid type RewardPaymentDelay = ConstU32<2>; /// Minimum collators selected per round, default at genesis and minimum forever after diff --git a/parachain/runtime/paseo/src/lib.rs b/parachain/runtime/paseo/src/lib.rs index b476273f2d..3de10a5f47 100644 --- a/parachain/runtime/paseo/src/lib.rs +++ b/parachain/runtime/paseo/src/lib.rs @@ -1038,11 +1038,11 @@ impl pallet_parachain_staking::Config for Runtime { /// Rounds before the candidate bond increase/decrease can be executed type CandidateBondLessDelay = ConstU32<{ prod_or_fast!(8, 1) }>; /// Rounds before the delegator exit can be executed - type LeaveDelegatorsDelay = ConstU32<{ prod_or_fast!(8, 1) }>; + type LeaveDelegatorsDelay = ConstU32<{ prod_or_fast!(0, 0) }>; /// Rounds before the delegator revocation can be executed - type RevokeDelegationDelay = ConstU32<{ prod_or_fast!(8, 1) }>; + type RevokeDelegationDelay = ConstU32<{ prod_or_fast!(0, 0) }>; /// Rounds before the delegator bond increase/decrease can be executed - type DelegationBondLessDelay = ConstU32<{ prod_or_fast!(8, 1) }>; + type DelegationBondLessDelay = ConstU32<{ prod_or_fast!(0, 0) }>; /// Rounds before the reward is paid type RewardPaymentDelay = ConstU32<2>; /// Minimum collators selected per round, default at genesis and minimum forever after From 0b0fe8342cb28a62b6920931106ab7db20ddf0c5 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 15:26:23 +0800 Subject: [PATCH 02/13] chore: fix --- .../parachain-staking/src/mock_zero_delay.rs | 329 +----------------- .../parachain-staking/src/tests_zero_delay.rs | 2 +- 2 files changed, 2 insertions(+), 329 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs index 657bfc29a9..b0258fdd1d 100644 --- a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs @@ -18,10 +18,9 @@ //! - Moonbeam `pallet_parachain_staking` use crate as pallet_parachain_staking; -use crate::{pallet, AwardedPts, Config, InflationInfo, Points, Range}; +use crate::{pallet, Config, InflationInfo, Points, Range}; use frame_support::{ construct_runtime, derive_impl, parameter_types, - traits::{OnFinalize, OnInitialize}, }; use sp_runtime::{BuildStorage, Perbill, Percent}; @@ -209,329 +208,3 @@ impl ExtBuilder { ext } } - -/// Rolls forward one block. Returns the new block number. -pub(crate) fn roll_one_block() -> u64 { - ParachainStaking::on_finalize(System::block_number()); - Balances::on_finalize(System::block_number()); - System::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - System::on_initialize(System::block_number()); - Balances::on_initialize(System::block_number()); - ParachainStaking::on_initialize(System::block_number()); - System::block_number() -} - -/// Rolls to the desired block. Returns the number of blocks played. -pub(crate) fn roll_to(n: u64) -> u64 { - let mut num_blocks = 0; - let mut block = System::block_number(); - while block < n { - block = roll_one_block(); - num_blocks += 1; - } - num_blocks -} - -/// Rolls block-by-block to the beginning of the specified round. -/// This will complete the block in which the round change occurs. -/// Returns the number of blocks played. -pub(crate) fn roll_to_round_begin(round: u64) -> u64 { - let block = (round - 1) * DefaultBlocksPerRound::get() as u64; - roll_to(block) -} - -/// Rolls block-by-block to the end of the specified round. -/// The block following will be the one in which the specified round change occurs. -pub(crate) fn roll_to_round_end(round: u64) -> u64 { - let block = round * DefaultBlocksPerRound::get() as u64 - 1; - roll_to(block) -} - -pub(crate) fn last_event() -> RuntimeEvent { - System::events().pop().expect("Event expected").event -} - -pub(crate) fn events() -> Vec> { - System::events() - .into_iter() - .map(|r| r.event) - .filter_map( - |e| if let RuntimeEvent::ParachainStaking(inner) = e { Some(inner) } else { None }, - ) - .collect::>() -} - -/// Assert input equal to the last event emitted -#[macro_export] -macro_rules! assert_last_event { - ($event:expr) => { - match &$event { - e => assert_eq!(*e, $crate::mock::last_event()), - } - }; -} - -/// Compares the system events with passed in events -/// Prints highlighted diff iff assert_eq fails -#[macro_export] -macro_rules! assert_eq_events { - ($events:expr) => { - match &$events { - e => similar_asserts::assert_eq!(*e, $crate::mock::events()), - } - }; -} - -/// Compares the last N system events with passed in events, where N is the length of events passed -/// in. -/// -/// Prints highlighted diff iff assert_eq fails. -/// The last events from frame_system will be taken in order to match the number passed to this -/// macro. If there are insufficient events from frame_system, they will still be compared; the -/// output may or may not be helpful. -/// -/// Examples: -/// If frame_system has events [A, B, C, D, E] and events [C, D, E] are passed in, the result would -/// be a successful match ([C, D, E] == [C, D, E]). -/// -/// If frame_system has events [A, B, C, D] and events [B, C] are passed in, the result would be an -/// error and a hopefully-useful diff will be printed between [C, D] and [B, C]. -/// -/// Note that events are filtered to only match parachain-staking (see events()). -#[macro_export] -macro_rules! assert_eq_last_events { - ($events:expr $(,)?) => { - assert_tail_eq!($events, $crate::mock::events()); - }; - ($events:expr, $($arg:tt)*) => { - assert_tail_eq!($events, $crate::mock::events(), $($arg)*); - }; -} - -/// Assert that one array is equal to the tail of the other. A more generic and testable version of -/// assert_eq_last_events. -#[macro_export] -macro_rules! assert_tail_eq { - ($tail:expr, $arr:expr $(,)?) => { - if $tail.len() != 0 { - // 0-length always passes - - if $tail.len() > $arr.len() { - similar_asserts::assert_eq!($tail, $arr); // will fail - } - - let len_diff = $arr.len() - $tail.len(); - similar_asserts::assert_eq!($tail, $arr[len_diff..]); - } - }; - ($tail:expr, $arr:expr, $($arg:tt)*) => { - if $tail.len() != 0 { - // 0-length always passes - - if $tail.len() > $arr.len() { - similar_asserts::assert_eq!($tail, $arr, $($arg)*); // will fail - } - - let len_diff = $arr.len() - $tail.len(); - similar_asserts::assert_eq!($tail, $arr[len_diff..], $($arg)*); - } - }; -} - -/// Panics if an event is not found in the system log of events -#[macro_export] -macro_rules! assert_event_emitted { - ($event:expr) => { - match &$event { - e => { - assert!( - $crate::mock::events().iter().find(|x| *x == e).is_some(), - "Event {:?} was not found in events: \n {:?}", - e, - $crate::mock::events() - ); - }, - } - }; -} - -/// Panics if an event is found in the system log of events -#[macro_export] -macro_rules! assert_event_not_emitted { - ($event:expr) => { - match &$event { - e => { - assert!( - $crate::mock::events().iter().find(|x| *x == e).is_none(), - "Event {:?} was found in events: \n {:?}", - e, - $crate::mock::events() - ); - }, - } - }; -} - -// Same storage changes as EventHandler::note_author impl -pub(crate) fn set_author(round: u32, acc: u64, pts: u32) { - >::mutate(round, |p| *p += pts); - >::mutate(round, acc, |p| *p += pts); -} - -#[test] -fn geneses() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 1100), - (4, 1100), - (5, 1100), - (6, 1100), - (7, 100), - (8, 9), - (9, 4), - ]) - .with_candidates(vec![(1, 500), (2, 200)]) - .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - // collators - assert_eq!(Balances::reserved_balance(&1), 500); - assert_eq!(Balances::free_balance(&1), 500); - assert!(ParachainStaking::is_candidate(&1)); - assert_eq!(Balances::reserved_balance(&2), 200); - assert_eq!(Balances::free_balance(&2), 100); - assert!(ParachainStaking::is_candidate(&2)); - // delegators - for x in 3..7 { - assert!(ParachainStaking::is_delegator(&x)); - assert_eq!(Balances::free_balance(&x), 1000); - assert_eq!(Balances::reserved_balance(&x), 100); - } - // uninvolved - for x in 7..10 { - assert!(!ParachainStaking::is_delegator(&x)); - } - assert_eq!(Balances::free_balance(&7), 100); - assert_eq!(Balances::reserved_balance(&7), 0); - assert_eq!(Balances::free_balance(&8), 9); - assert_eq!(Balances::reserved_balance(&8), 0); - assert_eq!(Balances::free_balance(&9), 4); - assert_eq!(Balances::reserved_balance(&9), 0); - }); - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - // collators - for x in 1..5 { - assert!(ParachainStaking::is_candidate(&x)); - assert_eq!(Balances::free_balance(&x), 80); - assert_eq!(Balances::reserved_balance(&x), 20); - } - assert!(ParachainStaking::is_candidate(&5)); - assert_eq!(Balances::free_balance(&5), 90); - assert_eq!(Balances::reserved_balance(&5), 10); - // delegators - for x in 6..11 { - assert!(ParachainStaking::is_delegator(&x)); - assert_eq!(Balances::free_balance(&x), 90); - assert_eq!(Balances::reserved_balance(&x), 10); - } - }); -} - -#[test] -fn roll_to_round_begin_works() { - ExtBuilder::default().build().execute_with(|| { - // these tests assume blocks-per-round of 5, as established by DefaultBlocksPerRound - assert_eq!(System::block_number(), 1); // we start on block 1 - - let num_blocks = roll_to_round_begin(1); - assert_eq!(System::block_number(), 1); // no-op, we're already on this round - assert_eq!(num_blocks, 0); - - let num_blocks = roll_to_round_begin(2); - assert_eq!(System::block_number(), 5); - assert_eq!(num_blocks, 4); - - let num_blocks = roll_to_round_begin(3); - assert_eq!(System::block_number(), 10); - assert_eq!(num_blocks, 5); - }); -} - -#[test] -fn roll_to_round_end_works() { - ExtBuilder::default().build().execute_with(|| { - // these tests assume blocks-per-round of 5, as established by DefaultBlocksPerRound - assert_eq!(System::block_number(), 1); // we start on block 1 - - let num_blocks = roll_to_round_end(1); - assert_eq!(System::block_number(), 4); - assert_eq!(num_blocks, 3); - - let num_blocks = roll_to_round_end(2); - assert_eq!(System::block_number(), 9); - assert_eq!(num_blocks, 5); - - let num_blocks = roll_to_round_end(3); - assert_eq!(System::block_number(), 14); - assert_eq!(num_blocks, 5); - }); -} - -#[test] -fn assert_tail_eq_works() { - assert_tail_eq!(vec![1, 2], vec![0, 1, 2]); - - assert_tail_eq!(vec![1], vec![1]); - - assert_tail_eq!( - vec![0u32; 0], // 0 length array - vec![0u32; 1] // 1-length array - ); - - assert_tail_eq!(vec![0u32, 0], vec![0u32, 0]); -} - -#[test] -#[should_panic] -fn assert_tail_eq_panics_on_non_equal_tail() { - assert_tail_eq!(vec![2, 2], vec![0, 1, 2]); -} - -#[test] -#[should_panic] -fn assert_tail_eq_panics_on_empty_arr() { - assert_tail_eq!(vec![2, 2], vec![0u32; 0]); -} - -#[test] -#[should_panic] -fn assert_tail_eq_panics_on_longer_tail() { - assert_tail_eq!(vec![1, 2, 3], vec![1, 2]); -} - -#[test] -#[should_panic] -fn assert_tail_eq_panics_on_unequal_elements_same_length_array() { - assert_tail_eq!(vec![1, 2, 3], vec![0, 1, 2]); -} diff --git a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs index 6d166b9530..8e1c98fd43 100644 --- a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs @@ -13,7 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::mock_zero_delay::{ExtBuilder, RuntimeCall, RuntimeOrigin, Test, Utility}; +use crate::mock_zero_delay::{ExtBuilder, RuntimeCall, RuntimeOrigin, Utility}; use frame_support::assert_ok; use crate::Call as ParachainStakingCall; From 2be4ed4834997f130efabfe95c01c9dbc392a211 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 15:29:24 +0800 Subject: [PATCH 03/13] chore: fix fmt --- parachain/pallets/parachain-staking/src/mock_zero_delay.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs index b0258fdd1d..91fd630703 100644 --- a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs @@ -19,9 +19,7 @@ use crate as pallet_parachain_staking; use crate::{pallet, Config, InflationInfo, Points, Range}; -use frame_support::{ - construct_runtime, derive_impl, parameter_types, -}; +use frame_support::{construct_runtime, derive_impl, parameter_types}; use sp_runtime::{BuildStorage, Perbill, Percent}; pub type AccountId = u64; From 17a234afe0c0aa4a214c4860b0058c7556092f1c Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 15:48:19 +0800 Subject: [PATCH 04/13] chore: fix clippy --- .../pallets/parachain-staking/src/mock_zero_delay.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs index 91fd630703..395b4a3ccf 100644 --- a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs @@ -18,7 +18,7 @@ //! - Moonbeam `pallet_parachain_staking` use crate as pallet_parachain_staking; -use crate::{pallet, Config, InflationInfo, Points, Range}; +use crate::{Config, InflationInfo, Range}; use frame_support::{construct_runtime, derive_impl, parameter_types}; use sp_runtime::{BuildStorage, Perbill, Percent}; @@ -173,14 +173,6 @@ impl ExtBuilder { self } - pub(crate) fn with_auto_compounding_delegations( - mut self, - delegations: Vec<(AccountId, AccountId, Balance, Percent)>, - ) -> Self { - self.delegations = delegations; - self - } - #[allow(dead_code)] pub(crate) fn with_inflation(mut self, inflation: InflationInfo) -> Self { self.inflation = inflation; From b359a363a1f23fa0c29fb8ee5695c862fb7cab6f Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 17:02:52 +0800 Subject: [PATCH 05/13] feat: make extra conditional judge --- .../pallets/parachain-staking/src/lib.rs | 25 ++++++- .../parachain-staking/src/tests_zero_delay.rs | 72 +++++++------------ 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/lib.rs b/parachain/pallets/parachain-staking/src/lib.rs index 4cce06162b..5b29f0eded 100644 --- a/parachain/pallets/parachain-staking/src/lib.rs +++ b/parachain/pallets/parachain-staking/src/lib.rs @@ -1248,7 +1248,12 @@ pub mod pallet { /// Success forbids future delegation requests until the request is invoked or cancelled. pub fn schedule_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; - Self::delegator_schedule_revoke_all(delegator) + let _ = Self::delegator_schedule_revoke_all(delegator.clone())?; + if T::LeaveDelegatorsDelay::get() == 0u32 { + Self::delegator_execute_scheduled_revoke_all(delegator) + } else { + Ok(().into()) + } } #[pallet::call_index(22)] #[pallet::weight(< T as Config >::WeightInfo::execute_leave_delegators( @@ -1281,7 +1286,12 @@ pub mod pallet { collator: T::AccountId, ) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; - Self::delegation_schedule_revoke(collator, delegator) + let _ = Self::delegation_schedule_revoke(collator.clone(), delegator.clone())?; + if T::RevokeDelegationDelay::get() == 0u32 { + Self::delegation_execute_scheduled_request(collator, delegator) + } else { + Ok(().into()) + } } #[pallet::call_index(25)] @@ -1317,7 +1327,16 @@ pub mod pallet { less: BalanceOf, ) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; - Self::delegation_schedule_bond_decrease(candidate, delegator, less) + let _ = Self::delegation_schedule_bond_decrease( + candidate.clone(), + delegator.clone(), + less, + )?; + if T::DelegationBondLessDelay::get() == 0u32 { + Self::delegation_execute_scheduled_request(collator, delegator) + } else { + Ok(().into()) + } } #[pallet::call_index(27)] diff --git a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs index 8e1c98fd43..f3a3e76cc9 100644 --- a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs @@ -13,8 +13,10 @@ // // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::mock_zero_delay::{ExtBuilder, RuntimeCall, RuntimeOrigin, Utility}; -use frame_support::assert_ok; +use crate::mock_zero_delay::{ + ExtBuilder, ParachainStaking, RuntimeCall, RuntimeOrigin, Test, Utility, +}; +use frame_support::{assert_noop, assert_ok}; use crate::Call as ParachainStakingCall; @@ -26,18 +28,13 @@ fn batch_unstake_and_leave_delegators_works_if_zero_delay() { .with_delegations(vec![(2, 1, 10)]) .build() .execute_with(|| { - // can execute immediately - assert_ok!(Utility::batch_all( - RuntimeOrigin::signed(2), - vec![ - RuntimeCall::ParachainStaking( - ParachainStakingCall::schedule_leave_delegators {} - ), - RuntimeCall::ParachainStaking(ParachainStakingCall::execute_leave_delegators { - delegator: 2 - }), - ] - )); + // Execute immediately + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2)), + Error::::PendingDelegationRequestDNE + ); }); } @@ -71,24 +68,17 @@ fn batch_unstake_and_delegator_bond_less_works_if_zero_delay() { .with_delegations(vec![(2, 1, 10)]) .build() .execute_with(|| { - // can execute immediately - assert_ok!(Utility::batch_all( + // Execute immediately + assert_ok!(ParachainStaking::schedule_delegator_bond_less( RuntimeOrigin::signed(2), - vec![ - RuntimeCall::ParachainStaking( - ParachainStakingCall::schedule_delegator_bond_less { - candidate: 1, - less: 1 - } - ), - RuntimeCall::ParachainStaking( - ParachainStakingCall::execute_delegation_request { - delegator: 2, - candidate: 1 - } - ), - ] + 1, + 1 )); + + assert_noop!( + ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), + Error::::PendingDelegationRequestDNE + ); }); } @@ -100,21 +90,13 @@ fn batch_unstake_and_revoke_delegation_works_if_zero_delay() { .with_delegations(vec![(2, 1, 10)]) .build() .execute_with(|| { - // can execute immediately - assert_ok!(Utility::batch_all( - RuntimeOrigin::signed(2), - vec![ - RuntimeCall::ParachainStaking( - ParachainStakingCall::schedule_revoke_delegation { collator: 1 } - ), - RuntimeCall::ParachainStaking( - ParachainStakingCall::execute_delegation_request { - delegator: 2, - candidate: 1 - } - ), - ] - )); + // Execute immediately + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + + assert_noop!( + ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), + Error::::PendingDelegationRequestDNE + ); }); } From 7df86c9dc0b9769684c10936f5526987acb04de5 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 17:12:39 +0800 Subject: [PATCH 06/13] chore: fix --- parachain/pallets/parachain-staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parachain/pallets/parachain-staking/src/lib.rs b/parachain/pallets/parachain-staking/src/lib.rs index 5b29f0eded..4ed969c481 100644 --- a/parachain/pallets/parachain-staking/src/lib.rs +++ b/parachain/pallets/parachain-staking/src/lib.rs @@ -1333,7 +1333,7 @@ pub mod pallet { less, )?; if T::DelegationBondLessDelay::get() == 0u32 { - Self::delegation_execute_scheduled_request(collator, delegator) + Self::delegation_execute_scheduled_request(candidate, delegator) } else { Ok(().into()) } From 708027eaa00a35083adcbb04727f4e6310eb6883 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 17:22:42 +0800 Subject: [PATCH 07/13] chore: fix --- .../pallets/parachain-staking/src/tests_zero_delay.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs index f3a3e76cc9..7f9408921f 100644 --- a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs @@ -13,8 +13,9 @@ // // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::mock_zero_delay::{ - ExtBuilder, ParachainStaking, RuntimeCall, RuntimeOrigin, Test, Utility, +use crate::{ + mock_zero_delay::{ExtBuilder, ParachainStaking, RuntimeCall, RuntimeOrigin, Test, Utility}, + Error, }; use frame_support::{assert_noop, assert_ok}; @@ -30,9 +31,8 @@ fn batch_unstake_and_leave_delegators_works_if_zero_delay() { .execute_with(|| { // Execute immediately assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2)), + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2), Error::::PendingDelegationRequestDNE ); }); @@ -74,7 +74,6 @@ fn batch_unstake_and_delegator_bond_less_works_if_zero_delay() { 1, 1 )); - assert_noop!( ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), Error::::PendingDelegationRequestDNE @@ -92,7 +91,6 @@ fn batch_unstake_and_revoke_delegation_works_if_zero_delay() { .execute_with(|| { // Execute immediately assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_noop!( ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), Error::::PendingDelegationRequestDNE From 4d36bdc187852cd12f82e35fea3a6da1b0f09e2e Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 17:34:47 +0800 Subject: [PATCH 08/13] chore: fix --- parachain/pallets/parachain-staking/src/tests_zero_delay.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs index 7f9408921f..1eb67792a5 100644 --- a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs @@ -33,7 +33,7 @@ fn batch_unstake_and_leave_delegators_works_if_zero_delay() { assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); assert_noop!( ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2), - Error::::PendingDelegationRequestDNE + Error::::DelegatorDNE ); }); } @@ -93,7 +93,7 @@ fn batch_unstake_and_revoke_delegation_works_if_zero_delay() { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); assert_noop!( ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), - Error::::PendingDelegationRequestDNE + Error::::DelegatorDNE ); }); } From 9dc8d4cafcd40cbe6dfa00207272c618b4321900 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 21:24:31 +0800 Subject: [PATCH 09/13] feat: make candidate conditional logic --- .../src/delegation_requests.rs | 109 ++++++++++++++++++ .../pallets/parachain-staking/src/lib.rs | 103 +++-------------- .../parachain-staking/src/tests_zero_delay.rs | 40 +++---- .../precompile-contract.test.ts | 66 +---------- 4 files changed, 136 insertions(+), 182 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/delegation_requests.rs b/parachain/pallets/parachain-staking/src/delegation_requests.rs index 415fe278ee..939c478dae 100644 --- a/parachain/pallets/parachain-staking/src/delegation_requests.rs +++ b/parachain/pallets/parachain-staking/src/delegation_requests.rs @@ -84,6 +84,115 @@ impl From> for CancelledScheduledRequest { } impl Pallet { + /// Schedules a [CollatorStatus::Leaving] for the candidate + pub(crate) fn candidate_schedule_revoke(collator: T::AccountId) -> DispatchResultWithPostInfo { + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + let (now, when) = state.schedule_leave::()?; + let mut candidates = >::get(); + if candidates.remove(&Bond::from_owner(collator.clone())) { + >::put(candidates); + } + >::insert(&collator, state); + Self::deposit_event(Event::CandidateScheduledExit { + exit_allowed_round: now, + candidate: collator, + scheduled_exit: when, + }); + Ok(().into()) + } + + /// Executes a [CollatorStatus::Leaving] for the candidate + pub(crate) fn candidate_execute_schedule_revoke( + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + let state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + state.can_leave::()?; + let return_stake = |bond: Bond>| -> DispatchResult { + T::Currency::unreserve(&bond.owner, bond.amount); + // remove delegation from delegator state + let mut delegator = DelegatorState::::get(&bond.owner).expect( + "Collator state and delegator state are consistent. + Collator state has a record of this delegation. Therefore, + Delegator state also has a record. qed.", + ); + + if let Some(remaining) = delegator.rm_delegation(&candidate) { + Self::delegation_remove_request_with_state(&candidate, &bond.owner, &mut delegator); + >::remove_auto_compound(&candidate, &bond.owner); + + if remaining.is_zero() { + // we do not remove the scheduled delegation requests from other collators + // since it is assumed that they were removed incrementally before only the + // last delegation was left. + >::remove(&bond.owner); + let _ = T::OnAllDelegationRemoved::on_all_delegation_removed(&bond.owner); + } else { + >::insert(&bond.owner, delegator); + } + } + Ok(()) + }; + // total backing stake is at least the candidate self bond + let mut total_backing = state.bond; + // return all top delegations + let top_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); + for bond in top_delegations.delegations { + return_stake(bond)?; + } + total_backing = total_backing.saturating_add(top_delegations.total); + // return all bottom delegations + let bottom_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); + for bond in bottom_delegations.delegations { + return_stake(bond)?; + } + total_backing = total_backing.saturating_add(bottom_delegations.total); + // return stake to collator + T::Currency::unreserve(&candidate, state.bond); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + let new_total_staked = >::get().saturating_sub(total_backing); + >::put(new_total_staked); + Self::deposit_event(Event::CandidateLeft { + ex_candidate: candidate, + unlocked_amount: total_backing, + new_total_amt_locked: new_total_staked, + }); + let actual_weight = + Some(T::WeightInfo::execute_leave_candidates(state.delegation_count as u32)); + Ok(actual_weight.into()) + } + + /// Schedules a [CandidateBondLessRequest] for the candidate + pub(crate) fn candidate_schedule_bond_decrease( + collator: T::AccountId, + less: BalanceOf, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + let when = state.schedule_bond_less::(less)?; + >::insert(&collator, state); + Self::deposit_event(Event::CandidateBondLessRequested { + candidate: collator, + amount_to_decrease: less, + execute_round: when, + }); + Ok(().into()) + } + + /// Executes a [CandidateBondLessRequest] for the candidate + pub(crate) fn candidate_execute_bond_decrease( + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + state.execute_bond_less::(candidate.clone())?; + >::insert(&candidate, state); + Ok(().into()) + } + /// Schedules a [DelegationAction::Revoke] for the delegator, towards a given collator. pub(crate) fn delegation_schedule_revoke( collator: T::AccountId, diff --git a/parachain/pallets/parachain-staking/src/lib.rs b/parachain/pallets/parachain-staking/src/lib.rs index 4ed969c481..3688f6c590 100644 --- a/parachain/pallets/parachain-staking/src/lib.rs +++ b/parachain/pallets/parachain-staking/src/lib.rs @@ -984,21 +984,13 @@ pub mod pallet { /// removed from the candidate pool to prevent selection as a collator. pub fn schedule_leave_candidates(origin: OriginFor) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - let (now, when) = state.schedule_leave::()?; - let mut candidates = >::get(); - if candidates.remove(&Bond::from_owner(collator.clone())) { - >::put(candidates); + let _ = Self::candidate_schedule_revoke(collator)?; + if T::LeaveCandidatesDelay::get() == 0u32 { + Self::candidate_execute_schedule_revoke(candidate) + } else { + Ok(().into()) } - >::insert(&collator, state); - Self::deposit_event(Event::CandidateScheduledExit { - exit_allowed_round: now, - candidate: collator, - scheduled_exit: when, - }); - Ok(().into()) } - #[pallet::call_index(11)] #[pallet::weight( < T as Config >::WeightInfo::execute_leave_candidates( @@ -1012,70 +1004,7 @@ pub mod pallet { candidate: T::AccountId, ) -> DispatchResultWithPostInfo { ensure_signed(origin)?; - let state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - state.can_leave::()?; - let return_stake = |bond: Bond>| -> DispatchResult { - T::Currency::unreserve(&bond.owner, bond.amount); - // remove delegation from delegator state - let mut delegator = DelegatorState::::get(&bond.owner).expect( - "Collator state and delegator state are consistent. - Collator state has a record of this delegation. Therefore, - Delegator state also has a record. qed.", - ); - - if let Some(remaining) = delegator.rm_delegation(&candidate) { - Self::delegation_remove_request_with_state( - &candidate, - &bond.owner, - &mut delegator, - ); - >::remove_auto_compound(&candidate, &bond.owner); - - if remaining.is_zero() { - // we do not remove the scheduled delegation requests from other collators - // since it is assumed that they were removed incrementally before only the - // last delegation was left. - >::remove(&bond.owner); - let _ = T::OnAllDelegationRemoved::on_all_delegation_removed(&bond.owner); - } else { - >::insert(&bond.owner, delegator); - } - } - Ok(()) - }; - // total backing stake is at least the candidate self bond - let mut total_backing = state.bond; - // return all top delegations - let top_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); - for bond in top_delegations.delegations { - return_stake(bond)?; - } - total_backing = total_backing.saturating_add(top_delegations.total); - // return all bottom delegations - let bottom_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); - for bond in bottom_delegations.delegations { - return_stake(bond)?; - } - total_backing = total_backing.saturating_add(bottom_delegations.total); - // return stake to collator - T::Currency::unreserve(&candidate, state.bond); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - let new_total_staked = >::get().saturating_sub(total_backing); - >::put(new_total_staked); - Self::deposit_event(Event::CandidateLeft { - ex_candidate: candidate, - unlocked_amount: total_backing, - new_total_amt_locked: new_total_staked, - }); - let actual_weight = - Some(T::WeightInfo::execute_leave_candidates(state.delegation_count as u32)); - Ok(actual_weight.into()) + Self::candidate_execute_schedule_revoke(candidate) } #[pallet::call_index(12)] #[pallet::weight(< T as Config >::WeightInfo::cancel_leave_candidates(< CandidatePool < T >>::get().0.len() as u32))] @@ -1157,15 +1086,12 @@ pub mod pallet { less: BalanceOf, ) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - let when = state.schedule_bond_less::(less)?; - >::insert(&collator, state); - Self::deposit_event(Event::CandidateBondLessRequested { - candidate: collator, - amount_to_decrease: less, - execute_round: when, - }); - Ok(().into()) + let _ = Self::candidate_schedule_bond_decrease(collator, less)?; + if T::CandidateBondLessDelay::get() { + Self::candidate_execute_bond_decrease(candidate)? + } else { + Ok(().into()) + } } #[pallet::call_index(17)] #[pallet::weight(< T as Config >::WeightInfo::execute_candidate_bond_less())] @@ -1175,10 +1101,7 @@ pub mod pallet { candidate: T::AccountId, ) -> DispatchResultWithPostInfo { ensure_signed(origin)?; // we may want to reward this if caller != candidate - let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - state.execute_bond_less::(candidate.clone())?; - >::insert(&candidate, state); - Ok(().into()) + Self::candidate_execute_bond_decrease(candidate) } #[pallet::call_index(18)] #[pallet::weight(< T as Config >::WeightInfo::cancel_candidate_bond_less())] diff --git a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs index 1eb67792a5..af17fcd9f0 100644 --- a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs @@ -14,13 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . use crate::{ - mock_zero_delay::{ExtBuilder, ParachainStaking, RuntimeCall, RuntimeOrigin, Test, Utility}, + mock_zero_delay::{ExtBuilder, ParachainStaking, RuntimeCall, RuntimeOrigin, Test}, Error, }; use frame_support::{assert_noop, assert_ok}; -use crate::Call as ParachainStakingCall; - #[test] fn batch_unstake_and_leave_delegators_works_if_zero_delay() { ExtBuilder::default() @@ -45,18 +43,12 @@ fn batch_unstake_and_leave_candidates_works_if_zero_delay() { .with_candidates(vec![(1, 10)]) .build() .execute_with(|| { - // can execute immediately - assert_ok!(Utility::batch_all( - RuntimeOrigin::signed(1), - vec![ - RuntimeCall::ParachainStaking( - ParachainStakingCall::schedule_leave_candidates {} - ), - RuntimeCall::ParachainStaking(ParachainStakingCall::execute_leave_candidates { - candidate: 1 - }), - ] - )); + // Execute immediately + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1))); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1), + Error::::CandidateDNE + ); }); } @@ -105,17 +97,11 @@ fn batch_unstake_and_candidate_bond_less_works_if_zero_delay() { .with_candidates(vec![(1, 20)]) .build() .execute_with(|| { - // can execute immediately - assert_ok!(Utility::batch_all( - RuntimeOrigin::signed(1), - vec![ - RuntimeCall::ParachainStaking( - ParachainStakingCall::schedule_candidate_bond_less { less: 1 } - ), - RuntimeCall::ParachainStaking( - ParachainStakingCall::execute_candidate_bond_less { candidate: 1 } - ), - ] - )); + // Execute immediately + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_noop!( + ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1), + Error::::PendingCandidateRequestNotDueYet + ); }); } diff --git a/parachain/ts-tests/integration-tests/precompile-contract.test.ts b/parachain/ts-tests/integration-tests/precompile-contract.test.ts index 5c6c16ba55..a85bf8b4f1 100644 --- a/parachain/ts-tests/integration-tests/precompile-contract.test.ts +++ b/parachain/ts-tests/integration-tests/precompile-contract.test.ts @@ -293,74 +293,10 @@ describeLitentry('Test Parachain Precompile Contract', ``, (context) => { precompileStakingContractAddress, 'scheduleDelegatorBondLess' ); - expect(await isPendingRequest()).to.be.true; - // cancelDelegationRequest(collator) - const cancelDelegationRequest = precompileStakingContract.interface.encodeFunctionData( - 'cancelDelegationRequest', - [collatorPublicKey] - ); - - expect(await isPendingRequest()).to.be.true; - await executeTransaction(cancelDelegationRequest, precompileStakingContractAddress, 'cancelDelegationRequest'); + // Zero delay impl will make execution immediately expect(await isPendingRequest()).to.be.false; - // only makes sense when parachain is compiled with `fast-runtime` feature, otherwise we'll - // never make it within reasonable time - if (config.parachain_fast_runtime === 'true') { - // testing bond less + execution - await executeTransaction( - scheduleDelegatorBondLess, - precompileStakingContractAddress, - 'scheduleDelegatorBondLess again to test execution' - ); - expect(await isPendingRequest()).to.be.true; - - // executeDelegationRequest(delegator, collator); - const executeDelegationRequest = precompileStakingContract.interface.encodeFunctionData( - 'executeDelegationRequest', - [evmAccountRaw.publicKey, collatorPublicKey] - ); - await executeTransaction( - executeDelegationRequest, - precompileStakingContractAddress, - 'executeDelegationRequest' - ); - const { data: balanceAfterBondLess } = await context.api.query.system.account(evmAccountRaw.mappedAddress); - expect(balanceAfterBondLess.reserved.toBigInt()).to.eq( - balanceAfterBondMore.reserved.toBigInt() - toBigInt(5) - ); - - // testing revoke delegation + execute - // scheduleRevokeDelegation(collator); - const scheduleRevokeDelegation = precompileStakingContract.interface.encodeFunctionData( - 'scheduleRevokeDelegation', - [collatorPublicKey] - ); - await executeTransaction( - scheduleRevokeDelegation, - precompileStakingContractAddress, - 'scheduleRevokeDelegation' - ); - - await executeTransaction( - executeDelegationRequest, - precompileStakingContractAddress, - 'executeDelegationRequest' - ); - const { data: balanceAfterRevoke } = await context.api.query.system.account(evmAccountRaw.mappedAddress); - expect(balanceAfterRevoke.reserved.toBigInt()).to.eq(toBigInt(0)); - - // delegate(collator, amount); - const delegate = precompileStakingContract.interface.encodeFunctionData('delegate', [ - collatorPublicKey, - ethers.utils.parseUnits('57', 18).toString(), - ]); - await executeTransaction(delegate, precompileStakingContractAddress, 'delegate'); - const { data: balanceAfterDelegate } = await context.api.query.system.account(evmAccountRaw.mappedAddress); - expect(balanceAfterDelegate.reserved.toBigInt()).to.eq(toBigInt(57)); - } - console.timeEnd('Test precompile staking contract'); }); From fe7805d399822234180d3b454f72cfeb0d576fe6 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 21:38:01 +0800 Subject: [PATCH 10/13] chore: fix --- .../parachain-staking/src/delegation_requests.rs | 10 ++++++---- parachain/pallets/parachain-staking/src/lib.rs | 10 +++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/delegation_requests.rs b/parachain/pallets/parachain-staking/src/delegation_requests.rs index 939c478dae..6a675631cc 100644 --- a/parachain/pallets/parachain-staking/src/delegation_requests.rs +++ b/parachain/pallets/parachain-staking/src/delegation_requests.rs @@ -22,21 +22,23 @@ use crate::{ pallet::{ - BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, - Event, Pallet, Round, RoundIndex, Total, + AutoCompoundingDelegations, BalanceOf, BottomDelegations, CandidateInfo, CandidatePool, + Config, DelegationScheduledRequests, DelegatorState, Error, Event, Pallet, Round, + RoundIndex, TopDelegations, Total, }, weights::WeightInfo, - AutoCompoundDelegations, Delegator, OnAllDelegationRemoved, + AutoCompoundDelegations, Bond, Delegator, OnAllDelegationRemoved, }; use frame_support::{ dispatch::DispatchResultWithPostInfo, ensure, + pallet_prelude::DispatchResult, traits::{Get, ReservableCurrency}, }; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_core::RuntimeDebug; -use sp_runtime::traits::Saturating; +use sp_runtime::traits::{Saturating, Zero}; use sp_std::{vec, vec::Vec}; /// An action that can be performed upon a delegation diff --git a/parachain/pallets/parachain-staking/src/lib.rs b/parachain/pallets/parachain-staking/src/lib.rs index 3688f6c590..c8c49d3bcc 100644 --- a/parachain/pallets/parachain-staking/src/lib.rs +++ b/parachain/pallets/parachain-staking/src/lib.rs @@ -984,9 +984,9 @@ pub mod pallet { /// removed from the candidate pool to prevent selection as a collator. pub fn schedule_leave_candidates(origin: OriginFor) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; - let _ = Self::candidate_schedule_revoke(collator)?; + let _ = Self::candidate_schedule_revoke(collator.clone())?; if T::LeaveCandidatesDelay::get() == 0u32 { - Self::candidate_execute_schedule_revoke(candidate) + Self::candidate_execute_schedule_revoke(collator) } else { Ok(().into()) } @@ -1086,9 +1086,9 @@ pub mod pallet { less: BalanceOf, ) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; - let _ = Self::candidate_schedule_bond_decrease(collator, less)?; - if T::CandidateBondLessDelay::get() { - Self::candidate_execute_bond_decrease(candidate)? + let _ = Self::candidate_schedule_bond_decrease(collator.clone(), less)?; + if T::CandidateBondLessDelay::get() == 0u32 { + Self::candidate_execute_bond_decrease(collator) } else { Ok(().into()) } From 30a7c617938d86252d885b4ea1a1646c72f943f3 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Thu, 9 Jan 2025 21:50:25 +0800 Subject: [PATCH 11/13] chore: fix --- parachain/pallets/parachain-staking/src/tests_zero_delay.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs index af17fcd9f0..09478a748f 100644 --- a/parachain/pallets/parachain-staking/src/tests_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/tests_zero_delay.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . use crate::{ - mock_zero_delay::{ExtBuilder, ParachainStaking, RuntimeCall, RuntimeOrigin, Test}, + mock_zero_delay::{ExtBuilder, ParachainStaking, RuntimeOrigin, Test}, Error, }; use frame_support::{assert_noop, assert_ok}; @@ -101,7 +101,7 @@ fn batch_unstake_and_candidate_bond_less_works_if_zero_delay() { assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 1)); assert_noop!( ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1), - Error::::PendingCandidateRequestNotDueYet + Error::::PendingCandidateRequestsDNE ); }); } From ee45c237f8a7f38555fba0d93881ba3e498f3cba Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Sat, 11 Jan 2025 09:49:14 +0800 Subject: [PATCH 12/13] chore: remove utility --- parachain/Cargo.lock | 1 - parachain/pallets/parachain-staking/Cargo.toml | 2 -- 2 files changed, 3 deletions(-) diff --git a/parachain/Cargo.lock b/parachain/Cargo.lock index 2bd3adeeaf..ec83f64fe5 100644 --- a/parachain/Cargo.lock +++ b/parachain/Cargo.lock @@ -8559,7 +8559,6 @@ dependencies = [ "pallet-authorship", "pallet-balances", "pallet-session", - "pallet-utility", "parity-scale-codec", "scale-info", "serde", diff --git a/parachain/pallets/parachain-staking/Cargo.toml b/parachain/pallets/parachain-staking/Cargo.toml index 1ddcb30c07..849eb168d5 100644 --- a/parachain/pallets/parachain-staking/Cargo.toml +++ b/parachain/pallets/parachain-staking/Cargo.toml @@ -35,7 +35,6 @@ substrate-fixed = { workspace = true } similar-asserts = { workspace = true } sp-core = { workspace = true, features = ["std"] } sp-io = { workspace = true, features = ["std"] } -pallet-utility = { workspace = true, features = ["std"] } [features] default = ["std"] @@ -50,7 +49,6 @@ std = [ "pallet-balances/std", "pallet-session/std", "parity-scale-codec/std", - "pallet-utility/std", "scale-info/std", "serde/std", "sp-core/std", From 8efb26f5bf44581b64da3896535230ff55ccca70 Mon Sep 17 00:00:00 2001 From: Minqi Wang Date: Sat, 11 Jan 2025 14:56:29 +0800 Subject: [PATCH 13/13] chore: fix --- .../pallets/parachain-staking/src/mock_zero_delay.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs index 395b4a3ccf..0b90a01a5c 100644 --- a/parachain/pallets/parachain-staking/src/mock_zero_delay.rs +++ b/parachain/pallets/parachain-staking/src/mock_zero_delay.rs @@ -32,7 +32,6 @@ construct_runtime!( System: frame_system, Balances: pallet_balances, ParachainStaking: pallet_parachain_staking, - Utility: pallet_utility, } ); @@ -53,13 +52,6 @@ impl pallet_balances::Config for Test { type AccountStore = System; } -impl pallet_utility::Config for Test { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type PalletsOrigin = OriginCaller; - type WeightInfo = (); -} - parameter_types! { pub const MinBlocksPerRound: u32 = 3; pub const DefaultBlocksPerRound: u32 = 5;