From 62730ceaa8d5b658b3ab72eb7060809cd198c741 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Thu, 13 Jul 2023 22:53:54 +0800 Subject: [PATCH 01/37] If the balance is insufficient, skip the bond --- Cargo.lock | 2 +- node/Cargo.toml | 2 +- pallets/automation-time/Cargo.toml | 2 +- pallets/automation-time/src/lib.rs | 52 +++++++++++++++++------------- pallets/vesting/Cargo.toml | 2 +- runtime/neumann/Cargo.toml | 2 +- runtime/oak/Cargo.toml | 2 +- runtime/turing/Cargo.toml | 2 +- 8 files changed, 36 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46984795f..c5115db74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6482,7 +6482,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-polkadot-v0.9.38#4ef614d84221f4ae364a4eb411f9fe2f00c8d497" +source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-polkadot-v0.9.38-dev#6c54e503591a3e620649d27ddc88e5958cff4afc" dependencies = [ "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", diff --git a/node/Cargo.toml b/node/Cargo.toml index 9b47c76bc..66619301c 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -127,7 +127,7 @@ polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "r xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", branch = "oak-polkadot-v0.9.38-dev" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/Cargo.toml b/pallets/automation-time/Cargo.toml index f42e239b1..e79b96786 100644 --- a/pallets/automation-time/Cargo.toml +++ b/pallets/automation-time/Cargo.toml @@ -46,7 +46,7 @@ pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-fe xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } ## Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } ## ORML orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 2d91f7a56..c395b3ff8 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -72,7 +72,7 @@ use pallet_xcmp_handler::XcmpTransactor; use primitives::EnsureProxy; use scale_info::TypeInfo; use sp_runtime::{ - traits::{CheckedConversion, Convert, Dispatchable, SaturatedConversion, Saturating}, + traits::{CheckedConversion, Convert, Dispatchable, SaturatedConversion, Saturating, Zero, CheckedSub}, ArithmeticError, DispatchError, Perbill, }; use sp_std::{boxed::Box, vec, vec::Vec}; @@ -264,6 +264,7 @@ pub mod pallet { BadVersion, UnsupportedFeePayment, CannotReanchor, + NoDelegation, } #[pallet::event] @@ -1096,31 +1097,36 @@ pub mod pallet { task: &TaskOf, ) -> (Weight, Option) { // TODO: Handle edge case where user has enough funds to run task but not reschedule + let balance = T::DelegatorActions::get_bond_balance(&delegator, &collator); + if balance.is_err() || balance.unwrap().is_zero() { + return (::WeightInfo::run_auto_compound_delegated_stake_task(), Some(Error::::NoDelegation.into())) + } let reserved_funds = account_minimum .saturating_add(Self::calculate_schedule_fee_amount(&task.action, 1).expect("Can only fail for DynamicDispatch and this is always AutoCompoundDelegatedStake")); - match T::DelegatorActions::delegator_bond_till_minimum( - &delegator, - &collator, - reserved_funds, - ) { - Ok(delegation) => { - Self::deposit_event(Event::SuccesfullyAutoCompoundedDelegatorStake { - task_id, - amount: delegation, - }); - (::WeightInfo::run_auto_compound_delegated_stake_task(), None) - }, - Err(e) => { - Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { - task_id, - error_message: Into::<&str>::into(e).as_bytes().to_vec(), - error: e, - }); - ( - ::WeightInfo::run_auto_compound_delegated_stake_task(), - Some(e.error), - ) + match T::DelegatorActions::get_delegator_stakable_free_balance(&delegator).checked_sub(&reserved_funds) { + Some(delegation) => { + match T::DelegatorActions::delegator_bond_more(&delegator, &collator, delegation) { + Ok(_) => { + Self::deposit_event(Event::SuccesfullyAutoCompoundedDelegatorStake { + task_id, + amount: delegation, + }); + (::WeightInfo::run_auto_compound_delegated_stake_task(), None) + }, + Err(e) => { + Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { + task_id, + error_message: Into::<&str>::into(e).as_bytes().to_vec(), + error: e.into(), + }); + return ( + ::WeightInfo::run_auto_compound_delegated_stake_task(), + Some(e.into()), + ) + }, + } }, + None => (::WeightInfo::run_auto_compound_delegated_stake_task(), None), } } diff --git a/pallets/vesting/Cargo.toml b/pallets/vesting/Cargo.toml index 4788b607a..27aaf0944 100644 --- a/pallets/vesting/Cargo.toml +++ b/pallets/vesting/Cargo.toml @@ -34,7 +34,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", default-featur pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } ## Moonbeam dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } diff --git a/runtime/neumann/Cargo.toml b/runtime/neumann/Cargo.toml index 4b404cf6c..467f62530 100644 --- a/runtime/neumann/Cargo.toml +++ b/runtime/neumann/Cargo.toml @@ -96,7 +96,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/runtime/oak/Cargo.toml b/runtime/oak/Cargo.toml index a2e5744d1..ade18bf4d 100644 --- a/runtime/oak/Cargo.toml +++ b/runtime/oak/Cargo.toml @@ -102,7 +102,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/runtime/turing/Cargo.toml b/runtime/turing/Cargo.toml index fa3bdeb96..50c2b5e50 100644 --- a/runtime/turing/Cargo.toml +++ b/runtime/turing/Cargo.toml @@ -102,7 +102,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } From 390080406111e74ed9e338297713dc01d2879c10 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Thu, 13 Jul 2023 14:55:05 +0000 Subject: [PATCH 02/37] fixup: auto format Rust code --- pallets/automation-time/src/lib.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index c395b3ff8..6de9f79ca 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -72,7 +72,9 @@ use pallet_xcmp_handler::XcmpTransactor; use primitives::EnsureProxy; use scale_info::TypeInfo; use sp_runtime::{ - traits::{CheckedConversion, Convert, Dispatchable, SaturatedConversion, Saturating, Zero, CheckedSub}, + traits::{ + CheckedConversion, CheckedSub, Convert, Dispatchable, SaturatedConversion, Saturating, Zero, + }, ArithmeticError, DispatchError, Perbill, }; use sp_std::{boxed::Box, vec, vec::Vec}; @@ -1099,19 +1101,29 @@ pub mod pallet { // TODO: Handle edge case where user has enough funds to run task but not reschedule let balance = T::DelegatorActions::get_bond_balance(&delegator, &collator); if balance.is_err() || balance.unwrap().is_zero() { - return (::WeightInfo::run_auto_compound_delegated_stake_task(), Some(Error::::NoDelegation.into())) + return ( + ::WeightInfo::run_auto_compound_delegated_stake_task(), + Some(Error::::NoDelegation.into()), + ) } let reserved_funds = account_minimum .saturating_add(Self::calculate_schedule_fee_amount(&task.action, 1).expect("Can only fail for DynamicDispatch and this is always AutoCompoundDelegatedStake")); - match T::DelegatorActions::get_delegator_stakable_free_balance(&delegator).checked_sub(&reserved_funds) { + match T::DelegatorActions::get_delegator_stakable_free_balance(&delegator) + .checked_sub(&reserved_funds) + { Some(delegation) => { - match T::DelegatorActions::delegator_bond_more(&delegator, &collator, delegation) { + match T::DelegatorActions::delegator_bond_more( + &delegator, &collator, delegation, + ) { Ok(_) => { Self::deposit_event(Event::SuccesfullyAutoCompoundedDelegatorStake { task_id, amount: delegation, }); - (::WeightInfo::run_auto_compound_delegated_stake_task(), None) + ( + ::WeightInfo::run_auto_compound_delegated_stake_task(), + None, + ) }, Err(e) => { Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { From a9e94cbf518d22b52d8647a67fe107ed0b980999 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Fri, 14 Jul 2023 23:43:51 +0800 Subject: [PATCH 03/37] Fix tests for auto compound task --- Cargo.lock | 2 +- pallets/automation-time/src/lib.rs | 17 ++++++--- pallets/automation-time/src/mock.rs | 23 ++++++------ pallets/automation-time/src/tests.rs | 56 ++++++++++++++++++++-------- 4 files changed, 64 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c5115db74..4cc2bf53e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6482,7 +6482,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-polkadot-v0.9.38-dev#6c54e503591a3e620649d27ddc88e5958cff4afc" +source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-polkadot-v0.9.38-dev#7f7b8bd04eea5886e22b47fa0c1f41264600357e" dependencies = [ "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 6de9f79ca..85ef8e9b1 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -73,7 +73,7 @@ use primitives::EnsureProxy; use scale_info::TypeInfo; use sp_runtime::{ traits::{ - CheckedConversion, CheckedSub, Convert, Dispatchable, SaturatedConversion, Saturating, Zero, + CheckedConversion, CheckedSub, Convert, Dispatchable, SaturatedConversion, Saturating, }, ArithmeticError, DispatchError, Perbill, }; @@ -266,7 +266,8 @@ pub mod pallet { BadVersion, UnsupportedFeePayment, CannotReanchor, - NoDelegation, + // Delegation Do Not Exist + DelegationDNE, } #[pallet::event] @@ -1099,13 +1100,19 @@ pub mod pallet { task: &TaskOf, ) -> (Weight, Option) { // TODO: Handle edge case where user has enough funds to run task but not reschedule - let balance = T::DelegatorActions::get_bond_balance(&delegator, &collator); - if balance.is_err() || balance.unwrap().is_zero() { + if !T::DelegatorActions::is_delegation_exist(&delegator, &collator) { + let e = sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationDNE); + Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { + task_id, + error_message: Into::<&str>::into(e).as_bytes().to_vec(), + error: e, + }); return ( ::WeightInfo::run_auto_compound_delegated_stake_task(), - Some(Error::::NoDelegation.into()), + Some(e.error), ) } + let reserved_funds = account_minimum .saturating_add(Self::calculate_schedule_fee_amount(&task.action, 1).expect("Can only fail for DynamicDispatch and this is always AutoCompoundDelegatedStake")); match T::DelegatorActions::get_delegator_stakable_free_balance(&delegator) diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 441d8d7b4..52b4aec86 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -27,7 +27,7 @@ use primitives::EnsureProxy; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{AccountIdConversion, BlakeTwo256, CheckedSub, Convert, IdentityLookup}, + traits::{AccountIdConversion, BlakeTwo256, Convert, IdentityLookup}, AccountId32, DispatchError, Perbill, }; use sp_std::marker::PhantomData; @@ -44,6 +44,7 @@ pub const ALICE: [u8; 32] = [1u8; 32]; pub const BOB: [u8; 32] = [2u8; 32]; pub const DELEGATOR_ACCOUNT: [u8; 32] = [3u8; 32]; pub const PROXY_ACCOUNT: [u8; 32] = [4u8; 32]; +pub const COLLATOR_ACCOUNT: [u8; 32] = [5u8; 32]; pub const PARA_ID: u32 = 2000; pub const NATIVE: CurrencyId = 0; @@ -198,24 +199,22 @@ impl< { fn delegator_bond_more( delegator: &T::AccountId, - _: &T::AccountId, + _candidate: &T::AccountId, amount: BalanceOf, ) -> Result { let delegation: u128 = amount.saturated_into(); C::reserve(delegator, delegation.saturated_into())?; Ok(true) } - fn delegator_bond_till_minimum( - delegator: &T::AccountId, - _: &T::AccountId, - account_minimum: BalanceOf, - ) -> Result, DispatchErrorWithPostInfo> { - let delegation = C::free_balance(&delegator) - .checked_sub(&account_minimum) - .ok_or(Error::::InsufficientBalance)?; - C::reserve(delegator, delegation)?; - Ok(delegation) + + fn is_delegation_exist(_delegator: &T::AccountId, candidate: &T::AccountId) -> bool { + *candidate == T::AccountId::decode(&mut COLLATOR_ACCOUNT.as_ref()).unwrap() } + + fn get_delegator_stakable_free_balance(delegator: &T::AccountId) -> BalanceOf { + C::free_balance(delegator) + } + #[cfg(feature = "runtime-benchmarks")] fn setup_delegator(_: &T::AccountId, _: &T::AccountId) -> DispatchResultWithPostInfo { Ok(().into()) diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index eab7f9617..22de1f045 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -364,7 +364,7 @@ fn calculate_auto_compound_action_schedule_fee_amount_works() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let num_of_execution = generate_random_num(1, 20); let delegator = AccountId32::new(ALICE); - let collator = AccountId32::new(BOB); + let collator = AccountId32::new(COLLATOR_ACCOUNT); let action = Action::AutoCompoundDelegatedStake { delegator, collator, @@ -2114,7 +2114,7 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { 3600, Action::AutoCompoundDelegatedStake { delegator: AccountId32::new(ALICE), - collator: AccountId32::new(BOB), + collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, ); @@ -2165,7 +2165,7 @@ fn auto_compound_delegated_stake_reschedules_and_reruns() { frequency, Action::AutoCompoundDelegatedStake { delegator: AccountId32::new(ALICE), - collator: AccountId32::new(BOB), + collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, ); @@ -2214,36 +2214,60 @@ fn auto_compound_delegated_stake_reschedules_and_reruns() { fn auto_compound_delegated_stake_without_minimum_balance() { new_test_ext(START_BLOCK_TIME).execute_with(|| { get_funds(AccountId32::new(ALICE)); - let balance = Balances::free_balance(AccountId32::new(ALICE)); - let account_minimum = balance * 2; + let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + let account_minimum = before_balance * 2; + let frequency = 3_600; - add_task_to_task_queue( + let task_id = add_recurring_task_to_task_queue( ALICE, vec![1], - vec![SCHEDULED_TIME], + SCHEDULED_TIME, + frequency, Action::AutoCompoundDelegatedStake { delegator: AccountId32::new(ALICE), - collator: AccountId32::new(BOB), + collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, ); - LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); System::reset_events(); AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - let new_balance = Balances::free_balance(AccountId32::new(ALICE)); - assert_eq!(new_balance, balance); events() .into_iter() .find(|e| match e { - RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { - .. - }) => true, + RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }) => true, _ => false, }) - .expect("AutoCompound failure event should have been emitted"); + .expect("TaskScheduled event should have been emitted"); + let next_scheduled_time = SCHEDULED_TIME + frequency; + AutomationTime::get_scheduled_tasks(next_scheduled_time) + .expect("Task should have been rescheduled") + .tasks + .into_iter() + .find(|t| *t == (AccountId32::new(ALICE), task_id)) + .expect("Task should have been rescheduled"); + let task = AutomationTime::get_account_task(AccountId32::new(ALICE), task_id) + .expect("Task should not have been removed from task map"); + assert_eq!(task.schedule.known_executions_left(), 1); + assert_eq!(task.execution_times(), vec![next_scheduled_time]); + + Timestamp::set_timestamp(next_scheduled_time * 1_000); + get_funds(AccountId32::new(ALICE)); + System::reset_events(); + AutomationTime::trigger_tasks(Weight::from_ref_time(100_000_000_000)); + + let found_event = events().into_iter().find(|e| match e { + RuntimeEvent::AutomationTime( + crate::Event::SuccesfullyAutoCompoundedDelegatorStake { .. }, + ) => true, + _ => false, + }); + + if found_event.is_some() { + panic!("AutoCompound success eventAutoCompound success event should not be emitted."); + } }) } @@ -2252,7 +2276,7 @@ fn auto_compound_delegated_stake_does_not_reschedule_on_failure() { new_test_ext(START_BLOCK_TIME).execute_with(|| { get_funds(AccountId32::new(ALICE)); let before_balance = Balances::free_balance(AccountId32::new(ALICE)); - let account_minimum = before_balance * 2; + let account_minimum = before_balance / 2; let frequency = 3_600; let task_id = add_recurring_task_to_task_queue( From b0e16ece00e8da861e9e191ce993d9e353c2ed23 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Mon, 17 Jul 2023 18:46:20 +0800 Subject: [PATCH 04/37] Add test cases of 4 scenarios for auto compound task --- pallets/automation-time/src/lib.rs | 22 +++- pallets/automation-time/src/tests.rs | 164 ++++++++++++++++++++------- 2 files changed, 142 insertions(+), 44 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 85ef8e9b1..0284a1163 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -266,8 +266,8 @@ pub mod pallet { BadVersion, UnsupportedFeePayment, CannotReanchor, - // Delegation Do Not Exist - DelegationDNE, + // Delegation Not Found + DelegationNonFound, } #[pallet::event] @@ -313,7 +313,7 @@ pub mod pallet { task_id: TaskId, error: DispatchError, }, - SuccesfullyAutoCompoundedDelegatorStake { + AutoCompoundDelegatorStakeSucceeded { task_id: TaskId, amount: BalanceOf, }, @@ -322,6 +322,10 @@ pub mod pallet { error_message: Vec, error: DispatchErrorWithPostInfo, }, + AutoCompoundDelegatorStakeSkipped { + task_id: TaskId, + message: Vec, + }, /// The task could not be run at the scheduled time. TaskMissed { who: AccountOf, @@ -1101,7 +1105,7 @@ pub mod pallet { ) -> (Weight, Option) { // TODO: Handle edge case where user has enough funds to run task but not reschedule if !T::DelegatorActions::is_delegation_exist(&delegator, &collator) { - let e = sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationDNE); + let e = sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNonFound); Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { task_id, error_message: Into::<&str>::into(e).as_bytes().to_vec(), @@ -1123,7 +1127,7 @@ pub mod pallet { &delegator, &collator, delegation, ) { Ok(_) => { - Self::deposit_event(Event::SuccesfullyAutoCompoundedDelegatorStake { + Self::deposit_event(Event::AutoCompoundDelegatorStakeSucceeded { task_id, amount: delegation, }); @@ -1145,7 +1149,13 @@ pub mod pallet { }, } }, - None => (::WeightInfo::run_auto_compound_delegated_stake_task(), None), + None => { + Self::deposit_event(Event::AutoCompoundDelegatorStakeSkipped { + task_id, + message: "Balance less than minimum".into(), + }); + (::WeightInfo::run_auto_compound_delegated_stake_task(), None) + }, } } diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 22de1f045..d60caa656 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -2131,7 +2131,7 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { .into_iter() .find(|e| match e { RuntimeEvent::AutomationTime( - crate::Event::SuccesfullyAutoCompoundedDelegatorStake { .. }, + crate::Event::AutoCompoundDelegatorStakeSucceeded { .. }, ) => true, _ => false, }) @@ -2140,7 +2140,7 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { let fee = ExecutionWeightFee::get().saturating_mul(execution_weight.ref_time().into()); assert_eq!( delegation_event, - RuntimeEvent::AutomationTime(crate::Event::SuccesfullyAutoCompoundedDelegatorStake { + RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSucceeded { task_id, amount: before_balance .checked_sub(account_minimum.saturating_add(fee)) @@ -2150,11 +2150,20 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { }) } +// Scheduling an auto compound delegated stake task will succeed if the account has a sufficient balance and an delegation with the specificed collator. +// Condition: +// 1. User's wallet balance >= minimum balance + execution fee +// 2. User has a delegation with the specificed collator +// Expected result: +// 1. Current execution will run and emit AutoCompoundDelegatorStakeSucceeded event +// 2. Next execution will be scheduled +// 3. The task will re-run in the next execution time and emit AutoCompoundDelegatorStakeSucceeded event again #[test] -fn auto_compound_delegated_stake_reschedules_and_reruns() { +fn auto_compound_delegated_stake_enough_balance_has_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { get_funds(AccountId32::new(ALICE)); let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + // Minimum balance is half of the user's wallet balance let account_minimum = before_balance / 2; let frequency = 3_600; @@ -2174,13 +2183,30 @@ fn auto_compound_delegated_stake_reschedules_and_reruns() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - events() + let emitted_events = events(); + + // Expected result: + // 1. Current execution will run and emit AutoCompoundDelegatorStakeSucceeded event + emitted_events + .clone() .into_iter() - .find(|e| match e { - RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }) => true, - _ => false, + .find(|e| { + matches!( + e, + RuntimeEvent::AutomationTime( + crate::Event::AutoCompoundDelegatorStakeSucceeded { .. } + ) + ) }) + .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted"); + + // 2. Next execution will be scheduled + emitted_events + .clone() + .into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }))) .expect("TaskScheduled event should have been emitted"); + let next_scheduled_time = SCHEDULED_TIME + frequency; AutomationTime::get_scheduled_tasks(next_scheduled_time) .expect("Task should have been rescheduled") @@ -2193,6 +2219,7 @@ fn auto_compound_delegated_stake_reschedules_and_reruns() { assert_eq!(task.schedule.known_executions_left(), 1); assert_eq!(task.execution_times(), vec![next_scheduled_time]); + // 3. The task will re-run in the next execution time Timestamp::set_timestamp(next_scheduled_time * 1_000); get_funds(AccountId32::new(ALICE)); System::reset_events(); @@ -2200,21 +2227,31 @@ fn auto_compound_delegated_stake_reschedules_and_reruns() { events() .into_iter() - .find(|e| match e { - RuntimeEvent::AutomationTime( - crate::Event::SuccesfullyAutoCompoundedDelegatorStake { .. }, - ) => true, - _ => false, + .find(|e| { + matches!( + e, + RuntimeEvent::AutomationTime( + crate::Event::AutoCompoundDelegatorStakeSucceeded { .. } + ) + ) }) - .expect("AutoCompound success event should have been emitted"); + .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted again!"); }) } +// Scheduling an auto compound delegated stake task will succeed if the account has not enough balance and a delegation with the specificed collator. +// Condition: +// 1. User's wallet balance < minimum balance + execution fee +// 2. User has a delegation with the specificed collator +// Expected result: +// 1. The current execution will be skipped, triggering the emission of an AutoCompoundDelegatorStakeSkipped event, message: Balance less than minimum +// 2. Next execution will be scheduled #[test] -fn auto_compound_delegated_stake_without_minimum_balance() { +fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { get_funds(AccountId32::new(ALICE)); let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + // Minimum balance is twice of the user's wallet balance let account_minimum = before_balance * 2; let frequency = 3_600; @@ -2234,13 +2271,19 @@ fn auto_compound_delegated_stake_without_minimum_balance() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - events() + let emitted_events = events(); + + // Expected result: + // 1. The current execution will be skipped, triggering the emission of an AutoCompoundDelegatorStakeSkipped event, message: Balance less than minimum + emitted_events.clone().into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSkipped { message, .. }) if *message == "Balance less than minimum".as_bytes().to_vec())).expect("AutoCompoundDelegatorStakeSkipped event should have been emitted"); + + // 2. Next execution will be scheduled + emitted_events .into_iter() - .find(|e| match e { - RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }) => true, - _ => false, - }) + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }))) .expect("TaskScheduled event should have been emitted"); + let next_scheduled_time = SCHEDULED_TIME + frequency; AutomationTime::get_scheduled_tasks(next_scheduled_time) .expect("Task should have been rescheduled") @@ -2252,31 +2295,72 @@ fn auto_compound_delegated_stake_without_minimum_balance() { .expect("Task should not have been removed from task map"); assert_eq!(task.schedule.known_executions_left(), 1); assert_eq!(task.execution_times(), vec![next_scheduled_time]); + }) +} - Timestamp::set_timestamp(next_scheduled_time * 1_000); +// Scheduling an auto compound delegated stake task will failed if the account has a sufficient balance and no delegation with the specificed collator. +// Condition: +// 1. User's wallet balance >= minimum balance + execution fee +// 2. User has no delegation with the specificed collator +// Expected result: +// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNonFound +// 2. Next execution will not be scheduled +#[test] +fn auto_compound_delegated_stake_enough_balance_no_delegation() { + new_test_ext(START_BLOCK_TIME).execute_with(|| { get_funds(AccountId32::new(ALICE)); + let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + // Minimum balance is half of the user's wallet balance + let account_minimum = before_balance / 2; + let frequency = 3_600; + + let task_id = add_recurring_task_to_task_queue( + ALICE, + vec![1], + SCHEDULED_TIME, + frequency, + Action::AutoCompoundDelegatedStake { + delegator: AccountId32::new(ALICE), + collator: AccountId32::new(BOB), + account_minimum, + }, + ); + System::reset_events(); - AutomationTime::trigger_tasks(Weight::from_ref_time(100_000_000_000)); - let found_event = events().into_iter().find(|e| match e { - RuntimeEvent::AutomationTime( - crate::Event::SuccesfullyAutoCompoundedDelegatorStake { .. }, - ) => true, - _ => false, - }); + AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - if found_event.is_some() { - panic!("AutoCompound success eventAutoCompound success event should not be emitted."); - } + // Expected result: + // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNonFound + events() + .into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { error, .. }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNonFound))) + .expect("AutoCompound failure event should have been emitted"); + + // 2. Next execution will not be scheduled + assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) + .filter(|scheduled| { + scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id)) + }) + .is_none()); + assert!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id).is_none()); }) } +// Scheduling an auto compound delegated stake task will failed if the account has not enough balance and no delegation with the specificed collator. +// Condition: +// 1. User's wallet balance < minimum balance + execution fee +// 2. User has no delegation with the specificed collator +// Expected result: +// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNonFound +// 2. Next execution will not be scheduled #[test] -fn auto_compound_delegated_stake_does_not_reschedule_on_failure() { +fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { get_funds(AccountId32::new(ALICE)); let before_balance = Balances::free_balance(AccountId32::new(ALICE)); - let account_minimum = before_balance / 2; + // Minimum balance is twice of the user's wallet balance + let account_minimum = before_balance * 2; let frequency = 3_600; let task_id = add_recurring_task_to_task_queue( @@ -2291,20 +2375,24 @@ fn auto_compound_delegated_stake_does_not_reschedule_on_failure() { }, ); - LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); System::reset_events(); AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + // Expected result: + // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNonFound events() .into_iter() - .find(|e| match e { - RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { - .. - }) => true, - _ => false, + .find(|e| { + matches!(e, + RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { + error, + .. + }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNonFound)) }) .expect("AutoCompound failure event should have been emitted"); + + // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) .filter(|scheduled| { scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id)) From 380328fd853a5edb2486ba65dcbc523c92563bc1 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Tue, 18 Jul 2023 15:23:31 +0800 Subject: [PATCH 05/37] Fix DelegationNotFound typo --- pallets/automation-time/src/lib.rs | 8 +++++--- pallets/automation-time/src/tests.rs | 16 ++++++++-------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 0284a1163..eeb6779b7 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -81,6 +81,8 @@ use sp_std::{boxed::Box, vec, vec::Vec}; pub use weights::WeightInfo; use xcm::{latest::prelude::*, VersionedMultiLocation}; +pub const ERROR_MESSAGE_BALANCE_LOW: &str = "Balance less than minimum"; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -267,7 +269,7 @@ pub mod pallet { UnsupportedFeePayment, CannotReanchor, // Delegation Not Found - DelegationNonFound, + DelegationNotFound, } #[pallet::event] @@ -1105,7 +1107,7 @@ pub mod pallet { ) -> (Weight, Option) { // TODO: Handle edge case where user has enough funds to run task but not reschedule if !T::DelegatorActions::is_delegation_exist(&delegator, &collator) { - let e = sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNonFound); + let e = sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound); Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { task_id, error_message: Into::<&str>::into(e).as_bytes().to_vec(), @@ -1152,7 +1154,7 @@ pub mod pallet { None => { Self::deposit_event(Event::AutoCompoundDelegatorStakeSkipped { task_id, - message: "Balance less than minimum".into(), + message: ERROR_MESSAGE_BALANCE_LOW.into(), }); (::WeightInfo::run_auto_compound_delegated_stake_task(), None) }, diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index d60caa656..dcdfae18b 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -18,7 +18,7 @@ use crate::{ mock::*, AccountTasks, Action, ActionOf, AssetPayment, Config, Error, InstructionSequence, LastTimeSlot, MissedTaskV2Of, ScheduleParam, ScheduledTasksOf, TaskHashInput, TaskOf, - TaskQueueV2, WeightInfo, + TaskQueueV2, WeightInfo, ERROR_MESSAGE_BALANCE_LOW, }; use codec::Encode; use frame_support::{ @@ -2276,7 +2276,7 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { // Expected result: // 1. The current execution will be skipped, triggering the emission of an AutoCompoundDelegatorStakeSkipped event, message: Balance less than minimum emitted_events.clone().into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSkipped { message, .. }) if *message == "Balance less than minimum".as_bytes().to_vec())).expect("AutoCompoundDelegatorStakeSkipped event should have been emitted"); + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSkipped { message, .. }) if *message == ERROR_MESSAGE_BALANCE_LOW.as_bytes().to_vec())).expect("AutoCompoundDelegatorStakeSkipped event should have been emitted"); // 2. Next execution will be scheduled emitted_events @@ -2303,7 +2303,7 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { // 1. User's wallet balance >= minimum balance + execution fee // 2. User has no delegation with the specificed collator // Expected result: -// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNonFound +// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound // 2. Next execution will not be scheduled #[test] fn auto_compound_delegated_stake_enough_balance_no_delegation() { @@ -2331,10 +2331,10 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); // Expected result: - // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNonFound + // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound events() .into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { error, .. }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNonFound))) + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { error, .. }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound))) .expect("AutoCompound failure event should have been emitted"); // 2. Next execution will not be scheduled @@ -2352,7 +2352,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { // 1. User's wallet balance < minimum balance + execution fee // 2. User has no delegation with the specificed collator // Expected result: -// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNonFound +// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound // 2. Next execution will not be scheduled #[test] fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { @@ -2380,7 +2380,7 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); // Expected result: - // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNonFound + // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound events() .into_iter() .find(|e| { @@ -2388,7 +2388,7 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { error, .. - }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNonFound)) + }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound)) }) .expect("AutoCompound failure event should have been emitted"); From 32fd90dda3f7c21d7ecc037c7fd501d02b7b8a72 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Tue, 18 Jul 2023 20:05:51 +0800 Subject: [PATCH 06/37] Change the branch of pallet-parachain-staking library to oak-staging --- Cargo.lock | 2 +- node/Cargo.toml | 2 +- pallets/automation-time/Cargo.toml | 2 +- pallets/vesting/Cargo.toml | 2 +- runtime/neumann/Cargo.toml | 2 +- runtime/oak/Cargo.toml | 2 +- runtime/turing/Cargo.toml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4cc2bf53e..e66ce2b3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6482,7 +6482,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-polkadot-v0.9.38-dev#7f7b8bd04eea5886e22b47fa0c1f41264600357e" +source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-staging#f9541fe1a0a3005947c5bc87ecc3d272f7741b1e" dependencies = [ "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", diff --git a/node/Cargo.toml b/node/Cargo.toml index 66619301c..92fda25c7 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -127,7 +127,7 @@ polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "r xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", branch = "oak-polkadot-v0.9.38-dev" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", branch = "oak-staging" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/Cargo.toml b/pallets/automation-time/Cargo.toml index e79b96786..466a08770 100644 --- a/pallets/automation-time/Cargo.toml +++ b/pallets/automation-time/Cargo.toml @@ -46,7 +46,7 @@ pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-fe xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } ## Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } ## ORML orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/vesting/Cargo.toml b/pallets/vesting/Cargo.toml index 27aaf0944..1b7b1f7e5 100644 --- a/pallets/vesting/Cargo.toml +++ b/pallets/vesting/Cargo.toml @@ -34,7 +34,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", default-featur pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } ## Moonbeam dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } diff --git a/runtime/neumann/Cargo.toml b/runtime/neumann/Cargo.toml index 467f62530..7e6f710ba 100644 --- a/runtime/neumann/Cargo.toml +++ b/runtime/neumann/Cargo.toml @@ -96,7 +96,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/runtime/oak/Cargo.toml b/runtime/oak/Cargo.toml index ade18bf4d..dd26f96fe 100644 --- a/runtime/oak/Cargo.toml +++ b/runtime/oak/Cargo.toml @@ -102,7 +102,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/runtime/turing/Cargo.toml b/runtime/turing/Cargo.toml index 50c2b5e50..367c702c3 100644 --- a/runtime/turing/Cargo.toml +++ b/runtime/turing/Cargo.toml @@ -102,7 +102,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38-dev" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } From f8d061a6655b13dd27c03fbf98a52b572e99839f Mon Sep 17 00:00:00 2001 From: imstar15 Date: Wed, 19 Jul 2023 17:29:10 +0800 Subject: [PATCH 07/37] In the AutoCompoundDelegatorStakeFailed event, the error_message will include details about both the delegator and collator. --- Cargo.lock | 1 + pallets/automation-time/Cargo.toml | 3 +++ pallets/automation-time/src/lib.rs | 16 ++++++++++++++-- pallets/automation-time/src/tests.rs | 19 ++++++++++++------- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e66ce2b3c..42e0777b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5938,6 +5938,7 @@ dependencies = [ "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", "frame-system 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", + "hex", "log", "orml-currencies", "orml-tokens", diff --git a/pallets/automation-time/Cargo.toml b/pallets/automation-time/Cargo.toml index 466a08770..3d23a7d33 100644 --- a/pallets/automation-time/Cargo.toml +++ b/pallets/automation-time/Cargo.toml @@ -20,6 +20,9 @@ scale-info = { version = "2.1", default-features = false, features = [ "derive", ] } log = { version = "0.4.17", default-features = false } +hex = { version = "0.4.3", default-features = false, features = [ + "alloc", +] } # Polkadot polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index eeb6779b7..ca5a1f1d9 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -64,13 +64,14 @@ use frame_support::{ weights::constants::WEIGHT_REF_TIME_PER_SECOND, }; use frame_system::pallet_prelude::*; +use hex; use orml_traits::{FixedConversionRateProvider, MultiCurrency}; use pallet_parachain_staking::DelegatorActions; use pallet_timestamp::{self as timestamp}; pub use pallet_xcmp_handler::InstructionSequence; use pallet_xcmp_handler::XcmpTransactor; use primitives::EnsureProxy; -use scale_info::TypeInfo; +use scale_info::{prelude::format, TypeInfo}; use sp_runtime::{ traits::{ CheckedConversion, CheckedSub, Convert, Dispatchable, SaturatedConversion, Saturating, @@ -81,6 +82,12 @@ use sp_std::{boxed::Box, vec, vec::Vec}; pub use weights::WeightInfo; use xcm::{latest::prelude::*, VersionedMultiLocation}; +#[macro_export] +macro_rules! ERROR_MESSAGE_DELEGATION_FORMAT { + () => { + "delegator: {:?}, collator: {:?}" + }; +} pub const ERROR_MESSAGE_BALANCE_LOW: &str = "Balance less than minimum"; #[frame_support::pallet] @@ -1108,9 +1115,14 @@ pub mod pallet { // TODO: Handle edge case where user has enough funds to run task but not reschedule if !T::DelegatorActions::is_delegation_exist(&delegator, &collator) { let e = sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound); + let error_message = format!( + ERROR_MESSAGE_DELEGATION_FORMAT!(), + hex::encode(Encode::encode(&delegator)), + hex::encode(Encode::encode(&collator)) + ); Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { task_id, - error_message: Into::<&str>::into(e).as_bytes().to_vec(), + error_message: error_message.into(), error: e, }); return ( diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index dcdfae18b..66156936e 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -18,7 +18,7 @@ use crate::{ mock::*, AccountTasks, Action, ActionOf, AssetPayment, Config, Error, InstructionSequence, LastTimeSlot, MissedTaskV2Of, ScheduleParam, ScheduledTasksOf, TaskHashInput, TaskOf, - TaskQueueV2, WeightInfo, ERROR_MESSAGE_BALANCE_LOW, + TaskQueueV2, WeightInfo, ERROR_MESSAGE_BALANCE_LOW, ERROR_MESSAGE_DELEGATION_FORMAT, }; use codec::Encode; use frame_support::{ @@ -28,6 +28,7 @@ use frame_support::{ weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, }; use frame_system::{self, RawOrigin}; +use hex; use rand::Rng; use sp_core::Get; use sp_runtime::{ @@ -2357,7 +2358,9 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { #[test] fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - get_funds(AccountId32::new(ALICE)); + let delegator = AccountId32::new(ALICE); + let collator = AccountId32::new(BOB); + get_funds(delegator.clone()); let before_balance = Balances::free_balance(AccountId32::new(ALICE)); // Minimum balance is twice of the user's wallet balance let account_minimum = before_balance * 2; @@ -2369,8 +2372,8 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { SCHEDULED_TIME, frequency, Action::AutoCompoundDelegatedStake { - delegator: AccountId32::new(ALICE), - collator: AccountId32::new(BOB), + delegator: delegator.clone(), + collator: collator.clone(), account_minimum, }, ); @@ -2381,24 +2384,26 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { // Expected result: // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound + let failed_error_message = format!(ERROR_MESSAGE_DELEGATION_FORMAT!(), hex::encode(&delegator), hex::encode(&collator)); events() .into_iter() .find(|e| { matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { + error_message, error, .. - }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound)) + }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound) && *error_message == failed_error_message.as_bytes().to_vec()) }) .expect("AutoCompound failure event should have been emitted"); // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) .filter(|scheduled| { - scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id)) + scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id)) }) .is_none()); - assert!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id).is_none()); + assert!(AutomationTime::get_account_task(delegator.clone(), task_id).is_none()); }) } From e74fc9fd7fe7b810d267834fda23c7494a6ea0a8 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Mon, 24 Jul 2023 23:27:35 +0800 Subject: [PATCH 08/37] Add non_interrupt_errors to Task attributes --- pallets/automation-time/Cargo.toml | 2 +- pallets/automation-time/src/benchmarking.rs | 8 +- pallets/automation-time/src/lib.rs | 151 ++++++++++++------ .../src/migrations/update_xcmp_task.rs | 1 + pallets/automation-time/src/tests.rs | 3 + pallets/automation-time/src/types.rs | 44 ++++- 6 files changed, 149 insertions(+), 60 deletions(-) diff --git a/pallets/automation-time/Cargo.toml b/pallets/automation-time/Cargo.toml index 3d23a7d33..6ff71f011 100644 --- a/pallets/automation-time/Cargo.toml +++ b/pallets/automation-time/Cargo.toml @@ -36,6 +36,7 @@ cumulus-primitives-core = { git = 'https://github.com/paritytech/cumulus', defau ## Substrate Primitive Dependencies sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } ## Substrate FRAME Dependencies frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.38" } @@ -65,7 +66,6 @@ primitives = { path = "../../primitives", default-features = false } rand = { version = "0.7.3" } serde = { version = "1.0.144" } sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } pallet-xcm = { git = 'https://github.com/paritytech/polkadot', default-features = false, branch = "release-v0.9.38" } diff --git a/pallets/automation-time/src/benchmarking.rs b/pallets/automation-time/src/benchmarking.rs index 46e04fb55..c9fd926cc 100644 --- a/pallets/automation-time/src/benchmarking.rs +++ b/pallets/automation-time/src/benchmarking.rs @@ -353,7 +353,7 @@ benchmarks! { for i in 0..v { let provided_id: Vec = vec![i.saturated_into::()]; - let task = TaskOf::::create_event_task::(caller.clone(), provided_id.clone(), vec![time.into()], vec![4, 5, 6]).unwrap(); + let task = TaskOf::::create_event_task::(caller.clone(), provided_id.clone(), vec![time.into()], vec![4, 5, 6], vec![]).unwrap(); let task_id = AutomationTime::::schedule_task(&task, provided_id).unwrap(); let missed_task = MissedTaskV2Of::::new(caller.clone(), task_id, time.into()); >::insert(caller.clone(), task_id, task); @@ -394,7 +394,7 @@ benchmarks! { for i in 0..v { let provided_id: Vec = vec![i.saturated_into::()]; - let task = TaskOf::::create_event_task::(caller.clone(), provided_id.clone(), vec![execution_time], vec![65, 65.saturating_add(i as u8)]).unwrap(); + let task = TaskOf::::create_event_task::(caller.clone(), provided_id.clone(), vec![execution_time], vec![65, 65.saturating_add(i as u8)], vec![]).unwrap(); let task_id = AutomationTime::::schedule_task(&task, provided_id).unwrap(); >::insert(caller.clone(), task_id, task); task_ids.push((caller.clone(), task_id)) @@ -442,7 +442,7 @@ benchmarks! { for j in 0..1 { let time = time.saturating_add(3600); let provided_id: Vec = vec![i.saturated_into::(), j.saturated_into::()]; - let task = TaskOf::::create_event_task::(caller.clone(), provided_id.clone(), vec![time.into()], vec![4, 5, 6]).unwrap(); + let task = TaskOf::::create_event_task::(caller.clone(), provided_id.clone(), vec![time.into()], vec![4, 5, 6], vec![]).unwrap(); let task_id = AutomationTime::::schedule_task(&task, provided_id).unwrap(); >::insert(caller.clone(), task_id, task); } @@ -458,7 +458,7 @@ benchmarks! { for i in 0..T::MaxTasksPerSlot::get() { provided_id = increment_provided_id(provided_id); - let task = TaskOf::::create_event_task::(caller.clone(), provided_id.clone(), vec![current_time.into()], vec![4, 5, 6]).unwrap(); + let task = TaskOf::::create_event_task::(caller.clone(), provided_id.clone(), vec![current_time.into()], vec![4, 5, 6], vec![]).unwrap(); let task_id = AutomationTime::::schedule_task(&task, provided_id.clone()).unwrap(); >::insert(caller.clone(), task_id, task); } diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 584856dd5..b4c8615d9 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -71,14 +71,14 @@ use pallet_timestamp::{self as timestamp}; pub use pallet_xcmp_handler::InstructionSequence; use pallet_xcmp_handler::XcmpTransactor; use primitives::EnsureProxy; -use scale_info::{prelude::format, TypeInfo}; +use scale_info::{prelude::{format, string::String}, TypeInfo}; use sp_runtime::{ traits::{ CheckedConversion, CheckedSub, Convert, Dispatchable, SaturatedConversion, Saturating, }, ArithmeticError, DispatchError, Perbill, }; -use sp_std::{boxed::Box, vec, vec::Vec}; +use sp_std::{boxed::Box, vec, vec::Vec, collections::btree_map::BTreeMap}; pub use weights::WeightInfo; use xcm::{latest::prelude::*, VersionedMultiLocation}; @@ -374,6 +374,12 @@ pub mod pallet { who: AccountOf, task_id: TaskId, }, + TaskTriggered { + who: AccountOf, + task_id: TaskId, + condition: BTreeMap, + non_interrupt_errors: Vec, + }, } #[pallet::hooks] @@ -449,7 +455,7 @@ pub mod pallet { let schedule = schedule.validated_into::()?; - Self::validate_and_schedule_task(action, who, provided_id, schedule)?; + Self::validate_and_schedule_task(action, who, provided_id, schedule, vec![])?; Ok(().into()) } @@ -515,7 +521,7 @@ pub mod pallet { }; let schedule = schedule.validated_into::()?; - Self::validate_and_schedule_task(action, who, provided_id, schedule)?; + Self::validate_and_schedule_task(action, who, provided_id, schedule, vec![])?; Ok(().into()) } @@ -554,7 +560,8 @@ pub mod pallet { account_minimum, }; let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; - Self::validate_and_schedule_task(action, who, provided_id, schedule)?; + let non_interrupt_errors = vec![String::from("InsufficientBalance")]; + Self::validate_and_schedule_task(action, who, provided_id, schedule, non_interrupt_errors)?; Ok(().into()) } @@ -586,7 +593,7 @@ pub mod pallet { let action = Action::DynamicDispatch { encoded_call }; let schedule = schedule.validated_into::()?; - Self::validate_and_schedule_task(action, who, provided_id, schedule)?; + Self::validate_and_schedule_task(action, who, provided_id, schedule, vec![])?; Ok(().into()) } @@ -915,6 +922,13 @@ pub mod pallet { mut weight_left: Weight, ) -> (Vec>, Weight) { let mut consumed_task_index: usize = 0; + + let time_slot = Self::get_current_time_slot(); + if time_slot.is_err() { + return (account_task_ids, weight_left) + } + let time_slot = time_slot.unwrap(); + for (account_id, task_id) in account_task_ids.iter() { consumed_task_index.saturating_inc(); let action_weight = match AccountTasks::::get(account_id.clone(), task_id) { @@ -926,6 +940,17 @@ pub mod pallet { ::WeightInfo::run_tasks_many_missing(1) }, Some(task) => { + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", time_slot)); + + Self::deposit_event(Event::TaskTriggered { + who: account_id.clone(), + task_id: task_id.clone(), + condition, + non_interrupt_errors: task.non_interrupt_errors.clone(), + }); + let (task_action_weight, dispatch_error) = match task.action.clone() { Action::Notify { message } => Self::run_notify_task(message), Action::NativeTransfer { sender, recipient, amount } => @@ -1401,6 +1426,7 @@ pub mod pallet { owner_id: AccountOf, provided_id: Vec, schedule: Schedule, + non_interrupt_errors: Vec, ) -> DispatchResult { if provided_id.len() == 0 { Err(Error::::EmptyProvidedId)? @@ -1430,7 +1456,7 @@ pub mod pallet { let executions = schedule.known_executions_left(); let task = - TaskOf::::new(owner_id.clone(), provided_id.clone(), schedule, action.clone()); + TaskOf::::new(owner_id.clone(), provided_id.clone(), schedule, action.clone(), non_interrupt_errors); let task_id = T::FeeHandler::pay_checked_fees_for(&owner_id, &action, executions, || { @@ -1453,38 +1479,76 @@ pub mod pallet { mut task: TaskOf, dispatch_error: Option, ) { - if let Some(err) = dispatch_error { - Self::deposit_event(Event::::TaskNotRescheduled { - who: task.owner_id.clone(), - task_id, - error: err, - }); - AccountTasks::::remove(task.owner_id.clone(), task_id); - } else { - let owner_id = task.owner_id.clone(); - let action = task.action.clone(); - match Self::reschedule_existing_task(task_id, &mut task) { - Ok(_) => { - let schedule_as = match action { - Action::XCMP { schedule_as, .. } => schedule_as, - _ => None, - }; - Self::deposit_event(Event::::TaskRescheduled { - who: owner_id, - task_id, - schedule_as, - }); - }, - Err(err) => { - Self::deposit_event(Event::::TaskFailedToReschedule { - who: task.owner_id.clone(), - task_id, - error: err, - }); - AccountTasks::::remove(task.owner_id.clone(), task_id); - }, - }; + + match dispatch_error { + Some(err) if !task.non_interrupt_errors.contains(&String::from(Into::<&str>::into(err))) => { + Self::deposit_event(Event::::TaskNotRescheduled { + who: task.owner_id.clone(), + task_id, + error: err, + }); + AccountTasks::::remove(task.owner_id.clone(), task_id); + }, + _ => { + let owner_id = task.owner_id.clone(); + let action = task.action.clone(); + match Self::reschedule_existing_task(task_id, &mut task) { + Ok(_) => { + let schedule_as = match action { + Action::XCMP { schedule_as, .. } => schedule_as, + _ => None, + }; + Self::deposit_event(Event::::TaskRescheduled { + who: owner_id.clone(), + task_id, + schedule_as, + }); + AccountTasks::::insert(owner_id.clone(), task_id, task.clone()); + }, + Err(err) => { + Self::deposit_event(Event::::TaskFailedToReschedule { + who: task.owner_id.clone(), + task_id, + error: err, + }); + AccountTasks::::remove(task.owner_id.clone(), task_id); + }, + }; + } } + + // if let Some(err) = dispatch_error if task.non_interrupt_errors.contains(&err.as_str()) { + // Self::deposit_event(Event::::TaskNotRescheduled { + // who: task.owner_id.clone(), + // task_id, + // error: err, + // }); + // AccountTasks::::remove(task.owner_id.clone(), task_id); + // } else { + // let owner_id = task.owner_id.clone(); + // let action = task.action.clone(); + // match Self::reschedule_existing_task(task_id, &mut task) { + // Ok(_) => { + // let schedule_as = match action { + // Action::XCMP { schedule_as, .. } => schedule_as, + // _ => None, + // }; + // Self::deposit_event(Event::::TaskRescheduled { + // who: owner_id, + // task_id, + // schedule_as, + // }); + // }, + // Err(err) => { + // Self::deposit_event(Event::::TaskFailedToReschedule { + // who: task.owner_id.clone(), + // task_id, + // error: err, + // }); + // AccountTasks::::remove(task.owner_id.clone(), task_id); + // }, + // }; + // } } fn reschedule_existing_task(task_id: TaskId, task: &mut TaskOf) -> DispatchResult { @@ -1503,17 +1567,6 @@ pub mod pallet { let owner_id = task.owner_id.clone(); AccountTasks::::insert(owner_id.clone(), task_id, task.clone()); - - let schedule_as = match task.action.clone() { - Action::XCMP { schedule_as, .. } => schedule_as.clone(), - _ => None, - }; - - Self::deposit_event(Event::::TaskScheduled { - who: owner_id, - task_id, - schedule_as, - }); }, Schedule::Fixed { .. } => {}, } diff --git a/pallets/automation-time/src/migrations/update_xcmp_task.rs b/pallets/automation-time/src/migrations/update_xcmp_task.rs index d5b1bddac..44cc9d9a7 100644 --- a/pallets/automation-time/src/migrations/update_xcmp_task.rs +++ b/pallets/automation-time/src/migrations/update_xcmp_task.rs @@ -31,6 +31,7 @@ impl From> for TaskOf { provided_id: task.provided_id, schedule: task.schedule, action: task.action.into(), + non_interrupt_errors: vec![], } } } diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 176dae69c..4accfbdf7 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -1095,6 +1095,7 @@ fn schedule_execution_times_removes_dupes() { vec![50], vec![SCHEDULED_TIME, SCHEDULED_TIME + 10800], vec![2, 4], + vec![], ) .unwrap(); @@ -1466,6 +1467,7 @@ fn cancel_task_must_exist() { vec![40], vec![SCHEDULED_TIME], vec![2, 4, 5], + vec![], ) .unwrap(); let task_id = BlakeTwo256::hash_of(&task); @@ -1491,6 +1493,7 @@ fn cancel_task_not_found() { vec![40], vec![SCHEDULED_TIME], vec![2, 4, 5], + vec![], ) .unwrap(); let task_id = BlakeTwo256::hash_of(&task); diff --git a/pallets/automation-time/src/types.rs b/pallets/automation-time/src/types.rs index 9dda6067e..e30f374ca 100644 --- a/pallets/automation-time/src/types.rs +++ b/pallets/automation-time/src/types.rs @@ -2,8 +2,9 @@ use crate::{weights::WeightInfo, Config, Error, InstructionSequence, Pallet}; use frame_support::{dispatch::GetDispatchInfo, pallet_prelude::*, traits::Get}; -use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion}; -use sp_std::prelude::*; +use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion, Printable}; +use sp_std::{prelude::*, collections::btree_map::BTreeMap}; +use scale_info::prelude::{format, string::String}; use pallet_automation_time_rpc_runtime_api::AutomationAction; @@ -213,6 +214,7 @@ pub struct Task { pub provided_id: Vec, pub schedule: Schedule, pub action: Action, + pub non_interrupt_errors: Vec, } impl PartialEq for Task { @@ -232,8 +234,9 @@ impl Task { provided_id: Vec, schedule: Schedule, action: Action, + non_interrupt_errors: Vec, ) -> Self { - Self { owner_id, provided_id, schedule, action } + Self { owner_id, provided_id, schedule, action, non_interrupt_errors } } pub fn create_event_task( @@ -241,12 +244,13 @@ impl Task { provided_id: Vec, execution_times: Vec, message: Vec, + non_interrupt_errors: Vec ) -> Result { let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: message }.into(); let action = Action::DynamicDispatch { encoded_call: call.encode() }; let schedule = Schedule::new_fixed_schedule::(execution_times)?; - Ok(Self::new(owner_id, provided_id, schedule, action)) + Ok(Self::new(owner_id, provided_id, schedule, action, non_interrupt_errors)) } pub fn create_xcmp_task( @@ -260,6 +264,7 @@ impl Task { encoded_call_weight: Weight, overall_weight: Weight, instruction_sequence: InstructionSequence, + non_interrupt_errors: Vec ) -> Result { let destination = MultiLocation::try_from(destination).map_err(|_| Error::::BadVersion)?; @@ -274,7 +279,7 @@ impl Task { instruction_sequence, }; let schedule = Schedule::new_fixed_schedule::(execution_times)?; - Ok(Self::new(owner_id, provided_id, schedule, action)) + Ok(Self::new(owner_id, provided_id, schedule, action, non_interrupt_errors)) } pub fn create_auto_compound_delegated_stake_task( @@ -284,6 +289,7 @@ impl Task { frequency: Seconds, collator_id: AccountId, account_minimum: Balance, + non_interrupt_errors: Vec, ) -> Result { let action = Action::AutoCompoundDelegatedStake { delegator: owner_id.clone(), @@ -291,7 +297,7 @@ impl Task { account_minimum, }; let schedule = Schedule::new_recurring_schedule::(next_execution_time, frequency)?; - Ok(Self::new(owner_id, provided_id, schedule, action)) + Ok(Self::new(owner_id, provided_id, schedule, action, non_interrupt_errors)) } pub fn execution_times(&self) -> Vec { @@ -367,6 +373,29 @@ impl ScheduledTasks { } } +#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct DispatchErrorWithData +where + Data: Eq + PartialEq + Clone + Encode + Decode + Printable, +{ + /// Additional data + pub data: Data, + pub message: Option, + /// The actual `DispatchResult` indicating whether the dispatch was successful. + pub error: DispatchError, +} + +#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)] +pub struct DispatchErrorDataMap(BTreeMap); +impl sp_runtime::traits::Printable for DispatchErrorDataMap { + fn print(&self) { + for (key, value) in self.0.iter() { + sp_io::misc::print_utf8(format!("{:?}: {:?}, ", key, value).as_bytes()); + } + } +} +pub type DispatchErrorWithDataMap = DispatchErrorWithData; + #[cfg(test)] mod tests { use super::*; @@ -389,6 +418,7 @@ mod tests { vec![0], vec![SCHEDULED_TIME], vec![0], + vec![], ) .unwrap(); let task_id = TaskId::::default(); @@ -410,6 +440,7 @@ mod tests { vec![0], vec![SCHEDULED_TIME], vec![0], + vec![], ) .unwrap(); let tasks = (0..MaxTasksPerSlot::get()).fold::>, _>( @@ -444,6 +475,7 @@ mod tests { vec![0], vec![SCHEDULED_TIME], vec![0], + vec![], ) .unwrap(); let task_id = TaskId::::default(); From 414dd654a336f148c30b5b5eb0f57b9e09ffc044 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Mon, 24 Jul 2023 15:27:58 +0000 Subject: [PATCH 09/37] fixup: auto format Rust code --- pallets/automation-time/src/lib.rs | 35 +++++++++++++++++++++------- pallets/automation-time/src/types.rs | 8 +++---- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index b4c8615d9..0a7380856 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -71,14 +71,17 @@ use pallet_timestamp::{self as timestamp}; pub use pallet_xcmp_handler::InstructionSequence; use pallet_xcmp_handler::XcmpTransactor; use primitives::EnsureProxy; -use scale_info::{prelude::{format, string::String}, TypeInfo}; +use scale_info::{ + prelude::{format, string::String}, + TypeInfo, +}; use sp_runtime::{ traits::{ CheckedConversion, CheckedSub, Convert, Dispatchable, SaturatedConversion, Saturating, }, ArithmeticError, DispatchError, Perbill, }; -use sp_std::{boxed::Box, vec, vec::Vec, collections::btree_map::BTreeMap}; +use sp_std::{boxed::Box, collections::btree_map::BTreeMap, vec, vec::Vec}; pub use weights::WeightInfo; use xcm::{latest::prelude::*, VersionedMultiLocation}; @@ -561,7 +564,13 @@ pub mod pallet { }; let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; let non_interrupt_errors = vec![String::from("InsufficientBalance")]; - Self::validate_and_schedule_task(action, who, provided_id, schedule, non_interrupt_errors)?; + Self::validate_and_schedule_task( + action, + who, + provided_id, + schedule, + non_interrupt_errors, + )?; Ok(().into()) } @@ -943,7 +952,7 @@ pub mod pallet { let mut condition: BTreeMap = BTreeMap::new(); condition.insert(String::from("type"), String::from("time")); condition.insert(String::from("timestamp"), format!("{}", time_slot)); - + Self::deposit_event(Event::TaskTriggered { who: account_id.clone(), task_id: task_id.clone(), @@ -1455,8 +1464,13 @@ pub mod pallet { let executions = schedule.known_executions_left(); - let task = - TaskOf::::new(owner_id.clone(), provided_id.clone(), schedule, action.clone(), non_interrupt_errors); + let task = TaskOf::::new( + owner_id.clone(), + provided_id.clone(), + schedule, + action.clone(), + non_interrupt_errors, + ); let task_id = T::FeeHandler::pay_checked_fees_for(&owner_id, &action, executions, || { @@ -1479,9 +1493,12 @@ pub mod pallet { mut task: TaskOf, dispatch_error: Option, ) { - match dispatch_error { - Some(err) if !task.non_interrupt_errors.contains(&String::from(Into::<&str>::into(err))) => { + Some(err) + if !task + .non_interrupt_errors + .contains(&String::from(Into::<&str>::into(err))) => + { Self::deposit_event(Event::::TaskNotRescheduled { who: task.owner_id.clone(), task_id, @@ -1514,7 +1531,7 @@ pub mod pallet { AccountTasks::::remove(task.owner_id.clone(), task_id); }, }; - } + }, } // if let Some(err) = dispatch_error if task.non_interrupt_errors.contains(&err.as_str()) { diff --git a/pallets/automation-time/src/types.rs b/pallets/automation-time/src/types.rs index e30f374ca..32afd7d58 100644 --- a/pallets/automation-time/src/types.rs +++ b/pallets/automation-time/src/types.rs @@ -2,9 +2,9 @@ use crate::{weights::WeightInfo, Config, Error, InstructionSequence, Pallet}; use frame_support::{dispatch::GetDispatchInfo, pallet_prelude::*, traits::Get}; -use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion, Printable}; -use sp_std::{prelude::*, collections::btree_map::BTreeMap}; use scale_info::prelude::{format, string::String}; +use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion, Printable}; +use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use pallet_automation_time_rpc_runtime_api::AutomationAction; @@ -244,7 +244,7 @@ impl Task { provided_id: Vec, execution_times: Vec, message: Vec, - non_interrupt_errors: Vec + non_interrupt_errors: Vec, ) -> Result { let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: message }.into(); @@ -264,7 +264,7 @@ impl Task { encoded_call_weight: Weight, overall_weight: Weight, instruction_sequence: InstructionSequence, - non_interrupt_errors: Vec + non_interrupt_errors: Vec, ) -> Result { let destination = MultiLocation::try_from(destination).map_err(|_| Error::::BadVersion)?; From 8033e825f5fa0f078cee576268c90728768d1744 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Tue, 25 Jul 2023 15:31:13 +0800 Subject: [PATCH 10/37] Add encoded_call attribute to TaskTriggered event --- pallets/automation-time/src/lib.rs | 23 ++++++++++++------- .../src/migrations/update_xcmp_task.rs | 3 ++- pallets/automation-time/src/types.rs | 18 +++++++-------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 0a7380856..5d0262e85 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -381,7 +381,8 @@ pub mod pallet { who: AccountOf, task_id: TaskId, condition: BTreeMap, - non_interrupt_errors: Vec, + encoded_call: Vec, + cancel_upon_errors: Vec, }, } @@ -563,13 +564,12 @@ pub mod pallet { account_minimum, }; let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; - let non_interrupt_errors = vec![String::from("InsufficientBalance")]; Self::validate_and_schedule_task( action, who, provided_id, schedule, - non_interrupt_errors, + vec![], )?; Ok(().into()) } @@ -953,11 +953,18 @@ pub mod pallet { condition.insert(String::from("type"), String::from("time")); condition.insert(String::from("timestamp"), format!("{}", time_slot)); + let encoded_call = match task.action.clone() { + Action::XCMP { encoded_call, .. } => encoded_call, + Action::DynamicDispatch { encoded_call } => encoded_call, + _ => vec![], + }; + Self::deposit_event(Event::TaskTriggered { who: account_id.clone(), task_id: task_id.clone(), condition, - non_interrupt_errors: task.non_interrupt_errors.clone(), + encoded_call, + cancel_upon_errors: task.cancel_upon_errors.clone(), }); let (task_action_weight, dispatch_error) = match task.action.clone() { @@ -1435,7 +1442,7 @@ pub mod pallet { owner_id: AccountOf, provided_id: Vec, schedule: Schedule, - non_interrupt_errors: Vec, + cancel_upon_errors: Vec, ) -> DispatchResult { if provided_id.len() == 0 { Err(Error::::EmptyProvidedId)? @@ -1469,7 +1476,7 @@ pub mod pallet { provided_id.clone(), schedule, action.clone(), - non_interrupt_errors, + cancel_upon_errors, ); let task_id = @@ -1496,7 +1503,7 @@ pub mod pallet { match dispatch_error { Some(err) if !task - .non_interrupt_errors + .cancel_upon_errors .contains(&String::from(Into::<&str>::into(err))) => { Self::deposit_event(Event::::TaskNotRescheduled { @@ -1534,7 +1541,7 @@ pub mod pallet { }, } - // if let Some(err) = dispatch_error if task.non_interrupt_errors.contains(&err.as_str()) { + // if let Some(err) = dispatch_error if task.cancel_upon_errors.contains(&err.as_str()) { // Self::deposit_event(Event::::TaskNotRescheduled { // who: task.owner_id.clone(), // task_id, diff --git a/pallets/automation-time/src/migrations/update_xcmp_task.rs b/pallets/automation-time/src/migrations/update_xcmp_task.rs index 44cc9d9a7..a2ecb64bb 100644 --- a/pallets/automation-time/src/migrations/update_xcmp_task.rs +++ b/pallets/automation-time/src/migrations/update_xcmp_task.rs @@ -10,6 +10,7 @@ use frame_support::{traits::OnRuntimeUpgrade, weights::Weight, Twox64Concat}; use scale_info::TypeInfo; use sp_runtime::traits::Convert; use sp_std::vec::Vec; +use sp_std::vec; use xcm::{latest::prelude::*, VersionedMultiLocation}; const EXECUTION_FEE_AMOUNT: u128 = 3_000_000_000; @@ -31,7 +32,7 @@ impl From> for TaskOf { provided_id: task.provided_id, schedule: task.schedule, action: task.action.into(), - non_interrupt_errors: vec![], + cancel_upon_errors: vec![], } } } diff --git a/pallets/automation-time/src/types.rs b/pallets/automation-time/src/types.rs index 32afd7d58..1a7d599d0 100644 --- a/pallets/automation-time/src/types.rs +++ b/pallets/automation-time/src/types.rs @@ -214,7 +214,7 @@ pub struct Task { pub provided_id: Vec, pub schedule: Schedule, pub action: Action, - pub non_interrupt_errors: Vec, + pub cancel_upon_errors: Vec, } impl PartialEq for Task { @@ -234,9 +234,9 @@ impl Task { provided_id: Vec, schedule: Schedule, action: Action, - non_interrupt_errors: Vec, + cancel_upon_errors: Vec, ) -> Self { - Self { owner_id, provided_id, schedule, action, non_interrupt_errors } + Self { owner_id, provided_id, schedule, action, cancel_upon_errors } } pub fn create_event_task( @@ -244,13 +244,13 @@ impl Task { provided_id: Vec, execution_times: Vec, message: Vec, - non_interrupt_errors: Vec, + cancel_upon_errors: Vec, ) -> Result { let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: message }.into(); let action = Action::DynamicDispatch { encoded_call: call.encode() }; let schedule = Schedule::new_fixed_schedule::(execution_times)?; - Ok(Self::new(owner_id, provided_id, schedule, action, non_interrupt_errors)) + Ok(Self::new(owner_id, provided_id, schedule, action, cancel_upon_errors)) } pub fn create_xcmp_task( @@ -264,7 +264,7 @@ impl Task { encoded_call_weight: Weight, overall_weight: Weight, instruction_sequence: InstructionSequence, - non_interrupt_errors: Vec, + cancel_upon_errors: Vec, ) -> Result { let destination = MultiLocation::try_from(destination).map_err(|_| Error::::BadVersion)?; @@ -279,7 +279,7 @@ impl Task { instruction_sequence, }; let schedule = Schedule::new_fixed_schedule::(execution_times)?; - Ok(Self::new(owner_id, provided_id, schedule, action, non_interrupt_errors)) + Ok(Self::new(owner_id, provided_id, schedule, action, cancel_upon_errors)) } pub fn create_auto_compound_delegated_stake_task( @@ -289,7 +289,7 @@ impl Task { frequency: Seconds, collator_id: AccountId, account_minimum: Balance, - non_interrupt_errors: Vec, + cancel_upon_errors: Vec, ) -> Result { let action = Action::AutoCompoundDelegatedStake { delegator: owner_id.clone(), @@ -297,7 +297,7 @@ impl Task { account_minimum, }; let schedule = Schedule::new_recurring_schedule::(next_execution_time, frequency)?; - Ok(Self::new(owner_id, provided_id, schedule, action, non_interrupt_errors)) + Ok(Self::new(owner_id, provided_id, schedule, action, cancel_upon_errors)) } pub fn execution_times(&self) -> Vec { From 8a65340858a97470f74a5526deb8ce1d547bca23 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Tue, 25 Jul 2023 07:31:31 +0000 Subject: [PATCH 11/37] fixup: auto format Rust code --- pallets/automation-time/src/lib.rs | 8 +------- .../automation-time/src/migrations/update_xcmp_task.rs | 3 +-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 5d0262e85..d19488538 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -564,13 +564,7 @@ pub mod pallet { account_minimum, }; let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; - Self::validate_and_schedule_task( - action, - who, - provided_id, - schedule, - vec![], - )?; + Self::validate_and_schedule_task(action, who, provided_id, schedule, vec![])?; Ok(().into()) } diff --git a/pallets/automation-time/src/migrations/update_xcmp_task.rs b/pallets/automation-time/src/migrations/update_xcmp_task.rs index a2ecb64bb..485070a43 100644 --- a/pallets/automation-time/src/migrations/update_xcmp_task.rs +++ b/pallets/automation-time/src/migrations/update_xcmp_task.rs @@ -9,8 +9,7 @@ use cumulus_primitives_core::ParaId; use frame_support::{traits::OnRuntimeUpgrade, weights::Weight, Twox64Concat}; use scale_info::TypeInfo; use sp_runtime::traits::Convert; -use sp_std::vec::Vec; -use sp_std::vec; +use sp_std::{vec, vec::Vec}; use xcm::{latest::prelude::*, VersionedMultiLocation}; const EXECUTION_FEE_AMOUNT: u128 = 3_000_000_000; From f60ec356f76c1aa851412d8c197ee75bce190897 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Tue, 25 Jul 2023 22:58:45 +0800 Subject: [PATCH 12/37] Remove XcmpTaskSucceeded, AutoCompoundDelegatorStakeSucceeded, AutoCompoundDelegatorStakeSkipped, DynamicDispatchResult event --- Cargo.lock | 2 +- node/Cargo.toml | 2 +- pallets/automation-time/Cargo.toml | 2 +- pallets/automation-time/src/benchmarking.rs | 9 +- pallets/automation-time/src/lib.rs | 150 +++++---- .../src/migrations/update_xcmp_task.rs | 1 + pallets/automation-time/src/mock.rs | 20 +- pallets/automation-time/src/tests.rs | 289 +++++++++--------- pallets/automation-time/src/types.rs | 15 +- pallets/vesting/Cargo.toml | 2 +- runtime/neumann/Cargo.toml | 2 +- runtime/oak/Cargo.toml | 2 +- runtime/turing/Cargo.toml | 2 +- 13 files changed, 241 insertions(+), 257 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42e0777b1..d0957748c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6483,7 +6483,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-staging#f9541fe1a0a3005947c5bc87ecc3d272f7741b1e" +source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-polkadot-v0.9.38#4ef614d84221f4ae364a4eb411f9fe2f00c8d497" dependencies = [ "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", diff --git a/node/Cargo.toml b/node/Cargo.toml index 92fda25c7..9b47c76bc 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -127,7 +127,7 @@ polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "r xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", branch = "oak-staging" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", branch = "oak-polkadot-v0.9.38" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/Cargo.toml b/pallets/automation-time/Cargo.toml index 6ff71f011..6de638485 100644 --- a/pallets/automation-time/Cargo.toml +++ b/pallets/automation-time/Cargo.toml @@ -50,7 +50,7 @@ pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-fe xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } ## Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } ## ORML orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/src/benchmarking.rs b/pallets/automation-time/src/benchmarking.rs index c9fd926cc..c69b7b2c2 100644 --- a/pallets/automation-time/src/benchmarking.rs +++ b/pallets/automation-time/src/benchmarking.rs @@ -55,6 +55,7 @@ fn schedule_notify_tasks(owner: T::AccountId, times: Vec, count: provided_id.clone(), times.clone(), vec![4, 5, 6], + vec![], ) .unwrap(); let task_id = AutomationTime::::schedule_task(&task, provided_id.clone()).unwrap(); @@ -91,6 +92,7 @@ fn schedule_xcmp_tasks(owner: T::AccountId, times: Vec, count: u Weight::from_ref_time(5_000), Weight::from_ref_time(10_000), InstructionSequence::PayThroughSovereignAccount, + vec![], ) .unwrap(); let task_id = AutomationTime::::schedule_task(&task, provided_id.clone()).unwrap(); @@ -123,6 +125,7 @@ fn schedule_auto_compound_delegated_stake_tasks( frequency, collator, account_minimum, + vec![], ) .unwrap(); let task_id = AutomationTime::::schedule_task(&task, provided_id).unwrap(); @@ -323,9 +326,9 @@ benchmarks! { let call: ::Call = frame_system::Call::remark { remark: vec![] }.into(); let encoded_call = call.encode(); }: { AutomationTime::::run_dynamic_dispatch_action(caller.clone(), encoded_call, task_id) } - verify { - assert_last_event::(Event::DynamicDispatchResult{ who: caller, task_id, result: Ok(()) }.into()) - } + // verify { + // assert_last_event::(Event::DynamicDispatchResult{ who: caller, task_id, result: Ok(()) }.into()) + // } run_dynamic_dispatch_action_fail_decode { let caller: T::AccountId = account("caller", 0, SEED); diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index d19488538..a768b34dc 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -53,7 +53,7 @@ use codec::Decode; use core::convert::TryInto; use cumulus_primitives_core::ParaId; use frame_support::{ - dispatch::{DispatchErrorWithPostInfo, GetDispatchInfo, PostDispatchInfo}, + dispatch::{GetDispatchInfo, PostDispatchInfo}, pallet_prelude::*, sp_runtime::traits::Hash, storage::{ @@ -64,7 +64,6 @@ use frame_support::{ weights::constants::WEIGHT_REF_TIME_PER_SECOND, }; use frame_system::pallet_prelude::*; -use hex; use orml_traits::{FixedConversionRateProvider, MultiCurrency}; use pallet_parachain_staking::DelegatorActions; use pallet_timestamp::{self as timestamp}; @@ -77,7 +76,7 @@ use scale_info::{ }; use sp_runtime::{ traits::{ - CheckedConversion, CheckedSub, Convert, Dispatchable, SaturatedConversion, Saturating, + CheckedConversion, Convert, Dispatchable, SaturatedConversion, Saturating, }, ArithmeticError, DispatchError, Perbill, }; @@ -93,6 +92,17 @@ macro_rules! ERROR_MESSAGE_DELEGATION_FORMAT { } pub const ERROR_MESSAGE_BALANCE_LOW: &str = "Balance less than minimum"; +#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)] +pub struct DispatchErrorDataMap(BTreeMap); +impl sp_runtime::traits::Printable for DispatchErrorDataMap { + fn print(&self) { + for (key, value) in self.0.iter() { + sp_io::misc::print_utf8(format!("{:?}: {:?}, ", key, value).as_bytes()); + } + } +} +pub type DispatchErrorWithDataMap = DispatchErrorWithData; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -309,11 +319,6 @@ pub mod pallet { SuccessfullyTransferredFunds { task_id: TaskId, }, - /// Successfully sent XCMP - XcmpTaskSucceeded { - task_id: T::Hash, - destination: MultiLocation, - }, /// Failed to send XCMP XcmpTaskFailed { task_id: T::Hash, @@ -325,18 +330,10 @@ pub mod pallet { task_id: TaskId, error: DispatchError, }, - AutoCompoundDelegatorStakeSucceeded { - task_id: TaskId, - amount: BalanceOf, - }, AutoCompoundDelegatorStakeFailed { + who: AccountOf, task_id: TaskId, - error_message: Vec, - error: DispatchErrorWithPostInfo, - }, - AutoCompoundDelegatorStakeSkipped { - task_id: TaskId, - message: Vec, + error: DispatchErrorWithDataMap, }, /// The task could not be run at the scheduled time. TaskMissed { @@ -344,12 +341,12 @@ pub mod pallet { task_id: TaskId, execution_time: UnixTime, }, - /// The result of the DynamicDispatch action. - DynamicDispatchResult { - who: AccountOf, - task_id: TaskId, - result: DispatchResult, - }, + // /// The result of the DynamicDispatch action. + // DynamicDispatchResult { + // who: AccountOf, + // task_id: TaskId, + // result: DispatchResult, + // }, /// The call for the DynamicDispatch action can no longer be decoded. CallCannotBeDecoded { who: AccountOf, @@ -384,6 +381,11 @@ pub mod pallet { encoded_call: Vec, cancel_upon_errors: Vec, }, + TaskExecutionFailed { + who: AccountOf, + task_id: TaskId, + error: DispatchError, + }, } #[pallet::hooks] @@ -1133,7 +1135,6 @@ pub mod pallet { flow, ) { Ok(()) => { - Self::deposit_event(Event::XcmpTaskSucceeded { task_id, destination }); (::WeightInfo::run_xcmp_task(), None) }, Err(e) => { @@ -1152,62 +1153,50 @@ pub mod pallet { task: &TaskOf, ) -> (Weight, Option) { // TODO: Handle edge case where user has enough funds to run task but not reschedule - if !T::DelegatorActions::is_delegation_exist(&delegator, &collator) { - let e = sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound); - let error_message = format!( - ERROR_MESSAGE_DELEGATION_FORMAT!(), - hex::encode(Encode::encode(&delegator)), - hex::encode(Encode::encode(&collator)) - ); - Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { - task_id, - error_message: error_message.into(), - error: e, - }); + let fee_amount = Self::calculate_schedule_fee_amount(&task.action, 1); + if fee_amount.is_err() { return ( ::WeightInfo::run_auto_compound_delegated_stake_task(), - Some(e.error), - ) + Some(fee_amount.unwrap_err()), + ); } + let fee_amount = fee_amount.unwrap(); - let reserved_funds = account_minimum - .saturating_add(Self::calculate_schedule_fee_amount(&task.action, 1).expect("Can only fail for DynamicDispatch and this is always AutoCompoundDelegatedStake")); - match T::DelegatorActions::get_delegator_stakable_free_balance(&delegator) - .checked_sub(&reserved_funds) - { - Some(delegation) => { - match T::DelegatorActions::delegator_bond_more( - &delegator, &collator, delegation, - ) { - Ok(_) => { - Self::deposit_event(Event::AutoCompoundDelegatorStakeSucceeded { - task_id, - amount: delegation, - }); - ( - ::WeightInfo::run_auto_compound_delegated_stake_task(), - None, - ) - }, - Err(e) => { - Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { - task_id, - error_message: Into::<&str>::into(e).as_bytes().to_vec(), - error: e.into(), - }); - return ( - ::WeightInfo::run_auto_compound_delegated_stake_task(), - Some(e.into()), - ) - }, - } + let reserved_funds = account_minimum.saturating_add(fee_amount); + match T::DelegatorActions::delegator_bond_till_minimum( + &delegator, &collator, reserved_funds, + ) { + Ok(_) => { + ( + ::WeightInfo::run_auto_compound_delegated_stake_task(), + None, + ) }, - None => { - Self::deposit_event(Event::AutoCompoundDelegatorStakeSkipped { + Err(e) => { + // BTreeMap::new() + // let error = DispatchErrorDataMap { + // data: + // } + + let mut data_map: BTreeMap = BTreeMap::new(); + data_map.insert(String::from("delagator"), String::from("68TwNoCpyz1X3ygMi9WtUAaCb8Q6jWAMvAHfAByRZqMFEtJG")); + data_map.insert(String::from("collator"), String::from("67RWv3VtgUxhL9jqu4jQPxJPzoApnbTyHhSdr8ELLwfNjJ5m")); + + let error = DispatchErrorWithDataMap { + data: DispatchErrorDataMap(data_map), + message: Some(String::from(Into::<&str>::into(e))), + error: e.error, + }; + + Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { + who: task.owner_id.clone(), task_id, - message: ERROR_MESSAGE_BALANCE_LOW.into(), + error, }); - (::WeightInfo::run_auto_compound_delegated_stake_task(), None) + return ( + ::WeightInfo::run_auto_compound_delegated_stake_task(), + Some(e.error), + ) }, } } @@ -1237,12 +1226,6 @@ pub mod pallet { (error_and_info.post_info.actual_weight, Err(error_and_info.error)), }; - Self::deposit_event(Event::DynamicDispatchResult { - who: caller, - task_id, - result, - }); - ( maybe_actual_call_weight.unwrap_or(call_weight).saturating_add( ::WeightInfo::run_dynamic_dispatch_action(), @@ -1596,6 +1579,13 @@ pub mod pallet { task: TaskOf, error: Option, ) { + if let Some(err) = error { + Self::deposit_event(Event::::TaskExecutionFailed { + who: task.owner_id.clone(), + task_id, + error: err, + }); + } match task.schedule { Schedule::Fixed { .. } => Self::decrement_task_and_remove_if_complete(task_id, task), diff --git a/pallets/automation-time/src/migrations/update_xcmp_task.rs b/pallets/automation-time/src/migrations/update_xcmp_task.rs index 485070a43..742d150ac 100644 --- a/pallets/automation-time/src/migrations/update_xcmp_task.rs +++ b/pallets/automation-time/src/migrations/update_xcmp_task.rs @@ -219,6 +219,7 @@ mod test { schedule_as, instruction_sequence: InstructionSequence::PayThroughSovereignAccount, }, + cancel_upon_errors: vec![], } ); }) diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 52b4aec86..081975eca 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -27,7 +27,7 @@ use primitives::EnsureProxy; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{AccountIdConversion, BlakeTwo256, Convert, IdentityLookup}, + traits::{AccountIdConversion, BlakeTwo256, Convert, IdentityLookup, CheckedSub}, AccountId32, DispatchError, Perbill, }; use sp_std::marker::PhantomData; @@ -207,12 +207,16 @@ impl< Ok(true) } - fn is_delegation_exist(_delegator: &T::AccountId, candidate: &T::AccountId) -> bool { - *candidate == T::AccountId::decode(&mut COLLATOR_ACCOUNT.as_ref()).unwrap() - } - - fn get_delegator_stakable_free_balance(delegator: &T::AccountId) -> BalanceOf { - C::free_balance(delegator) + fn delegator_bond_till_minimum( + delegator: &T::AccountId, + _candidate: &T::AccountId, + account_minimum: BalanceOf, + ) -> Result, frame_support::dispatch::DispatchErrorWithPostInfo> { + let delegation = C::free_balance(&delegator) + .checked_sub(&account_minimum) + .ok_or(Error::::InsufficientBalance)?; + C::reserve(delegator, delegation)?; + Ok(delegation) } #[cfg(feature = "runtime-benchmarks")] @@ -580,7 +584,7 @@ pub fn create_task( ) -> sp_core::H256 { let task_hash_input = TaskHashInput::new(AccountId32::new(owner), provided_id.clone()); let task_id = BlakeTwo256::hash_of(&task_hash_input); - let task = TaskOf::::new(owner.into(), provided_id, schedule, action); + let task = TaskOf::::new(owner.into(), provided_id, schedule, action, vec![]); AccountTasks::::insert(AccountId::new(owner), task_id, task); task_id } diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 4accfbdf7..8b88f2c18 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -349,11 +349,11 @@ fn schedule_transfer_with_dynamic_dispatch() { to: recipient.clone(), amount: 127, }), - RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - who: account_id.clone(), - task_id, - result: Ok(()), - }), + // RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { + // who: account_id.clone(), + // task_id, + // result: Ok(()), + // }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: account_id, task_id, @@ -520,10 +520,10 @@ fn will_emit_task_completed_event_when_task_failed() { let my_events = events(); // The DynamicDispatchResult event with error should be emitted when task failed. - let event = my_events.clone().into_iter().find(|e| { - matches!(e, RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { result, .. }) if result.is_err()) - }) - .expect("The DynamicDispatchResult event with error should be emitted when task failed"); + // let event = my_events.clone().into_iter().find(|e| { + // matches!(e, RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { result, .. }) if result.is_err()) + // }) + // .expect("The DynamicDispatchResult event with error should be emitted when task failed"); // When a task fails, the TaskCompleted event will still be emitted. let event = my_events.into_iter().find(|e| { @@ -931,6 +931,7 @@ fn schedule_auto_compound_delegated_stake() { 3_600, bob, 1_000_000_000, + vec![], ) .ok() ); @@ -1380,11 +1381,11 @@ fn cancel_works_for_an_executed_task() { sender: owner.clone(), hash: BlakeTwo256::hash(&vec![50]), }), - RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - who: owner.clone(), - task_id: task_id1, - result: Ok(()), - }), + // RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { + // who: owner.clone(), + // task_id: task_id1, + // result: Ok(()), + // }), ] ); match AutomationTime::get_account_task(owner.clone(), task_id1) { @@ -1648,14 +1649,14 @@ mod run_dynamic_dispatch_action { AutomationTime::run_dynamic_dispatch_action(account_id.clone(), encoded_call, task_id); - assert_eq!( - events(), - [RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - who: account_id, - task_id, - result: Err(DispatchError::BadOrigin), - }),] - ); + // assert_eq!( + // events(), + // [RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { + // who: account_id, + // task_id, + // result: Err(DispatchError::BadOrigin), + // }),] + // ); }) } @@ -1669,14 +1670,14 @@ mod run_dynamic_dispatch_action { AutomationTime::run_dynamic_dispatch_action(account_id.clone(), encoded_call, task_id); - assert_eq!( - events(), - [RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - who: account_id, - task_id, - result: Err(DispatchError::from(frame_system::Error::::CallFiltered)), - }),] - ); + // assert_eq!( + // events(), + // [RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { + // who: account_id, + // task_id, + // result: Err(DispatchError::from(frame_system::Error::::CallFiltered)), + // }),] + // ); }) } @@ -1690,14 +1691,14 @@ mod run_dynamic_dispatch_action { AutomationTime::run_dynamic_dispatch_action(account_id.clone(), encoded_call, task_id); - assert_eq!( - events(), - [RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - who: account_id, - task_id, - result: Ok(()), - }),] - ); + // assert_eq!( + // events(), + // [RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { + // who: account_id, + // task_id, + // result: Ok(()), + // }),] + // ); }) } } @@ -1821,11 +1822,11 @@ fn trigger_tasks_handles_missed_slots() { sender: AccountId32::new(ALICE), hash: BlakeTwo256::hash(&vec![50]), }), - RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - who: AccountId32::new(ALICE), - task_id: task_will_be_run_id, - result: Ok(()), - }), + // RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { + // who: AccountId32::new(ALICE), + // task_id: task_will_be_run_id, + // result: Ok(()), + // }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: AccountId32::new(ALICE), task_id: task_will_be_run_id, @@ -1899,11 +1900,11 @@ fn trigger_tasks_limits_missed_slots() { sender: owner.clone(), hash: BlakeTwo256::hash(&vec![32]), }), - RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - who: owner.clone(), - task_id, - result: Ok(()), - }), + // RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { + // who: owner.clone(), + // task_id, + // result: Ok(()), + // }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id, @@ -2324,10 +2325,6 @@ fn trigger_tasks_completes_some_xcmp_tasks() { assert_eq!( events(), [ - RuntimeEvent::AutomationTime(crate::Event::XcmpTaskSucceeded { - destination, - task_id, - }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: AccountId32::new(ALICE), task_id, @@ -2364,26 +2361,26 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { let new_balance = Balances::free_balance(AccountId32::new(ALICE)); assert!(new_balance < before_balance); assert_eq!(new_balance, account_minimum); - let delegation_event = events() - .into_iter() - .find(|e| match e { - RuntimeEvent::AutomationTime( - crate::Event::AutoCompoundDelegatorStakeSucceeded { .. }, - ) => true, - _ => false, - }) - .expect("AutoCompound success event should have been emitted"); + // let delegation_event = events() + // .into_iter() + // .find(|e| match e { + // RuntimeEvent::AutomationTime( + // crate::Event::AutoCompoundDelegatorStakeSucceeded { .. }, + // ) => true, + // _ => false, + // }) + // .expect("AutoCompound success event should have been emitted"); let execution_weight = MockWeight::::run_auto_compound_delegated_stake_task(); let fee = ExecutionWeightFee::get().saturating_mul(execution_weight.ref_time().into()); - assert_eq!( - delegation_event, - RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSucceeded { - task_id, - amount: before_balance - .checked_sub(account_minimum.saturating_add(fee)) - .expect("Event should not exist if value is neg"), - }) - ); + // assert_eq!( + // delegation_event, + // RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSucceeded { + // task_id, + // amount: before_balance + // .checked_sub(account_minimum.saturating_add(fee)) + // .expect("Event should not exist if value is neg"), + // }) + // ); }) } @@ -2422,27 +2419,27 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { let emitted_events = events(); - // Expected result: - // 1. Current execution will run and emit AutoCompoundDelegatorStakeSucceeded event - emitted_events - .clone() - .into_iter() - .find(|e| { - matches!( - e, - RuntimeEvent::AutomationTime( - crate::Event::AutoCompoundDelegatorStakeSucceeded { .. } - ) - ) - }) - .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted"); - - // 2. Next execution will be scheduled - emitted_events - .clone() - .into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }))) - .expect("TaskScheduled event should have been emitted"); + // // Expected result: + // // 1. Current execution will run and emit AutoCompoundDelegatorStakeSucceeded event + // emitted_events + // .clone() + // .into_iter() + // .find(|e| { + // matches!( + // e, + // RuntimeEvent::AutomationTime( + // crate::Event::AutoCompoundDelegatorStakeSucceeded { .. } + // ) + // ) + // }) + // .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted"); + + // // 2. Next execution will be scheduled + // emitted_events + // .clone() + // .into_iter() + // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }))) + // .expect("TaskScheduled event should have been emitted"); let next_scheduled_time = SCHEDULED_TIME + frequency; AutomationTime::get_scheduled_tasks(next_scheduled_time) @@ -2462,17 +2459,17 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { System::reset_events(); AutomationTime::trigger_tasks(Weight::from_ref_time(100_000_000_000)); - events() - .into_iter() - .find(|e| { - matches!( - e, - RuntimeEvent::AutomationTime( - crate::Event::AutoCompoundDelegatorStakeSucceeded { .. } - ) - ) - }) - .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted again!"); + // events() + // .into_iter() + // .find(|e| { + // matches!( + // e, + // RuntimeEvent::AutomationTime( + // crate::Event::AutoCompoundDelegatorStakeSucceeded { .. } + // ) + // ) + // }) + // .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted again!"); }) } @@ -2510,16 +2507,16 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { let emitted_events = events(); - // Expected result: - // 1. The current execution will be skipped, triggering the emission of an AutoCompoundDelegatorStakeSkipped event, message: Balance less than minimum - emitted_events.clone().into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSkipped { message, .. }) if *message == ERROR_MESSAGE_BALANCE_LOW.as_bytes().to_vec())).expect("AutoCompoundDelegatorStakeSkipped event should have been emitted"); + // // Expected result: + // // 1. The current execution will be skipped, triggering the emission of an AutoCompoundDelegatorStakeSkipped event, message: Balance less than minimum + // emitted_events.clone().into_iter() + // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSkipped { message, .. }) if *message == ERROR_MESSAGE_BALANCE_LOW.as_bytes().to_vec())).expect("AutoCompoundDelegatorStakeSkipped event should have been emitted"); - // 2. Next execution will be scheduled - emitted_events - .into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }))) - .expect("TaskScheduled event should have been emitted"); + // // 2. Next execution will be scheduled + // emitted_events + // .into_iter() + // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }))) + // .expect("TaskScheduled event should have been emitted"); let next_scheduled_time = SCHEDULED_TIME + frequency; AutomationTime::get_scheduled_tasks(next_scheduled_time) @@ -2567,20 +2564,20 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - // Expected result: - // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound - events() - .into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { error, .. }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound))) - .expect("AutoCompound failure event should have been emitted"); + // // Expected result: + // // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound + // events() + // .into_iter() + // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { error, .. }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound))) + // .expect("AutoCompound failure event should have been emitted"); - // 2. Next execution will not be scheduled - assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) - .filter(|scheduled| { - scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id)) - }) - .is_none()); - assert!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id).is_none()); + // // 2. Next execution will not be scheduled + // assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) + // .filter(|scheduled| { + // scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id)) + // }) + // .is_none()); + // assert!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id).is_none()); }) } @@ -2618,28 +2615,28 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - // Expected result: - // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound - let failed_error_message = format!(ERROR_MESSAGE_DELEGATION_FORMAT!(), hex::encode(&delegator), hex::encode(&collator)); - events() - .into_iter() - .find(|e| { - matches!(e, - RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { - error_message, - error, - .. - }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound) && *error_message == failed_error_message.as_bytes().to_vec()) - }) - .expect("AutoCompound failure event should have been emitted"); - - // 2. Next execution will not be scheduled - assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) - .filter(|scheduled| { - scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id)) - }) - .is_none()); - assert!(AutomationTime::get_account_task(delegator.clone(), task_id).is_none()); + // // Expected result: + // // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound + // let failed_error_message = format!(ERROR_MESSAGE_DELEGATION_FORMAT!(), hex::encode(&delegator), hex::encode(&collator)); + // events() + // .into_iter() + // .find(|e| { + // matches!(e, + // RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { + // error_message, + // error, + // .. + // }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound) && *error_message == failed_error_message.as_bytes().to_vec()) + // }) + // .expect("AutoCompound failure event should have been emitted"); + + // // 2. Next execution will not be scheduled + // assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) + // .filter(|scheduled| { + // scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id)) + // }) + // .is_none()); + // assert!(AutomationTime::get_account_task(delegator.clone(), task_id).is_none()); }) } diff --git a/pallets/automation-time/src/types.rs b/pallets/automation-time/src/types.rs index 1a7d599d0..dbf56c9ec 100644 --- a/pallets/automation-time/src/types.rs +++ b/pallets/automation-time/src/types.rs @@ -2,9 +2,9 @@ use crate::{weights::WeightInfo, Config, Error, InstructionSequence, Pallet}; use frame_support::{dispatch::GetDispatchInfo, pallet_prelude::*, traits::Get}; -use scale_info::prelude::{format, string::String}; +use scale_info::prelude::string::String; use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion, Printable}; -use sp_std::{collections::btree_map::BTreeMap, prelude::*}; +use sp_std::prelude::*; use pallet_automation_time_rpc_runtime_api::AutomationAction; @@ -385,17 +385,6 @@ where pub error: DispatchError, } -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)] -pub struct DispatchErrorDataMap(BTreeMap); -impl sp_runtime::traits::Printable for DispatchErrorDataMap { - fn print(&self) { - for (key, value) in self.0.iter() { - sp_io::misc::print_utf8(format!("{:?}: {:?}, ", key, value).as_bytes()); - } - } -} -pub type DispatchErrorWithDataMap = DispatchErrorWithData; - #[cfg(test)] mod tests { use super::*; diff --git a/pallets/vesting/Cargo.toml b/pallets/vesting/Cargo.toml index 1b7b1f7e5..4788b607a 100644 --- a/pallets/vesting/Cargo.toml +++ b/pallets/vesting/Cargo.toml @@ -34,7 +34,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", default-featur pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } ## Moonbeam dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } diff --git a/runtime/neumann/Cargo.toml b/runtime/neumann/Cargo.toml index 7e6f710ba..4b404cf6c 100644 --- a/runtime/neumann/Cargo.toml +++ b/runtime/neumann/Cargo.toml @@ -96,7 +96,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/runtime/oak/Cargo.toml b/runtime/oak/Cargo.toml index dd26f96fe..a2e5744d1 100644 --- a/runtime/oak/Cargo.toml +++ b/runtime/oak/Cargo.toml @@ -102,7 +102,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/runtime/turing/Cargo.toml b/runtime/turing/Cargo.toml index 367c702c3..fa3bdeb96 100644 --- a/runtime/turing/Cargo.toml +++ b/runtime/turing/Cargo.toml @@ -102,7 +102,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } From 2b5ae4d00aa622972303933ba6b87f290f690731 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Tue, 25 Jul 2023 14:59:07 +0000 Subject: [PATCH 13/37] fixup: auto format Rust code --- pallets/automation-time/src/lib.rs | 34 ++++++++++++++-------------- pallets/automation-time/src/mock.rs | 2 +- pallets/automation-time/src/tests.rs | 26 ++++++++++----------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index a768b34dc..4f452390a 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -75,9 +75,7 @@ use scale_info::{ TypeInfo, }; use sp_runtime::{ - traits::{ - CheckedConversion, Convert, Dispatchable, SaturatedConversion, Saturating, - }, + traits::{CheckedConversion, Convert, Dispatchable, SaturatedConversion, Saturating}, ArithmeticError, DispatchError, Perbill, }; use sp_std::{boxed::Box, collections::btree_map::BTreeMap, vec, vec::Vec}; @@ -1134,9 +1132,7 @@ pub mod pallet { overall_weight, flow, ) { - Ok(()) => { - (::WeightInfo::run_xcmp_task(), None) - }, + Ok(()) => (::WeightInfo::run_xcmp_task(), None), Err(e) => { Self::deposit_event(Event::XcmpTaskFailed { task_id, destination, error: e }); (::WeightInfo::run_xcmp_task(), Some(e)) @@ -1158,29 +1154,33 @@ pub mod pallet { return ( ::WeightInfo::run_auto_compound_delegated_stake_task(), Some(fee_amount.unwrap_err()), - ); + ) } let fee_amount = fee_amount.unwrap(); let reserved_funds = account_minimum.saturating_add(fee_amount); match T::DelegatorActions::delegator_bond_till_minimum( - &delegator, &collator, reserved_funds, + &delegator, + &collator, + reserved_funds, ) { - Ok(_) => { - ( - ::WeightInfo::run_auto_compound_delegated_stake_task(), - None, - ) - }, + Ok(_) => + (::WeightInfo::run_auto_compound_delegated_stake_task(), None), Err(e) => { // BTreeMap::new() // let error = DispatchErrorDataMap { - // data: + // data: // } let mut data_map: BTreeMap = BTreeMap::new(); - data_map.insert(String::from("delagator"), String::from("68TwNoCpyz1X3ygMi9WtUAaCb8Q6jWAMvAHfAByRZqMFEtJG")); - data_map.insert(String::from("collator"), String::from("67RWv3VtgUxhL9jqu4jQPxJPzoApnbTyHhSdr8ELLwfNjJ5m")); + data_map.insert( + String::from("delagator"), + String::from("68TwNoCpyz1X3ygMi9WtUAaCb8Q6jWAMvAHfAByRZqMFEtJG"), + ); + data_map.insert( + String::from("collator"), + String::from("67RWv3VtgUxhL9jqu4jQPxJPzoApnbTyHhSdr8ELLwfNjJ5m"), + ); let error = DispatchErrorWithDataMap { data: DispatchErrorDataMap(data_map), diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 081975eca..8916f81b7 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -27,7 +27,7 @@ use primitives::EnsureProxy; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{AccountIdConversion, BlakeTwo256, Convert, IdentityLookup, CheckedSub}, + traits::{AccountIdConversion, BlakeTwo256, CheckedSub, Convert, IdentityLookup}, AccountId32, DispatchError, Perbill, }; use sp_std::marker::PhantomData; diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 8b88f2c18..065ae0a68 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -484,9 +484,11 @@ fn will_emit_task_completed_event_when_task_failed() { let current_funds = Balances::free_balance(AccountId32::new(ALICE)); // Because the execution of the transfer task twice requires a total amount is larger than current balance, the second task will fail. - let call: ::RuntimeCall = - pallet_balances::Call::transfer { dest: AccountId32::new(BOB), value: current_funds / 2 + 1 } - .into(); + let call: ::RuntimeCall = pallet_balances::Call::transfer { + dest: AccountId32::new(BOB), + value: current_funds / 2 + 1, + } + .into(); // Schedule a task to be executed at SCHEDULED_TIME and SCHEDULED_TIME + frequency. let next_execution_time = SCHEDULED_TIME + frequency; @@ -526,10 +528,10 @@ fn will_emit_task_completed_event_when_task_failed() { // .expect("The DynamicDispatchResult event with error should be emitted when task failed"); // When a task fails, the TaskCompleted event will still be emitted. - let event = my_events.into_iter().find(|e| { - matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. })) - }) - .expect("When a task fails, the TaskCompleted event will still be emitted"); + let event = my_events + .into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. }))) + .expect("When a task fails, the TaskCompleted event will still be emitted"); }) } @@ -2324,12 +2326,10 @@ fn trigger_tasks_completes_some_xcmp_tasks() { assert_eq!( events(), - [ - RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: AccountId32::new(ALICE), - task_id, - }) - ] + [RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { + who: AccountId32::new(ALICE), + task_id, + })] ); }) } From 49c19a93ffd5b22fe4edb089ee074ed6b441a0b1 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Thu, 27 Jul 2023 02:41:17 +0800 Subject: [PATCH 14/37] Fix tests --- Cargo.lock | 53 ++--- pallets/automation-time/src/lib.rs | 21 +- pallets/automation-time/src/mock.rs | 80 +++++++- pallets/automation-time/src/tests.rs | 296 +++++++++++++++++++++------ 4 files changed, 342 insertions(+), 108 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0957748c..a92e11415 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,7 +419,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.27", ] [[package]] @@ -763,9 +763,9 @@ checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byte-slice-cast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byte-tools" @@ -1017,7 +1017,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.27", ] [[package]] @@ -1968,7 +1968,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.15", + "syn 2.0.27", ] [[package]] @@ -1985,7 +1985,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.27", ] [[package]] @@ -3122,7 +3122,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.27", ] [[package]] @@ -5935,6 +5935,7 @@ version = "1.0.0" dependencies = [ "cumulus-pallet-xcm", "cumulus-primitives-core", + "env_logger", "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", "frame-system 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", @@ -7032,9 +7033,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.4.0" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637935964ff85a605d114591d4d2c13c5d1ba2806dae97cea6bf180238a749ac" +checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" dependencies = [ "arrayvec 0.7.2", "bitvec", @@ -7047,9 +7048,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.4" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -8602,9 +8603,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -8768,9 +8769,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -10629,22 +10630,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.27", ] [[package]] @@ -12168,7 +12169,7 @@ dependencies = [ [[package]] name = "substrate-fixed" version = "0.5.9" -source = "git+https://github.com/encointer/substrate-fixed#a4fb461aae6205ffc55bed51254a40c52be04e5d" +source = "git+https://github.com/encointer/substrate-fixed#df67f97a6db9b40215f105613b381ca82f1e2ff4" dependencies = [ "parity-scale-codec", "scale-info", @@ -12283,9 +12284,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" dependencies = [ "proc-macro2", "quote", @@ -12383,7 +12384,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.27", ] [[package]] @@ -12553,7 +12554,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.27", ] [[package]] @@ -13006,7 +13007,7 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "typenum" version = "1.16.0" -source = "git+https://github.com/encointer/typenum?tag=v1.16.0#4c8dddaa8bdd13130149e43b4085ad14e960617f" +source = "git+https://github.com/encointer/typenum?tag=polkadot-v1.0.0#4cba9a73f7e94ba38c824616efab93f177c9a556" dependencies = [ "parity-scale-codec", "scale-info", diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 4f452390a..cc25251cc 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -101,6 +101,8 @@ impl sp_runtime::traits::Printable for DispatchErrorDataMap { } pub type DispatchErrorWithDataMap = DispatchErrorWithData; +const AUTO_COMPOUND_DELEGATION_CANCEL_UPON_ERRORS: [&str; 1] = ["DelegationDNE"]; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -564,7 +566,13 @@ pub mod pallet { account_minimum, }; let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; - Self::validate_and_schedule_task(action, who, provided_id, schedule, vec![])?; + + let errors: Vec = AUTO_COMPOUND_DELEGATION_CANCEL_UPON_ERRORS + .iter() + .map(|&error| String::from(error)) + .collect(); + + Self::validate_and_schedule_task(action, who, provided_id, schedule, errors)?; Ok(().into()) } @@ -1167,19 +1175,14 @@ pub mod pallet { Ok(_) => (::WeightInfo::run_auto_compound_delegated_stake_task(), None), Err(e) => { - // BTreeMap::new() - // let error = DispatchErrorDataMap { - // data: - // } - let mut data_map: BTreeMap = BTreeMap::new(); data_map.insert( String::from("delagator"), - String::from("68TwNoCpyz1X3ygMi9WtUAaCb8Q6jWAMvAHfAByRZqMFEtJG"), + String::from(hex::encode(Encode::encode(&delegator))), ); data_map.insert( String::from("collator"), - String::from("67RWv3VtgUxhL9jqu4jQPxJPzoApnbTyHhSdr8ELLwfNjJ5m"), + String::from(hex::encode(Encode::encode(&collator))), ); let error = DispatchErrorWithDataMap { @@ -1479,7 +1482,7 @@ pub mod pallet { ) { match dispatch_error { Some(err) - if !task + if task .cancel_upon_errors .contains(&String::from(Into::<&str>::into(err))) => { diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 8916f81b7..686de279c 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -19,9 +19,9 @@ use super::*; use crate as pallet_automation_time; use frame_benchmarking::frame_support::assert_ok; use frame_support::{ - construct_runtime, parameter_types, traits::Everything, weights::Weight, PalletId, + construct_runtime, parameter_types, traits::{ ConstU128, ConstU32, Everything }, weights::Weight, PalletId, dispatch::DispatchErrorWithPostInfo, }; -use frame_system::{self as system, RawOrigin}; +use frame_system::{self as system, RawOrigin, EnsureRoot}; use orml_traits::parameter_type_with_key; use primitives::EnsureProxy; use sp_core::H256; @@ -40,6 +40,12 @@ pub type Balance = u128; pub type AccountId = AccountId32; pub type CurrencyId = u32; +const TOKEN_DECIMALS: u32 = 10; +const TOKEN_BASE: u128 = 10; +// Unit = the base number of indivisible units for balances +const UNIT: Balance = TOKEN_BASE.pow(TOKEN_DECIMALS); // 10_000_000_000 +const DOLLAR: Balance = UNIT; // 10_000_000_000 + pub const ALICE: [u8; 32] = [1u8; 32]; pub const BOB: [u8; 32] = [2u8; 32]; pub const DELEGATOR_ACCOUNT: [u8; 32] = [3u8; 32]; @@ -93,6 +99,7 @@ construct_runtime!( Tokens: orml_tokens::{Pallet, Storage, Event, Config}, Currencies: orml_currencies::{Pallet, Call}, AutomationTime: pallet_automation_time::{Pallet, Call, Storage, Event}, + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config}, } ); @@ -180,6 +187,8 @@ impl orml_currencies::Config for Test { pub type AdaptedBasicCurrency = orml_currencies::BasicCurrencyAdapter; parameter_types! { + /// Minimum stake required to become a collator + pub const MinCollatorStk: u128 = 400_000 * DOLLAR; pub const MinimumPeriod: u64 = 1000; } @@ -190,9 +199,52 @@ impl pallet_timestamp::Config for Test { type WeightInfo = (); } +impl pallet_parachain_staking::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = EnsureRoot; + /// Minimum round length is 2 minutes (10 * 12 second block times) + type MinBlocksPerRound = ConstU32<10>; + /// Rounds before the collator leaving the candidates request can be executed + type LeaveCandidatesDelay = ConstU32<2>; + /// Rounds before the candidate bond increase/decrease can be executed + type CandidateBondLessDelay = ConstU32<2>; + /// Rounds before the delegator exit can be executed + type LeaveDelegatorsDelay = ConstU32<2>; + /// Rounds before the delegator revocation can be executed + type RevokeDelegationDelay = ConstU32<2>; + /// Rounds before the delegator bond increase/decrease can be executed + type DelegationBondLessDelay = ConstU32<2>; + /// Rounds before the reward is paid + type RewardPaymentDelay = ConstU32<2>; + /// Minimum collators selected per round, default at genesis and minimum forever after + type MinSelectedCandidates = ConstU32<5>; + /// Maximum top delegations per candidate + type MaxTopDelegationsPerCandidate = ConstU32<10>; + /// Maximum bottom delegations per candidate + type MaxBottomDelegationsPerCandidate = ConstU32<50>; + /// Maximum delegations per delegator + type MaxDelegationsPerDelegator = ConstU32<10>; + type MinCollatorStk = MinCollatorStk; + /// Minimum stake required to be reserved to be a candidate + type MinCandidateStk = ConstU128<{ 500 * DOLLAR }>; + /// Minimum delegation amount after initial + type MinDelegation = ConstU128<{ 50 * DOLLAR }>; + /// Minimum initial stake required to be reserved to be a delegator + type MinDelegatorStk = ConstU128<{ 50 * DOLLAR }>; + /// Handler to notify the runtime when a collator is paid + type OnCollatorPayout = (); + type PayoutCollatorReward = (); + /// Handler to notify the runtime when a new round begins + type OnNewRound = (); + /// Any additional issuance that should be used for inflation calcs + type AdditionalIssuance = (); + type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; +} + pub struct MockDelegatorActions(PhantomData<(T, C)>); impl< - T: Config + pallet::Config, + T: Config + pallet::Config + pallet_parachain_staking::Config, C: frame_support::traits::ReservableCurrency, > pallet_parachain_staking::DelegatorActions> for MockDelegatorActions @@ -209,12 +261,19 @@ impl< fn delegator_bond_till_minimum( delegator: &T::AccountId, - _candidate: &T::AccountId, + candidate: &T::AccountId, account_minimum: BalanceOf, - ) -> Result, frame_support::dispatch::DispatchErrorWithPostInfo> { + ) -> Result, DispatchErrorWithPostInfo> { + log::error!("delegator_bond_till_minimum AAAAAAA"); + if *candidate != T::AccountId::decode(&mut COLLATOR_ACCOUNT.as_ref()).unwrap() { + log::error!("delegator_bond_till_minimum BBBB"); + return Err(DispatchErrorWithPostInfo::from(>::DelegationDNE)); + } + log::error!("delegator_bond_till_minimum CCCCCC"); + let delegation = C::free_balance(&delegator) .checked_sub(&account_minimum) - .ok_or(Error::::InsufficientBalance)?; + .ok_or(>::InsufficientBalance)?; C::reserve(delegator, delegation)?; Ok(delegation) } @@ -485,7 +544,7 @@ pub fn schedule_task( provided_id: Vec, scheduled_times: Vec, message: Vec, -) -> sp_core::H256 { +) -> (RuntimeCall, sp_core::H256) { let account_id = AccountId32::new(owner); let task_hash_input = TaskHashInput::new(account_id.clone(), provided_id.clone()); let call: RuntimeCall = frame_system::Call::remark_with_event { remark: message }.into(); @@ -496,9 +555,9 @@ pub fn schedule_task( RuntimeOrigin::signed(account_id.clone()), provided_id, ScheduleParam::Fixed { execution_times: scheduled_times }, - Box::new(call), + Box::new(call.clone()), )); - BlakeTwo256::hash_of(&task_hash_input) + (call, BlakeTwo256::hash_of(&task_hash_input)) } // A function to support test scheduling a Recurring schedule @@ -590,7 +649,8 @@ pub fn create_task( } pub fn events() -> Vec { - let evt = System::events().into_iter().map(|evt| evt.event).collect::>(); + let events = System::events(); + let evt = events.into_iter().map(|evt| evt.event).collect::>(); System::reset_events(); diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 065ae0a68..5c0797c11 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -36,6 +36,10 @@ use sp_runtime::{ AccountId32, }; use xcm::latest::{prelude::*, Junction::Parachain, MultiLocation}; +use sp_runtime::DispatchError::Module; +use sp_runtime::ModuleError; +use frame_support::pallet_prelude::DispatchError; +use sp_std::collections::btree_map::BTreeMap; use pallet_balances; use pallet_valve::Shutdown; @@ -321,7 +325,7 @@ fn schedule_transfer_with_dynamic_dispatch() { RuntimeOrigin::signed(account_id.clone()), vec![1, 2], ScheduleParam::Fixed { execution_times: vec![SCHEDULED_TIME] }, - Box::new(call), + Box::new(call.clone()), )); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); @@ -334,9 +338,19 @@ fn schedule_transfer_with_dynamic_dispatch() { let recipient = AccountId32::new(BOB); assert_eq!(Balances::free_balance(recipient.clone()), 127); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); assert_eq!( my_events, [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: account_id.clone(), + task_id: task_id.clone(), + condition, + encoded_call: call.encode(), + cancel_upon_errors: vec![], + }), RuntimeEvent::System(frame_system::Event::NewAccount { account: recipient.clone() }), @@ -349,11 +363,6 @@ fn schedule_transfer_with_dynamic_dispatch() { to: recipient.clone(), amount: 127, }), - // RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - // who: account_id.clone(), - // task_id, - // result: Ok(()), - // }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: account_id, task_id, @@ -416,6 +425,7 @@ fn will_emit_task_completed_event_when_task_completed() { } // The TaskCompleted event will not be emitted when the task is canceled. +#[test] fn will_not_emit_task_completed_event_when_task_canceled() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let frequency = 3_600; @@ -1076,7 +1086,7 @@ fn schedule_execution_times_removes_dupes() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let owner = AccountId32::new(ALICE); get_funds(owner.clone()); - let task_id1 = schedule_task( + let (_, task_id1) = schedule_task( ALICE, vec![50], vec![ @@ -1172,11 +1182,11 @@ fn schedule_time_slot_full_rolls_back() { let call1: RuntimeCall = frame_system::Call::remark { remark: vec![2, 4, 5] }.into(); assert_ok!(fund_account_dynamic_dispatch(&AccountId32::new(ALICE), 1, call1.encode())); - let task_id1 = schedule_task(ALICE, vec![40], vec![SCHEDULED_TIME + 7200], vec![2, 4, 5]); + let (_, task_id1) = schedule_task(ALICE, vec![40], vec![SCHEDULED_TIME + 7200], vec![2, 4, 5]); let call2: RuntimeCall = frame_system::Call::remark { remark: vec![2, 4] }.into(); assert_ok!(fund_account_dynamic_dispatch(&AccountId32::new(ALICE), 1, call1.encode())); - let task_id2 = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME + 7200], vec![2, 4]); + let (_, task_id2) = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME + 7200], vec![2, 4]); let call: RuntimeCall = frame_system::Call::remark { remark: vec![2] }.into(); assert_ok!(fund_account_dynamic_dispatch(&AccountId32::new(ALICE), 1, call.encode())); @@ -1221,8 +1231,8 @@ fn schedule_time_slot_full_rolls_back() { #[test] fn cancel_works_for_fixed_scheduled() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - let task_id1 = schedule_task(ALICE, vec![40], vec![SCHEDULED_TIME], vec![2, 4, 5]); - let task_id2 = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME], vec![2, 4]); + let (_, task_id1) = schedule_task(ALICE, vec![40], vec![SCHEDULED_TIME], vec![2, 4, 5]); + let (_, task_id2) = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME], vec![2, 4]); LastTimeSlot::::put((SCHEDULED_TIME - 14400, SCHEDULED_TIME - 14400)); System::reset_events(); @@ -1261,7 +1271,7 @@ fn cancel_works_for_fixed_scheduled() { fn cancel_works_for_multiple_executions_scheduled() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let owner = AccountId32::new(ALICE); - let task_id1 = schedule_task( + let (_, task_id1) = schedule_task( ALICE, vec![40], vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600, SCHEDULED_TIME + 7200], @@ -1338,7 +1348,7 @@ fn cancel_works_for_recurring_scheduled() { fn cancel_works_for_an_executed_task() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let owner = AccountId32::new(ALICE); - let task_id1 = + let (call, task_id1) = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600], vec![50]); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); LastTimeSlot::::put((SCHEDULED_TIME - 3600, SCHEDULED_TIME - 3600)); @@ -1375,19 +1385,23 @@ fn cancel_works_for_an_executed_task() { AutomationTime::trigger_tasks(Weight::from_ref_time(200_000)); let my_events = events(); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); assert_eq!( my_events, - //[RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![50] }),] [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id1, + condition, + encoded_call: call.encode(), + cancel_upon_errors: vec![], + }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), hash: BlakeTwo256::hash(&vec![50]), }), - // RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - // who: owner.clone(), - // task_id: task_id1, - // result: Ok(()), - // }), ] ); match AutomationTime::get_account_task(owner.clone(), task_id1) { @@ -1527,7 +1541,7 @@ fn cancel_task_not_found() { fn cancel_task_fail_non_owner() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let owner = AccountId32::new(ALICE); - let task_id1 = schedule_task( + let (_, task_id1) = schedule_task( ALICE, vec![40], vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600, SCHEDULED_TIME + 7200], @@ -1551,7 +1565,7 @@ fn cancel_task_fail_non_owner() { // #[test] fn force_cancel_task_works() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - let task_id = schedule_task(ALICE, vec![40], vec![SCHEDULED_TIME], vec![2, 4, 5]); + let (_, task_id) = schedule_task(ALICE, vec![40], vec![SCHEDULED_TIME], vec![2, 4, 5]); LastTimeSlot::::put((SCHEDULED_TIME - 14400, SCHEDULED_TIME - 14400)); System::reset_events(); @@ -1757,7 +1771,7 @@ fn trigger_tasks_updates_queues() { SCHEDULED_TIME - 3600, ); assert_eq!(AutomationTime::get_missed_queue().len(), 0); - let scheduled_task_id = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME], vec![50]); + let (_, scheduled_task_id) = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME], vec![50]); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); LastTimeSlot::::put((SCHEDULED_TIME - 3600, SCHEDULED_TIME - 3600)); System::reset_events(); @@ -1781,6 +1795,7 @@ fn trigger_tasks_updates_queues() { #[test] fn trigger_tasks_handles_missed_slots() { new_test_ext(START_BLOCK_TIME).execute_with(|| { + let owner = AccountId32::new(ALICE); let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: vec![40] }.into(); @@ -1793,15 +1808,15 @@ fn trigger_tasks_handles_missed_slots() { assert_eq!(AutomationTime::get_missed_queue().len(), 0); - let missed_task_id = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME - 3600], vec![50]); + let (_, missed_task_id) = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME - 3600], vec![50]); let missed_task = MissedTaskV2Of::::new( AccountId32::new(ALICE), - missed_task_id, + missed_task_id.clone(), SCHEDULED_TIME - 3600, ); - let task_will_be_run_id = schedule_task(ALICE, vec![59], vec![SCHEDULED_TIME], vec![50]); - let scheduled_task_id = schedule_task(ALICE, vec![60], vec![SCHEDULED_TIME], vec![50]); + let (call, task_will_be_run_id) = schedule_task(ALICE, vec![59], vec![SCHEDULED_TIME], vec![50]); + let (_, scheduled_task_id) = schedule_task(ALICE, vec![60], vec![SCHEDULED_TIME], vec![50]); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); LastTimeSlot::::put((SCHEDULED_TIME - 7200, SCHEDULED_TIME - 7200)); @@ -1817,18 +1832,25 @@ fn trigger_tasks_handles_missed_slots() { // the final one is in current schedule will be move into the task queue assert_eq!(AutomationTime::get_task_queue().len(), 1); assert_eq!(AutomationTime::get_task_queue()[0].1, scheduled_task_id); + + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); + assert_eq!( events(), vec![ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_will_be_run_id, + condition, + encoded_call: call.encode(), + cancel_upon_errors: vec![], + }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: AccountId32::new(ALICE), hash: BlakeTwo256::hash(&vec![50]), }), - // RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - // who: AccountId32::new(ALICE), - // task_id: task_will_be_run_id, - // result: Ok(()), - // }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: AccountId32::new(ALICE), task_id: task_will_be_run_id, @@ -1866,19 +1888,19 @@ fn trigger_tasks_limits_missed_slots() { assert_eq!(AutomationTime::get_missed_queue().len(), 0); Timestamp::set_timestamp((SCHEDULED_TIME - 25200) * 1_000); - let missing_task_id1 = + let (_, missing_task_id1) = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME - 3600], vec![50]); - let missing_task_id2 = + let (_, missing_task_id2) = schedule_task(ALICE, vec![60], vec![SCHEDULED_TIME - 7200], vec![50]); - let missing_task_id3 = + let (_, missing_task_id3) = schedule_task(ALICE, vec![70], vec![SCHEDULED_TIME - 10800], vec![50]); - let missing_task_id4 = + let (_, missing_task_id4) = schedule_task(ALICE, vec![80], vec![SCHEDULED_TIME - 14400], vec![50]); - let missing_task_id5 = + let (_, missing_task_id5) = schedule_task(ALICE, vec![90], vec![SCHEDULED_TIME - 18000], vec![50]); - let task_id = schedule_task(ALICE, vec![100], vec![SCHEDULED_TIME], vec![32]); + let (call, task_id) = schedule_task(ALICE, vec![100], vec![SCHEDULED_TIME], vec![32]); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); LastTimeSlot::::put((SCHEDULED_TIME - 25200, SCHEDULED_TIME - 25200)); @@ -1895,18 +1917,25 @@ fn trigger_tasks_limits_missed_slots() { { assert_eq!(updated_last_time_slot, SCHEDULED_TIME); assert_eq!(updated_last_missed_slot, SCHEDULED_TIME - 10800); + + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); + assert_eq!( my_events, [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id.clone(), + condition: condition.clone(), + encoded_call: call.encode(), + cancel_upon_errors: vec![], + }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), hash: BlakeTwo256::hash(&vec![32]), }), - // RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { - // who: owner.clone(), - // task_id, - // result: Ok(()), - // }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id, @@ -1979,6 +2008,7 @@ fn trigger_tasks_limits_missed_slots() { fn trigger_tasks_completes_all_tasks() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let message_one: Vec = vec![2, 4, 5]; + let owner = AccountId32::new(ALICE); let task_id1 = add_task_to_task_queue( ALICE, vec![40], @@ -1996,14 +2026,32 @@ fn trigger_tasks_completes_all_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + assert_eq!( events(), [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id1.clone(), + condition: condition.clone(), + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: AccountId32::new(ALICE), task_id: task_id1, }), + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner, + task_id: task_id2.clone(), + condition, + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: AccountId32::new(ALICE), @@ -2062,9 +2110,20 @@ fn trigger_tasks_completes_some_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(80_000)); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + assert_eq!( events(), [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: AccountId32::new(ALICE), + task_id: task_id1.clone(), + condition, + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: AccountId32::new(ALICE), @@ -2236,9 +2295,21 @@ fn missed_tasks_removes_completed_tasks() { assert_eq!(AutomationTime::get_task_queue().len(), 0); assert_eq!(AutomationTime::get_missed_queue().len(), 0); + + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + assert_eq!( events(), [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id01.clone(), + condition: condition.clone(), + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one }), RuntimeEvent::AutomationTime(crate::Event::TaskMissed { who: AccountId32::new(ALICE), @@ -2300,6 +2371,8 @@ fn trigger_tasks_completes_some_native_transfer_tasks() { fn trigger_tasks_completes_some_xcmp_tasks() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let destination = MultiLocation::new(1, X1(Parachain(PARA_ID))); + let encoded_call = vec![3, 4, 5]; + let owner = AccountId32::new(ALICE); let task_id = add_task_to_task_queue( ALICE, vec![40], @@ -2311,7 +2384,7 @@ fn trigger_tasks_completes_some_xcmp_tasks() { asset_location: MultiLocation::new(0, Here).into(), amount: 10, }, - encoded_call: vec![3, 4, 5], + encoded_call: encoded_call.clone(), encoded_call_weight: Weight::from_ref_time(100_000), overall_weight: Weight::from_ref_time(200_000), schedule_as: None, @@ -2324,12 +2397,25 @@ fn trigger_tasks_completes_some_xcmp_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + assert_eq!( events(), - [RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: AccountId32::new(ALICE), - task_id, - })] + [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id.clone(), + condition, + encoded_call, + cancel_upon_errors: vec![], + }), + RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { + who: owner, + task_id, + }) + ] ); }) } @@ -2478,7 +2564,7 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { // 1. User's wallet balance < minimum balance + execution fee // 2. User has a delegation with the specificed collator // Expected result: -// 1. The current execution will be skipped, triggering the emission of an AutoCompoundDelegatorStakeSkipped event, message: Balance less than minimum +// 1. Emit TaskExecutionFailed event with error: InsufficientBalance // 2. Next execution will be scheduled #[test] fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { @@ -2507,16 +2593,17 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { let emitted_events = events(); - // // Expected result: - // // 1. The current execution will be skipped, triggering the emission of an AutoCompoundDelegatorStakeSkipped event, message: Balance less than minimum - // emitted_events.clone().into_iter() - // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSkipped { message, .. }) if *message == ERROR_MESSAGE_BALANCE_LOW.as_bytes().to_vec())).expect("AutoCompoundDelegatorStakeSkipped event should have been emitted"); + // Expected result: + // 1. Emit TaskExecutionFailed event with error: InsufficientBalance + let insufficient_balance_error: DispatchError = >::InsufficientBalance.into(); + let event = emitted_events.clone().into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { error, .. }) if *error == insufficient_balance_error )).expect("TaskExecutionFailed event should have been emitted"); - // // 2. Next execution will be scheduled - // emitted_events - // .into_iter() - // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }))) - // .expect("TaskScheduled event should have been emitted"); + // 2. Next execution will be scheduled + emitted_events + .into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { .. }))) + .expect("TaskRescheduled event should have been emitted"); let next_scheduled_time = SCHEDULED_TIME + frequency; AutomationTime::get_scheduled_tasks(next_scheduled_time) @@ -2586,7 +2673,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { // 1. User's wallet balance < minimum balance + execution fee // 2. User has no delegation with the specificed collator // Expected result: -// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound +// 1. Emit TaskExecutionFailed event with error: DelegationDNE // 2. Next execution will not be scheduled #[test] fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { @@ -2615,8 +2702,8 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - // // Expected result: - // // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound + // Expected result: + // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound // let failed_error_message = format!(ERROR_MESSAGE_DELEGATION_FORMAT!(), hex::encode(&delegator), hex::encode(&collator)); // events() // .into_iter() @@ -2630,7 +2717,14 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { // }) // .expect("AutoCompound failure event should have been emitted"); - // // 2. Next execution will not be scheduled + let delegation_dne_error: DispatchError = >::DelegationDNE.into(); + + let emit_events = events(); + + let event = emit_events.into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { error, .. }) if *error == delegation_dne_error )).expect("TaskExecutionFailed event should have been emitted"); + + // 2. Next execution will not be scheduled // assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) // .filter(|scheduled| { // scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id)) @@ -2654,7 +2748,7 @@ fn trigger_tasks_updates_executions_left() { Action::Notify { message: message_one.clone() }, ); - match AutomationTime::get_account_task(owner.clone(), task_id01) { + match AutomationTime::get_account_task(owner.clone(), task_id01.clone()) { None => { panic!("A task should exist if it was scheduled") }, @@ -2668,9 +2762,22 @@ fn trigger_tasks_updates_executions_left() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + assert_eq!( events(), - [RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }),] + [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id01, + condition, + encoded_call: vec![], + cancel_upon_errors: vec![], + }), + RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), + ] ); match AutomationTime::get_account_task(owner.clone(), task_id01) { None => { @@ -2709,9 +2816,21 @@ fn trigger_tasks_removes_completed_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + assert_eq!( events(), [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id01.clone(), + condition, + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), @@ -2750,14 +2869,33 @@ fn on_init_runs_tasks() { LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); AutomationTime::on_initialize(1); + + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + assert_eq!( events(), [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id1.clone(), + condition: condition.clone(), + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: task_id1, }), + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id2.clone(), + condition: condition, + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), @@ -2816,14 +2954,32 @@ fn on_init_check_task_queue() { let owner = AccountId32::new(ALICE); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + assert_eq!( events(), [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: tasks[0].clone(), + condition: condition.clone(), + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![0] }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: tasks[0], }), + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: tasks[1].clone(), + condition: condition.clone(), + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![1] }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), @@ -2839,11 +2995,25 @@ fn on_init_check_task_queue() { assert_eq!( events(), [ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: tasks[2].clone(), + condition: condition.clone(), + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![2] }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: tasks[2], }), + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: tasks[3].clone(), + condition: condition.clone(), + encoded_call: vec![], + cancel_upon_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![3] }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), From 07fc23b27e1f52f11101e2cdcaaf942375dce0fe Mon Sep 17 00:00:00 2001 From: imstar15 Date: Fri, 28 Jul 2023 00:09:05 +0800 Subject: [PATCH 15/37] Fix tests. Add comments. --- Cargo.lock | 3 +- node/Cargo.toml | 2 +- pallets/automation-time/Cargo.toml | 2 +- pallets/automation-time/src/lib.rs | 148 ++++++++--------- pallets/automation-time/src/mock.rs | 129 +++++++-------- pallets/automation-time/src/tests.rs | 239 +++++++++++---------------- pallets/vesting/Cargo.toml | 2 +- runtime/neumann/Cargo.toml | 2 +- runtime/oak/Cargo.toml | 2 +- runtime/turing/Cargo.toml | 2 +- 10 files changed, 232 insertions(+), 299 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a92e11415..46bc48e04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5935,7 +5935,6 @@ version = "1.0.0" dependencies = [ "cumulus-pallet-xcm", "cumulus-primitives-core", - "env_logger", "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", "frame-system 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", @@ -6484,7 +6483,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-polkadot-v0.9.38#4ef614d84221f4ae364a4eb411f9fe2f00c8d497" +source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-staging#f9541fe1a0a3005947c5bc87ecc3d272f7741b1e" dependencies = [ "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", diff --git a/node/Cargo.toml b/node/Cargo.toml index 9b47c76bc..92fda25c7 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -127,7 +127,7 @@ polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "r xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", branch = "oak-staging" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/Cargo.toml b/pallets/automation-time/Cargo.toml index 6de638485..6ff71f011 100644 --- a/pallets/automation-time/Cargo.toml +++ b/pallets/automation-time/Cargo.toml @@ -50,7 +50,7 @@ pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-fe xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } ## Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } ## ORML orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index cc25251cc..63c905225 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -55,7 +55,7 @@ use cumulus_primitives_core::ParaId; use frame_support::{ dispatch::{GetDispatchInfo, PostDispatchInfo}, pallet_prelude::*, - sp_runtime::traits::Hash, + sp_runtime::traits::{CheckedSub, Hash}, storage::{ with_transaction, TransactionOutcome::{Commit, Rollback}, @@ -82,14 +82,6 @@ use sp_std::{boxed::Box, collections::btree_map::BTreeMap, vec, vec::Vec}; pub use weights::WeightInfo; use xcm::{latest::prelude::*, VersionedMultiLocation}; -#[macro_export] -macro_rules! ERROR_MESSAGE_DELEGATION_FORMAT { - () => { - "delegator: {:?}, collator: {:?}" - }; -} -pub const ERROR_MESSAGE_BALANCE_LOW: &str = "Balance less than minimum"; - #[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)] pub struct DispatchErrorDataMap(BTreeMap); impl sp_runtime::traits::Printable for DispatchErrorDataMap { @@ -101,7 +93,7 @@ impl sp_runtime::traits::Printable for DispatchErrorDataMap { } pub type DispatchErrorWithDataMap = DispatchErrorWithData; -const AUTO_COMPOUND_DELEGATION_CANCEL_UPON_ERRORS: [&str; 1] = ["DelegationDNE"]; +const AUTO_COMPOUND_DELEGATION_CANCEL_UPON_ERRORS: [&str; 1] = ["DelegationNotFound"]; #[frame_support::pallet] pub mod pallet { @@ -341,12 +333,6 @@ pub mod pallet { task_id: TaskId, execution_time: UnixTime, }, - // /// The result of the DynamicDispatch action. - // DynamicDispatchResult { - // who: AccountOf, - // task_id: TaskId, - // result: DispatchResult, - // }, /// The call for the DynamicDispatch action can no longer be decoded. CallCannotBeDecoded { who: AccountOf, @@ -1156,7 +1142,35 @@ pub mod pallet { task_id: TaskId, task: &TaskOf, ) -> (Weight, Option) { + let mut delegation_info: BTreeMap = BTreeMap::new(); + delegation_info.insert( + String::from("delagator"), + String::from(hex::encode(Encode::encode(&delegator))), + ); + delegation_info.insert( + String::from("collator"), + String::from(hex::encode(Encode::encode(&collator))), + ); + // TODO: Handle edge case where user has enough funds to run task but not reschedule + if !T::DelegatorActions::is_delegation_exist(&delegator, &collator) { + // DelegationNotFound + let error_with_data = DispatchErrorWithDataMap { + data: DispatchErrorDataMap(delegation_info), + message: Some(String::from(Into::<&str>::into(Error::::DelegationNotFound))), + error: Error::::DelegationNotFound.into(), + }; + Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { + who: task.owner_id.clone(), + task_id, + error: error_with_data.clone(), + }); + return ( + ::WeightInfo::run_auto_compound_delegated_stake_task(), + Some(error_with_data.error), + ) + } + let fee_amount = Self::calculate_schedule_fee_amount(&task.action, 1); if fee_amount.is_err() { return ( @@ -1167,38 +1181,52 @@ pub mod pallet { let fee_amount = fee_amount.unwrap(); let reserved_funds = account_minimum.saturating_add(fee_amount); - match T::DelegatorActions::delegator_bond_till_minimum( - &delegator, - &collator, - reserved_funds, - ) { - Ok(_) => - (::WeightInfo::run_auto_compound_delegated_stake_task(), None), - Err(e) => { - let mut data_map: BTreeMap = BTreeMap::new(); - data_map.insert( - String::from("delagator"), - String::from(hex::encode(Encode::encode(&delegator))), - ); - data_map.insert( - String::from("collator"), - String::from(hex::encode(Encode::encode(&collator))), - ); - + match T::DelegatorActions::get_delegator_stakable_free_balance(&delegator) + .checked_sub(&reserved_funds) + { + Some(delegation) => { + match T::DelegatorActions::delegator_bond_more( + &delegator, &collator, delegation, + ) { + Ok(_) => ( + ::WeightInfo::run_auto_compound_delegated_stake_task(), + None, + ), + Err(e) => { + let error = DispatchErrorWithDataMap { + data: DispatchErrorDataMap(delegation_info), + message: Some(String::from(Into::<&str>::into(e))), + error: e, + }; + Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { + who: task.owner_id.clone(), + task_id, + error, + }); + return ( + ::WeightInfo::run_auto_compound_delegated_stake_task(), + Some(e), + ) + }, + } + }, + None => { + // InsufficientBalance let error = DispatchErrorWithDataMap { - data: DispatchErrorDataMap(data_map), - message: Some(String::from(Into::<&str>::into(e))), - error: e.error, + data: DispatchErrorDataMap(delegation_info), + message: Some(String::from(Into::<&str>::into( + Error::::InsufficientBalance, + ))), + error: Error::::InsufficientBalance.into(), }; - Self::deposit_event(Event::AutoCompoundDelegatorStakeFailed { who: task.owner_id.clone(), task_id, - error, + error: error.clone(), }); - return ( + ( ::WeightInfo::run_auto_compound_delegated_stake_task(), - Some(e.error), + Some(error.error), ) }, } @@ -1480,11 +1508,10 @@ pub mod pallet { mut task: TaskOf, dispatch_error: Option, ) { + // When the error can be found in the cancel_upon_errors list, the next task execution will not be scheduled. Otherwise, continue to execute the next task. match dispatch_error { Some(err) - if task - .cancel_upon_errors - .contains(&String::from(Into::<&str>::into(err))) => + if task.cancel_upon_errors.contains(&String::from(Into::<&str>::into(err))) => { Self::deposit_event(Event::::TaskNotRescheduled { who: task.owner_id.clone(), @@ -1520,39 +1547,6 @@ pub mod pallet { }; }, } - - // if let Some(err) = dispatch_error if task.cancel_upon_errors.contains(&err.as_str()) { - // Self::deposit_event(Event::::TaskNotRescheduled { - // who: task.owner_id.clone(), - // task_id, - // error: err, - // }); - // AccountTasks::::remove(task.owner_id.clone(), task_id); - // } else { - // let owner_id = task.owner_id.clone(); - // let action = task.action.clone(); - // match Self::reschedule_existing_task(task_id, &mut task) { - // Ok(_) => { - // let schedule_as = match action { - // Action::XCMP { schedule_as, .. } => schedule_as, - // _ => None, - // }; - // Self::deposit_event(Event::::TaskRescheduled { - // who: owner_id, - // task_id, - // schedule_as, - // }); - // }, - // Err(err) => { - // Self::deposit_event(Event::::TaskFailedToReschedule { - // who: task.owner_id.clone(), - // task_id, - // error: err, - // }); - // AccountTasks::::remove(task.owner_id.clone(), task_id); - // }, - // }; - // } } fn reschedule_existing_task(task_id: TaskId, task: &mut TaskOf) -> DispatchResult { diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 686de279c..f3c65ce3c 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -19,15 +19,18 @@ use super::*; use crate as pallet_automation_time; use frame_benchmarking::frame_support::assert_ok; use frame_support::{ - construct_runtime, parameter_types, traits::{ ConstU128, ConstU32, Everything }, weights::Weight, PalletId, dispatch::DispatchErrorWithPostInfo, + construct_runtime, parameter_types, + traits::{ConstU32, Everything}, + weights::Weight, + PalletId, }; -use frame_system::{self as system, RawOrigin, EnsureRoot}; +use frame_system::{self as system, RawOrigin}; use orml_traits::parameter_type_with_key; use primitives::EnsureProxy; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{AccountIdConversion, BlakeTwo256, CheckedSub, Convert, IdentityLookup}, + traits::{AccountIdConversion, BlakeTwo256, Convert, IdentityLookup}, AccountId32, DispatchError, Perbill, }; use sp_std::marker::PhantomData; @@ -40,12 +43,6 @@ pub type Balance = u128; pub type AccountId = AccountId32; pub type CurrencyId = u32; -const TOKEN_DECIMALS: u32 = 10; -const TOKEN_BASE: u128 = 10; -// Unit = the base number of indivisible units for balances -const UNIT: Balance = TOKEN_BASE.pow(TOKEN_DECIMALS); // 10_000_000_000 -const DOLLAR: Balance = UNIT; // 10_000_000_000 - pub const ALICE: [u8; 32] = [1u8; 32]; pub const BOB: [u8; 32] = [2u8; 32]; pub const DELEGATOR_ACCOUNT: [u8; 32] = [3u8; 32]; @@ -99,7 +96,6 @@ construct_runtime!( Tokens: orml_tokens::{Pallet, Storage, Event, Config}, Currencies: orml_currencies::{Pallet, Call}, AutomationTime: pallet_automation_time::{Pallet, Call, Storage, Event}, - ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config}, } ); @@ -188,7 +184,7 @@ pub type AdaptedBasicCurrency = orml_currencies::BasicCurrencyAdapter; - /// Minimum round length is 2 minutes (10 * 12 second block times) - type MinBlocksPerRound = ConstU32<10>; - /// Rounds before the collator leaving the candidates request can be executed - type LeaveCandidatesDelay = ConstU32<2>; - /// Rounds before the candidate bond increase/decrease can be executed - type CandidateBondLessDelay = ConstU32<2>; - /// Rounds before the delegator exit can be executed - type LeaveDelegatorsDelay = ConstU32<2>; - /// Rounds before the delegator revocation can be executed - type RevokeDelegationDelay = ConstU32<2>; - /// Rounds before the delegator bond increase/decrease can be executed - type DelegationBondLessDelay = ConstU32<2>; - /// Rounds before the reward is paid - type RewardPaymentDelay = ConstU32<2>; - /// Minimum collators selected per round, default at genesis and minimum forever after - type MinSelectedCandidates = ConstU32<5>; - /// Maximum top delegations per candidate - type MaxTopDelegationsPerCandidate = ConstU32<10>; - /// Maximum bottom delegations per candidate - type MaxBottomDelegationsPerCandidate = ConstU32<50>; - /// Maximum delegations per delegator - type MaxDelegationsPerDelegator = ConstU32<10>; - type MinCollatorStk = MinCollatorStk; - /// Minimum stake required to be reserved to be a candidate - type MinCandidateStk = ConstU128<{ 500 * DOLLAR }>; - /// Minimum delegation amount after initial - type MinDelegation = ConstU128<{ 50 * DOLLAR }>; - /// Minimum initial stake required to be reserved to be a delegator - type MinDelegatorStk = ConstU128<{ 50 * DOLLAR }>; - /// Handler to notify the runtime when a collator is paid - type OnCollatorPayout = (); - type PayoutCollatorReward = (); - /// Handler to notify the runtime when a new round begins - type OnNewRound = (); - /// Any additional issuance that should be used for inflation calcs - type AdditionalIssuance = (); - type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; -} +// impl pallet_parachain_staking::Config for Test { +// type RuntimeEvent = RuntimeEvent; +// type Currency = Balances; +// type MonetaryGovernanceOrigin = EnsureRoot; +// /// Minimum round length is 2 minutes (10 * 12 second block times) +// type MinBlocksPerRound = ConstU32<10>; +// /// Rounds before the collator leaving the candidates request can be executed +// type LeaveCandidatesDelay = ConstU32<2>; +// /// Rounds before the candidate bond increase/decrease can be executed +// type CandidateBondLessDelay = ConstU32<2>; +// /// Rounds before the delegator exit can be executed +// type LeaveDelegatorsDelay = ConstU32<2>; +// /// Rounds before the delegator revocation can be executed +// type RevokeDelegationDelay = ConstU32<2>; +// /// Rounds before the delegator bond increase/decrease can be executed +// type DelegationBondLessDelay = ConstU32<2>; +// /// Rounds before the reward is paid +// type RewardPaymentDelay = ConstU32<2>; +// /// Minimum collators selected per round, default at genesis and minimum forever after +// type MinSelectedCandidates = ConstU32<5>; +// /// Maximum top delegations per candidate +// type MaxTopDelegationsPerCandidate = ConstU32<10>; +// /// Maximum bottom delegations per candidate +// type MaxBottomDelegationsPerCandidate = ConstU32<50>; +// /// Maximum delegations per delegator +// type MaxDelegationsPerDelegator = ConstU32<10>; +// type MinCollatorStk = MinCollatorStk; +// /// Minimum stake required to be reserved to be a candidate +// type MinCandidateStk = ConstU128<{ 500 * DOLLAR }>; +// /// Minimum delegation amount after initial +// type MinDelegation = ConstU128<{ 50 * DOLLAR }>; +// /// Minimum initial stake required to be reserved to be a delegator +// type MinDelegatorStk = ConstU128<{ 50 * DOLLAR }>; +// /// Handler to notify the runtime when a collator is paid +// type OnCollatorPayout = (); +// type PayoutCollatorReward = (); +// /// Handler to notify the runtime when a new round begins +// type OnNewRound = (); +// /// Any additional issuance that should be used for inflation calcs +// type AdditionalIssuance = (); +// type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; +// } pub struct MockDelegatorActions(PhantomData<(T, C)>); impl< - T: Config + pallet::Config + pallet_parachain_staking::Config, + T: Config + pallet::Config, C: frame_support::traits::ReservableCurrency, > pallet_parachain_staking::DelegatorActions> for MockDelegatorActions @@ -259,23 +255,16 @@ impl< Ok(true) } - fn delegator_bond_till_minimum( - delegator: &T::AccountId, - candidate: &T::AccountId, - account_minimum: BalanceOf, - ) -> Result, DispatchErrorWithPostInfo> { - log::error!("delegator_bond_till_minimum AAAAAAA"); - if *candidate != T::AccountId::decode(&mut COLLATOR_ACCOUNT.as_ref()).unwrap() { - log::error!("delegator_bond_till_minimum BBBB"); - return Err(DispatchErrorWithPostInfo::from(>::DelegationDNE)); - } - log::error!("delegator_bond_till_minimum CCCCCC"); + fn is_delegation_exist(delegator: &T::AccountId, candidate: &T::AccountId) -> bool { + let has_delegator = + *delegator == T::AccountId::decode(&mut DELEGATOR_ACCOUNT.as_ref()).unwrap(); + let has_delegation = + *candidate == T::AccountId::decode(&mut COLLATOR_ACCOUNT.as_ref()).unwrap(); + has_delegator && has_delegation + } - let delegation = C::free_balance(&delegator) - .checked_sub(&account_minimum) - .ok_or(>::InsufficientBalance)?; - C::reserve(delegator, delegation)?; - Ok(delegation) + fn get_delegator_stakable_free_balance(delegator: &T::AccountId) -> BalanceOf { + C::free_balance(delegator) } #[cfg(feature = "runtime-benchmarks")] diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 5c0797c11..9b35f0c95 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -16,9 +16,9 @@ // limitations under the License. use crate::{ - mock::*, AccountTasks, Action, ActionOf, AssetPayment, Config, Error, InstructionSequence, - LastTimeSlot, MissedTaskV2Of, ScheduleParam, ScheduledTasksOf, TaskHashInput, TaskOf, - TaskQueueV2, WeightInfo, ERROR_MESSAGE_BALANCE_LOW, ERROR_MESSAGE_DELEGATION_FORMAT, + mock::*, AccountTasks, Action, ActionOf, AssetPayment, Config, DispatchErrorWithDataMap, Error, + InstructionSequence, LastTimeSlot, MissedTaskV2Of, ScheduleParam, ScheduledTasksOf, + TaskHashInput, TaskOf, TaskQueueV2, WeightInfo, }; use codec::Encode; use frame_support::{ @@ -28,7 +28,6 @@ use frame_support::{ weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, }; use frame_system::{self, RawOrigin}; -use hex; use rand::Rng; use sp_core::Get; use sp_runtime::{ @@ -36,8 +35,8 @@ use sp_runtime::{ AccountId32, }; use xcm::latest::{prelude::*, Junction::Parachain, MultiLocation}; -use sp_runtime::DispatchError::Module; -use sp_runtime::ModuleError; +// use sp_runtime::DispatchError::Module; +// use sp_runtime::ModuleError; use frame_support::pallet_prelude::DispatchError; use sp_std::collections::btree_map::BTreeMap; @@ -378,8 +377,6 @@ fn will_emit_task_completed_event_when_task_completed() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let frequency = 3_600; let account_id = AccountId32::new(ALICE); - let provided_id = vec![1, 2]; - let task_id = AutomationTime::generate_task_id(account_id.clone(), provided_id.clone()); fund_account(&account_id, 900_000_000, 2, Some(0)); @@ -487,11 +484,9 @@ fn will_emit_task_completed_event_when_task_failed() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let frequency = 3_600; let account_id = AccountId32::new(ALICE); - let provided_id = vec![1, 2]; - let task_id = AutomationTime::generate_task_id(account_id.clone(), provided_id.clone()); fund_account(&account_id, 900_000_000, 2, Some(0)); - let current_funds = Balances::free_balance(AccountId32::new(ALICE)); + let current_funds = Balances::free_balance(account_id.clone()); // Because the execution of the transfer task twice requires a total amount is larger than current balance, the second task will fail. let call: ::RuntimeCall = pallet_balances::Call::transfer { @@ -531,14 +526,8 @@ fn will_emit_task_completed_event_when_task_failed() { AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000)); let my_events = events(); - // The DynamicDispatchResult event with error should be emitted when task failed. - // let event = my_events.clone().into_iter().find(|e| { - // matches!(e, RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { result, .. }) if result.is_err()) - // }) - // .expect("The DynamicDispatchResult event with error should be emitted when task failed"); - // When a task fails, the TaskCompleted event will still be emitted. - let event = my_events + my_events .into_iter() .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. }))) .expect("When a task fails, the TaskCompleted event will still be emitted"); @@ -1182,7 +1171,8 @@ fn schedule_time_slot_full_rolls_back() { let call1: RuntimeCall = frame_system::Call::remark { remark: vec![2, 4, 5] }.into(); assert_ok!(fund_account_dynamic_dispatch(&AccountId32::new(ALICE), 1, call1.encode())); - let (_, task_id1) = schedule_task(ALICE, vec![40], vec![SCHEDULED_TIME + 7200], vec![2, 4, 5]); + let (_, task_id1) = + schedule_task(ALICE, vec![40], vec![SCHEDULED_TIME + 7200], vec![2, 4, 5]); let call2: RuntimeCall = frame_system::Call::remark { remark: vec![2, 4] }.into(); assert_ok!(fund_account_dynamic_dispatch(&AccountId32::new(ALICE), 1, call1.encode())); @@ -1626,7 +1616,6 @@ mod extrinsics { mod run_dynamic_dispatch_action { use super::*; - use sp_runtime::DispatchError; #[test] fn cannot_decode() { @@ -1808,14 +1797,16 @@ fn trigger_tasks_handles_missed_slots() { assert_eq!(AutomationTime::get_missed_queue().len(), 0); - let (_, missed_task_id) = schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME - 3600], vec![50]); + let (_, missed_task_id) = + schedule_task(ALICE, vec![50], vec![SCHEDULED_TIME - 3600], vec![50]); let missed_task = MissedTaskV2Of::::new( AccountId32::new(ALICE), missed_task_id.clone(), SCHEDULED_TIME - 3600, ); - let (call, task_will_be_run_id) = schedule_task(ALICE, vec![59], vec![SCHEDULED_TIME], vec![50]); + let (call, task_will_be_run_id) = + schedule_task(ALICE, vec![59], vec![SCHEDULED_TIME], vec![50]); let (_, scheduled_task_id) = schedule_task(ALICE, vec![60], vec![SCHEDULED_TIME], vec![50]); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); @@ -2411,10 +2402,7 @@ fn trigger_tasks_completes_some_xcmp_tasks() { encoded_call, cancel_upon_errors: vec![], }), - RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: owner, - task_id, - }) + RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner, task_id }) ] ); }) @@ -2423,17 +2411,18 @@ fn trigger_tasks_completes_some_xcmp_tasks() { #[test] fn trigger_tasks_completes_auto_compound_delegated_stake_task() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - get_funds(AccountId32::new(ALICE)); - let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + let delegator = AccountId32::new(DELEGATOR_ACCOUNT); + get_funds(delegator.clone()); + let before_balance = Balances::free_balance(delegator.clone()); let account_minimum = before_balance / 2; - let task_id = add_recurring_task_to_task_queue( - ALICE, + add_recurring_task_to_task_queue( + DELEGATOR_ACCOUNT, vec![1], SCHEDULED_TIME, 3600, Action::AutoCompoundDelegatedStake { - delegator: AccountId32::new(ALICE), + delegator: delegator.clone(), collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, @@ -2444,29 +2433,9 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - let new_balance = Balances::free_balance(AccountId32::new(ALICE)); + let new_balance = Balances::free_balance(delegator.clone()); assert!(new_balance < before_balance); assert_eq!(new_balance, account_minimum); - // let delegation_event = events() - // .into_iter() - // .find(|e| match e { - // RuntimeEvent::AutomationTime( - // crate::Event::AutoCompoundDelegatorStakeSucceeded { .. }, - // ) => true, - // _ => false, - // }) - // .expect("AutoCompound success event should have been emitted"); - let execution_weight = MockWeight::::run_auto_compound_delegated_stake_task(); - let fee = ExecutionWeightFee::get().saturating_mul(execution_weight.ref_time().into()); - // assert_eq!( - // delegation_event, - // RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeSucceeded { - // task_id, - // amount: before_balance - // .checked_sub(account_minimum.saturating_add(fee)) - // .expect("Event should not exist if value is neg"), - // }) - // ); }) } @@ -2475,25 +2444,26 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { // 1. User's wallet balance >= minimum balance + execution fee // 2. User has a delegation with the specificed collator // Expected result: -// 1. Current execution will run and emit AutoCompoundDelegatorStakeSucceeded event +// 1. Current execution will run // 2. Next execution will be scheduled -// 3. The task will re-run in the next execution time and emit AutoCompoundDelegatorStakeSucceeded event again +// 3. The task will re-run in the next execution time #[test] fn auto_compound_delegated_stake_enough_balance_has_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - get_funds(AccountId32::new(ALICE)); - let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + let delegator = AccountId32::new(DELEGATOR_ACCOUNT); + get_funds(delegator.clone()); + let before_balance = Balances::free_balance(delegator.clone()); // Minimum balance is half of the user's wallet balance let account_minimum = before_balance / 2; let frequency = 3_600; let task_id = add_recurring_task_to_task_queue( - ALICE, + DELEGATOR_ACCOUNT, vec![1], SCHEDULED_TIME, frequency, Action::AutoCompoundDelegatedStake { - delegator: AccountId32::new(ALICE), + delegator: delegator.clone(), collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, @@ -2506,56 +2476,39 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { let emitted_events = events(); // // Expected result: - // // 1. Current execution will run and emit AutoCompoundDelegatorStakeSucceeded event - // emitted_events - // .clone() - // .into_iter() - // .find(|e| { - // matches!( - // e, - // RuntimeEvent::AutomationTime( - // crate::Event::AutoCompoundDelegatorStakeSucceeded { .. } - // ) - // ) - // }) - // .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted"); - - // // 2. Next execution will be scheduled - // emitted_events - // .clone() - // .into_iter() - // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }))) - // .expect("TaskScheduled event should have been emitted"); + // // 1. Current execution will run + + // 2. Next execution will be scheduled + emitted_events + .clone() + .into_iter() + .find(|e| { + matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { .. })) + }) + .expect("TaskRescheduled event should have been emitted"); let next_scheduled_time = SCHEDULED_TIME + frequency; AutomationTime::get_scheduled_tasks(next_scheduled_time) .expect("Task should have been rescheduled") .tasks .into_iter() - .find(|t| *t == (AccountId32::new(ALICE), task_id)) + .find(|t| *t == (delegator.clone(), task_id)) .expect("Task should have been rescheduled"); - let task = AutomationTime::get_account_task(AccountId32::new(ALICE), task_id) + let task = AutomationTime::get_account_task(delegator.clone(), task_id) .expect("Task should not have been removed from task map"); assert_eq!(task.schedule.known_executions_left(), 1); assert_eq!(task.execution_times(), vec![next_scheduled_time]); // 3. The task will re-run in the next execution time Timestamp::set_timestamp(next_scheduled_time * 1_000); - get_funds(AccountId32::new(ALICE)); + get_funds(delegator.clone()); System::reset_events(); AutomationTime::trigger_tasks(Weight::from_ref_time(100_000_000_000)); - // events() - // .into_iter() - // .find(|e| { - // matches!( - // e, - // RuntimeEvent::AutomationTime( - // crate::Event::AutoCompoundDelegatorStakeSucceeded { .. } - // ) - // ) - // }) - // .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted again!"); + events() + .into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { .. }))) + .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted again!"); }) } @@ -2569,19 +2522,20 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { #[test] fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - get_funds(AccountId32::new(ALICE)); - let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + let delegator = AccountId32::new(DELEGATOR_ACCOUNT); + get_funds(delegator.clone()); + let before_balance = Balances::free_balance(delegator.clone()); // Minimum balance is twice of the user's wallet balance let account_minimum = before_balance * 2; let frequency = 3_600; let task_id = add_recurring_task_to_task_queue( - ALICE, + DELEGATOR_ACCOUNT, vec![1], SCHEDULED_TIME, frequency, Action::AutoCompoundDelegatedStake { - delegator: AccountId32::new(ALICE), + delegator: delegator.clone(), collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, @@ -2595,8 +2549,8 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { // Expected result: // 1. Emit TaskExecutionFailed event with error: InsufficientBalance - let insufficient_balance_error: DispatchError = >::InsufficientBalance.into(); - let event = emitted_events.clone().into_iter() + let insufficient_balance_error: DispatchError = Error::::InsufficientBalance.into(); + emitted_events.clone().into_iter() .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { error, .. }) if *error == insufficient_balance_error )).expect("TaskExecutionFailed event should have been emitted"); // 2. Next execution will be scheduled @@ -2610,9 +2564,9 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { .expect("Task should have been rescheduled") .tasks .into_iter() - .find(|t| *t == (AccountId32::new(ALICE), task_id)) + .find(|t| *t == (delegator.clone(), task_id)) .expect("Task should have been rescheduled"); - let task = AutomationTime::get_account_task(AccountId32::new(ALICE), task_id) + let task = AutomationTime::get_account_task(delegator.clone(), task_id) .expect("Task should not have been removed from task map"); assert_eq!(task.schedule.known_executions_left(), 1); assert_eq!(task.execution_times(), vec![next_scheduled_time]); @@ -2629,8 +2583,9 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { #[test] fn auto_compound_delegated_stake_enough_balance_no_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - get_funds(AccountId32::new(ALICE)); - let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + let delegator = AccountId32::new(DELEGATOR_ACCOUNT); + get_funds(delegator.clone()); + let before_balance = Balances::free_balance(delegator.clone()); // Minimum balance is half of the user's wallet balance let account_minimum = before_balance / 2; let frequency = 3_600; @@ -2641,7 +2596,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { SCHEDULED_TIME, frequency, Action::AutoCompoundDelegatedStake { - delegator: AccountId32::new(ALICE), + delegator: delegator.clone(), collator: AccountId32::new(BOB), account_minimum, }, @@ -2651,20 +2606,21 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - // // Expected result: - // // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound - // events() - // .into_iter() - // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { error, .. }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound))) - // .expect("AutoCompound failure event should have been emitted"); + // Expected result: + // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationDNE + let delegation_error: DispatchError = Error::::DelegationNotFound.into(); + events() + .into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { error, .. }) if error.error == delegation_error)) + .expect("AutoCompoundDelegatorStakeFailed event should have been emitted"); - // // 2. Next execution will not be scheduled - // assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) - // .filter(|scheduled| { - // scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id)) - // }) - // .is_none()); - // assert!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id).is_none()); + // 2. Next execution will not be scheduled + assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) + .filter(|scheduled| { + scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id)) + }) + .is_none()); + assert!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id).is_none()); }) } @@ -2678,7 +2634,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { #[test] fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - let delegator = AccountId32::new(ALICE); + let delegator = AccountId32::new(DELEGATOR_ACCOUNT); let collator = AccountId32::new(BOB); get_funds(delegator.clone()); let before_balance = Balances::free_balance(AccountId32::new(ALICE)); @@ -2701,36 +2657,32 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { System::reset_events(); AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + let emit_events = events(); // Expected result: - // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound - // let failed_error_message = format!(ERROR_MESSAGE_DELEGATION_FORMAT!(), hex::encode(&delegator), hex::encode(&collator)); - // events() - // .into_iter() - // .find(|e| { - // matches!(e, - // RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { - // error_message, - // error, - // .. - // }) if *error == sp_runtime::DispatchErrorWithPostInfo::from(Error::::DelegationNotFound) && *error_message == failed_error_message.as_bytes().to_vec()) - // }) - // .expect("AutoCompound failure event should have been emitted"); - - let delegation_dne_error: DispatchError = >::DelegationDNE.into(); - - let emit_events = events(); + // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationDNE + let delegation_error: DispatchError = Error::::DelegationNotFound.into(); + emit_events.clone() + .into_iter() + .find(|e| { + matches!(e, + RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { + error: DispatchErrorWithDataMap { error, .. }, + .. + }) if *error == delegation_error.clone()) + }) + .expect("AutoCompoundDelegatorStakeFailed event should have been emitted"); - let event = emit_events.into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { error, .. }) if *error == delegation_dne_error )).expect("TaskExecutionFailed event should have been emitted"); + emit_events.into_iter() + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { error, .. }) if *error == delegation_error )).expect("TaskExecutionFailed event should have been emitted"); // 2. Next execution will not be scheduled - // assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) - // .filter(|scheduled| { - // scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id)) - // }) - // .is_none()); - // assert!(AutomationTime::get_account_task(delegator.clone(), task_id).is_none()); + assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) + .filter(|scheduled| { + scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id)) + }) + .is_none()); + assert!(AutomationTime::get_account_task(delegator.clone(), task_id).is_none()); }) } @@ -2816,7 +2768,6 @@ fn trigger_tasks_removes_completed_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - let mut condition: BTreeMap = BTreeMap::new(); condition.insert(String::from("type"), String::from("time")); condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); @@ -2892,7 +2843,7 @@ fn on_init_runs_tasks() { RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { who: owner.clone(), task_id: task_id2.clone(), - condition: condition, + condition, encoded_call: vec![], cancel_upon_errors: vec![], }), diff --git a/pallets/vesting/Cargo.toml b/pallets/vesting/Cargo.toml index 4788b607a..1b7b1f7e5 100644 --- a/pallets/vesting/Cargo.toml +++ b/pallets/vesting/Cargo.toml @@ -34,7 +34,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", default-featur pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } ## Moonbeam dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } diff --git a/runtime/neumann/Cargo.toml b/runtime/neumann/Cargo.toml index 4b404cf6c..7e6f710ba 100644 --- a/runtime/neumann/Cargo.toml +++ b/runtime/neumann/Cargo.toml @@ -96,7 +96,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/runtime/oak/Cargo.toml b/runtime/oak/Cargo.toml index a2e5744d1..dd26f96fe 100644 --- a/runtime/oak/Cargo.toml +++ b/runtime/oak/Cargo.toml @@ -102,7 +102,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/runtime/turing/Cargo.toml b/runtime/turing/Cargo.toml index fa3bdeb96..367c702c3 100644 --- a/runtime/turing/Cargo.toml +++ b/runtime/turing/Cargo.toml @@ -102,7 +102,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.38" } # Moonbeam Dependencies -pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-polkadot-v0.9.38" } +pallet-parachain-staking = { git = "https://github.com/OAK-Foundation/moonbeam", default-features = false, branch = "oak-staging" } # ORML Dependencies orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.38" } From 707c7cb91c932ceafc4a86e882e5864156251914 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Fri, 28 Jul 2023 09:59:03 +0000 Subject: [PATCH 16/37] fixup: auto format Rust code --- pallets/automation-time/src/lib.rs | 8 +++----- pallets/automation-time/src/mock.rs | 6 +----- pallets/automation-time/src/tests.rs | 8 ++++++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 6532b6a18..3ffcff6a2 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -53,7 +53,7 @@ use codec::Decode; use core::convert::TryInto; use cumulus_primitives_core::ParaId; use frame_support::{ - dispatch::{GetDispatchInfo, PostDispatchInfo}, + dispatch::{DispatchErrorWithPostInfo, GetDispatchInfo, PostDispatchInfo}, pallet_prelude::*, sp_runtime::traits::{CheckedSub, Hash}, storage::{ @@ -81,7 +81,6 @@ use sp_runtime::{ use sp_std::{boxed::Box, collections::btree_map::BTreeMap, vec, vec::Vec}; pub use weights::WeightInfo; use xcm::{latest::prelude::*, VersionedMultiLocation}; -use frame_support::dispatch::DispatchErrorWithPostInfo; #[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)] pub struct DispatchErrorDataMap(BTreeMap); @@ -1173,12 +1172,11 @@ pub mod pallet { ::WeightInfo::run_auto_compound_delegated_stake_task(), None, ), - Err(e) => { + Err(e) => return ( ::WeightInfo::run_auto_compound_delegated_stake_task(), Some(e), - ) - }, + ), } }, None => { diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 7ad703f4a..bef67b42a 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -531,11 +531,7 @@ pub fn new_test_ext(state_block_time: u64) -> sp_io::TestExternalities { // A function to support test scheduleing a Fixed schedule // We don't focus on making sure the execution run properly. We just focus on // making sure a task is scheduled into the queue -pub fn schedule_task( - owner: [u8; 32], - scheduled_times: Vec, - message: Vec, -) -> TaskIdV2 { +pub fn schedule_task(owner: [u8; 32], scheduled_times: Vec, message: Vec) -> TaskIdV2 { let call: RuntimeCall = frame_system::Call::remark_with_event { remark: message }.into(); let task_id = schedule_dynamic_dispatch_task(owner, scheduled_times, call.encode()); task_id diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 043fab729..39b08c653 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -1477,7 +1477,11 @@ fn cancel_works_for_an_executed_task() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let owner = AccountId32::new(ALICE); let call: RuntimeCall = frame_system::Call::remark_with_event { remark: vec![50] }.into(); - let task_id1 = schedule_dynamic_dispatch_task(ALICE, vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600], call.encode()); + let task_id1 = schedule_dynamic_dispatch_task( + ALICE, + vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600], + call.encode(), + ); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); LastTimeSlot::::put((SCHEDULED_TIME - 3600, SCHEDULED_TIME - 3600)); System::reset_events(); @@ -2816,7 +2820,7 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { // }) if *error == delegation_error.clone()) // }) // .expect("AutoCompoundDelegatorStakeFailed event should have been emitted"); - + // emit_events.into_iter() // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { error, .. }) if *error == delegation_error )).expect("TaskExecutionFailed event should have been emitted"); From 2c84a6fdabd7207afc1b9776e580e2fdbb611a96 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Fri, 28 Jul 2023 22:17:22 +0800 Subject: [PATCH 17/37] Rename cancel_upon_errors to abort_errors --- pallets/automation-time/src/lib.rs | 16 +++++----- .../src/migrations/update_xcmp_task.rs | 2 +- .../automation-time/src/migrations/utils.rs | 2 +- pallets/automation-time/src/tests.rs | 32 +++++++++---------- pallets/automation-time/src/types.rs | 18 +++++------ 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 3ffcff6a2..e97dd7f91 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -93,7 +93,7 @@ impl sp_runtime::traits::Printable for DispatchErrorDataMap { } pub type DispatchErrorWithDataMap = DispatchErrorWithData; -const AUTO_COMPOUND_DELEGATION_CANCEL_UPON_ERRORS: [&str; 1] = ["DelegationNotFound"]; +const AUTO_COMPOUND_DELEGATION_abort_errors: [&str; 1] = ["DelegationNotFound"]; #[frame_support::pallet] pub mod pallet { @@ -369,7 +369,7 @@ pub mod pallet { task_id: TaskIdV2, condition: BTreeMap, encoded_call: Vec, - cancel_upon_errors: Vec, + abort_errors: Vec, }, TaskExecutionFailed { who: AccountOf, @@ -549,7 +549,7 @@ pub mod pallet { }; let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; - let errors: Vec = AUTO_COMPOUND_DELEGATION_CANCEL_UPON_ERRORS + let errors: Vec = AUTO_COMPOUND_DELEGATION_abort_errors .iter() .map(|&error| String::from(error)) .collect(); @@ -946,7 +946,7 @@ pub mod pallet { task_id: task_id.clone(), condition, encoded_call, - cancel_upon_errors: task.cancel_upon_errors.clone(), + abort_errors: task.abort_errors.clone(), }); let (task_action_weight, dispatch_error) = match task.action.clone() { @@ -1411,7 +1411,7 @@ pub mod pallet { action: ActionOf, owner_id: AccountOf, schedule: Schedule, - cancel_upon_errors: Vec, + abort_errors: Vec, ) -> DispatchResult { match action.clone() { Action::XCMP { execution_fee, instruction_sequence, .. } => { @@ -1441,7 +1441,7 @@ pub mod pallet { Self::generate_task_idv2(), schedule, action.clone(), - cancel_upon_errors, + abort_errors, ); let task_id = @@ -1466,10 +1466,10 @@ pub mod pallet { mut task: TaskOf, dispatch_error: Option, ) { - // When the error can be found in the cancel_upon_errors list, the next task execution will not be scheduled. Otherwise, continue to execute the next task. + // When the error can be found in the abort_errors list, the next task execution will not be scheduled. Otherwise, continue to execute the next task. match dispatch_error { Some(err) - if task.cancel_upon_errors.contains(&String::from(Into::<&str>::into(err))) => + if task.abort_errors.contains(&String::from(Into::<&str>::into(err))) => { Self::deposit_event(Event::::TaskNotRescheduled { who: task.owner_id.clone(), diff --git a/pallets/automation-time/src/migrations/update_xcmp_task.rs b/pallets/automation-time/src/migrations/update_xcmp_task.rs index 26a7c0a96..37e8fce34 100644 --- a/pallets/automation-time/src/migrations/update_xcmp_task.rs +++ b/pallets/automation-time/src/migrations/update_xcmp_task.rs @@ -181,7 +181,7 @@ mod test { schedule_as, instruction_sequence: InstructionSequence::PayThroughSovereignAccount, }, - cancel_upon_errors: vec![], + abort_errors: vec![], } ); }) diff --git a/pallets/automation-time/src/migrations/utils.rs b/pallets/automation-time/src/migrations/utils.rs index c554145a4..5efd49086 100644 --- a/pallets/automation-time/src/migrations/utils.rs +++ b/pallets/automation-time/src/migrations/utils.rs @@ -53,7 +53,7 @@ impl From> for TaskOf { task_id: deprecate::old_taskid_to_idv2::(&old_task_id), schedule: task.schedule, action: task.action.into(), - cancel_upon_errors: vec![], + abort_errors: vec![], } } } diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 39b08c653..639cb43c9 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -342,7 +342,7 @@ fn schedule_transfer_with_dynamic_dispatch() { task_id: task_id.clone(), condition, encoded_call: call.encode(), - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::System(frame_system::Event::NewAccount { account: recipient.clone() @@ -1528,7 +1528,7 @@ fn cancel_works_for_an_executed_task() { task_id: task_id1.clone(), condition, encoded_call: call.encode(), - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), @@ -1973,7 +1973,7 @@ fn trigger_tasks_handles_missed_slots() { task_id: task_will_be_run_id.clone(), condition, encoded_call: call.encode(), - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: AccountId32::new(ALICE), @@ -2053,7 +2053,7 @@ fn trigger_tasks_limits_missed_slots() { task_id: task_id.clone(), condition: condition.clone(), encoded_call: call.encode(), - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), @@ -2161,7 +2161,7 @@ fn trigger_tasks_completes_all_tasks() { task_id: task_id1.clone(), condition: condition.clone(), encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -2173,7 +2173,7 @@ fn trigger_tasks_completes_all_tasks() { task_id: task_id2.clone(), condition, encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -2244,7 +2244,7 @@ fn trigger_tasks_completes_some_tasks() { task_id: task_id1.clone(), condition, encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -2436,7 +2436,7 @@ fn missed_tasks_removes_completed_tasks() { task_id: task_id01.clone(), condition: condition.clone(), encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one }), RuntimeEvent::AutomationTime(crate::Event::TaskMissed { @@ -2876,7 +2876,7 @@ fn trigger_tasks_updates_executions_left() { task_id: task_id01.clone(), condition, encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), ] @@ -2930,7 +2930,7 @@ fn trigger_tasks_removes_completed_tasks() { task_id: task_id01.clone(), condition, encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -2983,7 +2983,7 @@ fn on_init_runs_tasks() { task_id: task_id1.clone(), condition: condition.clone(), encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -2995,7 +2995,7 @@ fn on_init_runs_tasks() { task_id: task_id2.clone(), condition, encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -3067,7 +3067,7 @@ fn on_init_check_task_queue() { task_id: tasks[0].clone(), condition: condition.clone(), encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![0] }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -3079,7 +3079,7 @@ fn on_init_check_task_queue() { task_id: tasks[1].clone(), condition: condition.clone(), encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![1] }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -3101,7 +3101,7 @@ fn on_init_check_task_queue() { task_id: tasks[2].clone(), condition: condition.clone(), encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![2] }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { @@ -3113,7 +3113,7 @@ fn on_init_check_task_queue() { task_id: tasks[3].clone(), condition: condition.clone(), encoded_call: vec![], - cancel_upon_errors: vec![], + abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![3] }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { diff --git a/pallets/automation-time/src/types.rs b/pallets/automation-time/src/types.rs index 4814cfb48..238835a22 100644 --- a/pallets/automation-time/src/types.rs +++ b/pallets/automation-time/src/types.rs @@ -214,7 +214,7 @@ pub struct Task { pub task_id: Vec, pub schedule: Schedule, pub action: Action, - pub cancel_upon_errors: Vec, + pub abort_errors: Vec, } impl PartialEq for Task { @@ -234,9 +234,9 @@ impl Task { task_id: Vec, schedule: Schedule, action: Action, - cancel_upon_errors: Vec, + abort_errors: Vec, ) -> Self { - Self { owner_id, task_id, schedule, action, cancel_upon_errors } + Self { owner_id, task_id, schedule, action, abort_errors } } pub fn create_event_task( @@ -244,13 +244,13 @@ impl Task { task_id: Vec, execution_times: Vec, message: Vec, - cancel_upon_errors: Vec, + abort_errors: Vec, ) -> Result { let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: message }.into(); let action = Action::DynamicDispatch { encoded_call: call.encode() }; let schedule = Schedule::new_fixed_schedule::(execution_times)?; - Ok(Self::new(owner_id, task_id, schedule, action, cancel_upon_errors)) + Ok(Self::new(owner_id, task_id, schedule, action, abort_errors)) } pub fn create_xcmp_task( @@ -264,7 +264,7 @@ impl Task { encoded_call_weight: Weight, overall_weight: Weight, instruction_sequence: InstructionSequence, - cancel_upon_errors: Vec, + abort_errors: Vec, ) -> Result { let destination = MultiLocation::try_from(destination).map_err(|_| Error::::BadVersion)?; @@ -279,7 +279,7 @@ impl Task { instruction_sequence, }; let schedule = Schedule::new_fixed_schedule::(execution_times)?; - Ok(Self::new(owner_id, task_id, schedule, action, cancel_upon_errors)) + Ok(Self::new(owner_id, task_id, schedule, action, abort_errors)) } pub fn create_auto_compound_delegated_stake_task( @@ -289,7 +289,7 @@ impl Task { frequency: Seconds, collator_id: AccountId, account_minimum: Balance, - cancel_upon_errors: Vec, + abort_errors: Vec, ) -> Result { let action = Action::AutoCompoundDelegatedStake { delegator: owner_id.clone(), @@ -297,7 +297,7 @@ impl Task { account_minimum, }; let schedule = Schedule::new_recurring_schedule::(next_execution_time, frequency)?; - Ok(Self::new(owner_id, task_id, schedule, action, cancel_upon_errors)) + Ok(Self::new(owner_id, task_id, schedule, action, abort_errors)) } pub fn execution_times(&self) -> Vec { From 1b02d36301c9a53cd5c88eed63567b4a9ed5b62a Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Fri, 28 Jul 2023 14:19:08 +0000 Subject: [PATCH 18/37] fixup: auto format Rust code --- pallets/automation-time/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index e97dd7f91..007bcf71a 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -1468,9 +1468,7 @@ pub mod pallet { ) { // When the error can be found in the abort_errors list, the next task execution will not be scheduled. Otherwise, continue to execute the next task. match dispatch_error { - Some(err) - if task.abort_errors.contains(&String::from(Into::<&str>::into(err))) => - { + Some(err) if task.abort_errors.contains(&String::from(Into::<&str>::into(err))) => { Self::deposit_event(Event::::TaskNotRescheduled { who: task.owner_id.clone(), task_id: task_id.clone(), From 8d3462ce92d62b8357c8edec260582e17688087e Mon Sep 17 00:00:00 2001 From: imstar15 Date: Sat, 29 Jul 2023 02:02:22 +0800 Subject: [PATCH 19/37] Fix tests --- Cargo.lock | 1 + pallets/automation-time/Cargo.toml | 1 + pallets/automation-time/src/mock.rs | 7 +++---- pallets/automation-time/src/tests.rs | 30 ++++++++++++++++++---------- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46bc48e04..3b39f4d08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5935,6 +5935,7 @@ version = "1.0.0" dependencies = [ "cumulus-pallet-xcm", "cumulus-primitives-core", + "env_logger", "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", "frame-system 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", diff --git a/pallets/automation-time/Cargo.toml b/pallets/automation-time/Cargo.toml index 6ff71f011..dfa7234b6 100644 --- a/pallets/automation-time/Cargo.toml +++ b/pallets/automation-time/Cargo.toml @@ -63,6 +63,7 @@ pallet-xcmp-handler = { path = "../xcmp-handler", default-features = false } primitives = { path = "../../primitives", default-features = false } [dev-dependencies] +env_logger = "0.9" rand = { version = "0.7.3" } serde = { version = "1.0.144" } sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index bef67b42a..5b7482030 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -533,19 +533,18 @@ pub fn new_test_ext(state_block_time: u64) -> sp_io::TestExternalities { // making sure a task is scheduled into the queue pub fn schedule_task(owner: [u8; 32], scheduled_times: Vec, message: Vec) -> TaskIdV2 { let call: RuntimeCall = frame_system::Call::remark_with_event { remark: message }.into(); - let task_id = schedule_dynamic_dispatch_task(owner, scheduled_times, call.encode()); + let task_id = schedule_dynamic_dispatch_task(owner, scheduled_times, call); task_id } pub fn schedule_dynamic_dispatch_task( owner: [u8; 32], scheduled_times: Vec, - encoded_call: Vec, + call: RuntimeCall, ) -> TaskIdV2 { let account_id = AccountId32::new(owner); - let call: RuntimeCall = frame_system::Call::remark_with_event { remark: vec![50] }.into(); - assert_ok!(fund_account_dynamic_dispatch(&account_id, scheduled_times.len(), encoded_call)); + assert_ok!(fund_account_dynamic_dispatch(&account_id, scheduled_times.len(), call.clone().encode())); assert_ok!(AutomationTime::schedule_dynamic_dispatch_task( RuntimeOrigin::signed(account_id.clone()), diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 639cb43c9..a0b5a9f25 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -1480,7 +1480,7 @@ fn cancel_works_for_an_executed_task() { let task_id1 = schedule_dynamic_dispatch_task( ALICE, vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600], - call.encode(), + call.clone(), ); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); LastTimeSlot::::put((SCHEDULED_TIME - 3600, SCHEDULED_TIME - 3600)); @@ -1943,7 +1943,10 @@ fn trigger_tasks_handles_missed_slots() { SCHEDULED_TIME - 3600, ); - let task_will_be_run_id = schedule_task(ALICE, vec![SCHEDULED_TIME], vec![50]); + let remark_message = vec![50]; + let call: ::RuntimeCall = + frame_system::Call::remark_with_event { remark: remark_message.clone() }.into(); + let task_will_be_run_id = schedule_dynamic_dispatch_task(ALICE, vec![SCHEDULED_TIME], call.clone()); let scheduled_task_id = schedule_task(ALICE, vec![SCHEDULED_TIME], vec![50]); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); @@ -1977,7 +1980,7 @@ fn trigger_tasks_handles_missed_slots() { }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: AccountId32::new(ALICE), - hash: BlakeTwo256::hash(&vec![50]), + hash: BlakeTwo256::hash(&remark_message), }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: AccountId32::new(ALICE), @@ -2003,6 +2006,7 @@ fn trigger_tasks_handles_missed_slots() { #[test] fn trigger_tasks_limits_missed_slots() { new_test_ext(START_BLOCK_TIME).execute_with(|| { + let _ = env_logger::try_init(); let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: vec![50] }.into(); @@ -2010,7 +2014,7 @@ fn trigger_tasks_limits_missed_slots() { ALICE, vec![40], vec![SCHEDULED_TIME], - Action::DynamicDispatch { encoded_call: call.encode() }, + Action::DynamicDispatch { encoded_call: call.clone().encode() }, ); assert_eq!(AutomationTime::get_missed_queue().len(), 0); @@ -2023,7 +2027,10 @@ fn trigger_tasks_limits_missed_slots() { let missing_task_id4 = schedule_task(ALICE, vec![SCHEDULED_TIME - 14400], vec![50]); let missing_task_id5 = schedule_task(ALICE, vec![SCHEDULED_TIME - 18000], vec![50]); - let task_id = schedule_task(ALICE, vec![SCHEDULED_TIME], vec![32]); + let remark_message = vec![50]; + let call: ::RuntimeCall = + frame_system::Call::remark_with_event { remark: remark_message.clone() }.into(); + let task_id = schedule_dynamic_dispatch_task(ALICE, vec![SCHEDULED_TIME], call.clone()); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); LastTimeSlot::::put((SCHEDULED_TIME - 25200, SCHEDULED_TIME - 25200)); @@ -2057,7 +2064,7 @@ fn trigger_tasks_limits_missed_slots() { }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), - hash: BlakeTwo256::hash(&vec![32]), + hash: BlakeTwo256::hash(&remark_message), }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), @@ -2532,10 +2539,13 @@ fn trigger_tasks_completes_some_xcmp_tasks() { assert_eq!( events(), [ - // RuntimeEvent::AutomationTime(crate::Event::XcmpTaskSucceeded { - // destination, - // task_id: task_id.clone(), - // }), + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: owner.clone(), + task_id: task_id.clone(), + condition, + encoded_call, + abort_errors: vec![], + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner, task_id }) ] ); From 938ec970dec24cfc278bc26468bafbd6d3be4385 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Fri, 28 Jul 2023 18:04:01 +0000 Subject: [PATCH 20/37] fixup: auto format Rust code --- pallets/automation-time/src/mock.rs | 6 +++++- pallets/automation-time/src/tests.rs | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 5b7482030..c758bf33a 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -544,7 +544,11 @@ pub fn schedule_dynamic_dispatch_task( ) -> TaskIdV2 { let account_id = AccountId32::new(owner); - assert_ok!(fund_account_dynamic_dispatch(&account_id, scheduled_times.len(), call.clone().encode())); + assert_ok!(fund_account_dynamic_dispatch( + &account_id, + scheduled_times.len(), + call.clone().encode() + )); assert_ok!(AutomationTime::schedule_dynamic_dispatch_task( RuntimeOrigin::signed(account_id.clone()), diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index a0b5a9f25..bf5f0c303 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -1946,7 +1946,8 @@ fn trigger_tasks_handles_missed_slots() { let remark_message = vec![50]; let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: remark_message.clone() }.into(); - let task_will_be_run_id = schedule_dynamic_dispatch_task(ALICE, vec![SCHEDULED_TIME], call.clone()); + let task_will_be_run_id = + schedule_dynamic_dispatch_task(ALICE, vec![SCHEDULED_TIME], call.clone()); let scheduled_task_id = schedule_task(ALICE, vec![SCHEDULED_TIME], vec![50]); Timestamp::set_timestamp(SCHEDULED_TIME * 1_000); From a8167bfefb81dc2d55e2535ba92d6f468b9fc907 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Mon, 31 Jul 2023 15:26:30 +0800 Subject: [PATCH 21/37] Add TaskExecuted event --- pallets/automation-time/src/lib.rs | 42 ++-- pallets/automation-time/src/mock.rs | 120 +++++----- pallets/automation-time/src/tests.rs | 317 +++++++++++++++++++++------ 3 files changed, 346 insertions(+), 133 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 007bcf71a..0320fff60 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -93,7 +93,7 @@ impl sp_runtime::traits::Printable for DispatchErrorDataMap { } pub type DispatchErrorWithDataMap = DispatchErrorWithData; -const AUTO_COMPOUND_DELEGATION_abort_errors: [&str; 1] = ["DelegationNotFound"]; +const AUTO_COMPOUND_DELEGATION_ABORT_ERRORS: [&str; 2] = ["DelegatorDNE", "DelegationDNE"]; #[frame_support::pallet] pub mod pallet { @@ -280,8 +280,6 @@ pub mod pallet { BadVersion, UnsupportedFeePayment, CannotReanchor, - // Delegation Not Found - DelegationNotFound, } #[pallet::event] @@ -371,6 +369,10 @@ pub mod pallet { encoded_call: Vec, abort_errors: Vec, }, + TaskExecuted { + who: AccountOf, + task_id: TaskIdV2, + }, TaskExecutionFailed { who: AccountOf, task_id: TaskIdV2, @@ -549,7 +551,7 @@ pub mod pallet { }; let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; - let errors: Vec = AUTO_COMPOUND_DELEGATION_abort_errors + let errors: Vec = AUTO_COMPOUND_DELEGATION_ABORT_ERRORS .iter() .map(|&error| String::from(error)) .collect(); @@ -995,6 +997,22 @@ pub mod pallet { task_id.clone(), ), }; + + // If an error occurs during the task execution process, the TaskExecutionFailed event will be emitted; + // Otherwise, the TaskExecuted event will be thrown. + if let Some(err) = dispatch_error { + Self::deposit_event(Event::::TaskExecutionFailed { + who: task.owner_id.clone(), + task_id: task_id.clone(), + error: err, + }); + } else { + Self::deposit_event(Event::::TaskExecuted { + who: task.owner_id.clone(), + task_id: task_id.clone(), + }); + } + Self::handle_task_post_processing(task_id.clone(), task, dispatch_error); task_action_weight .saturating_add(T::DbWeight::get().writes(1u64)) @@ -1142,15 +1160,6 @@ pub mod pallet { task_id: TaskIdV2, task: &TaskOf, ) -> (Weight, Option) { - // TODO: Handle edge case where user has enough funds to run task but not reschedule - if !T::DelegatorActions::is_delegation_exist(&delegator, &collator) { - // DelegationNotFound - return ( - ::WeightInfo::run_auto_compound_delegated_stake_task(), - Some(Error::::DelegationNotFound.into()), - ) - } - let fee_amount = Self::calculate_schedule_fee_amount(&task.action, 1); if fee_amount.is_err() { return ( @@ -1534,13 +1543,6 @@ pub mod pallet { task: TaskOf, error: Option, ) { - if let Some(err) = error { - Self::deposit_event(Event::::TaskExecutionFailed { - who: task.owner_id.clone(), - task_id: task_id.clone(), - error: err, - }); - } match task.schedule { Schedule::Fixed { .. } => Self::decrement_task_and_remove_if_complete(task_id, task), diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index c758bf33a..0fbb4961e 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -22,11 +22,11 @@ use crate::TaskIdV2; use frame_benchmarking::frame_support::assert_ok; use frame_support::{ construct_runtime, parameter_types, - traits::{ConstU32, Everything}, + traits::{ConstU32, Everything, ConstU128}, weights::Weight, PalletId, }; -use frame_system::{self as system, RawOrigin}; +use frame_system::{self as system, RawOrigin, EnsureRoot}; use orml_traits::parameter_type_with_key; use primitives::EnsureProxy; use sp_core::H256; @@ -57,6 +57,8 @@ pub const NATIVE_LOCATION: MultiLocation = MultiLocation { parents: 0, interior: pub const NATIVE_EXECUTION_WEIGHT_FEE: u128 = 12; pub const FOREIGN_CURRENCY_ID: CurrencyId = 1; +const DOLLAR: u128 = 10_000_000_000; + pub const MOONBASE_ASSET_LOCATION: MultiLocation = MultiLocation { parents: 1, interior: X2(Parachain(1000), PalletInstance(3)) }; pub const UNKNOWN_SCHEDULE_FEE: MultiLocation = @@ -98,6 +100,7 @@ construct_runtime!( Tokens: orml_tokens::{Pallet, Storage, Event, Config}, Currencies: orml_currencies::{Pallet, Call}, AutomationTime: pallet_automation_time::{Pallet, Call, Storage, Event}, + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config}, } ); @@ -187,7 +190,7 @@ pub type AdaptedBasicCurrency = orml_currencies::BasicCurrencyAdapter; -// /// Minimum round length is 2 minutes (10 * 12 second block times) -// type MinBlocksPerRound = ConstU32<10>; -// /// Rounds before the collator leaving the candidates request can be executed -// type LeaveCandidatesDelay = ConstU32<2>; -// /// Rounds before the candidate bond increase/decrease can be executed -// type CandidateBondLessDelay = ConstU32<2>; -// /// Rounds before the delegator exit can be executed -// type LeaveDelegatorsDelay = ConstU32<2>; -// /// Rounds before the delegator revocation can be executed -// type RevokeDelegationDelay = ConstU32<2>; -// /// Rounds before the delegator bond increase/decrease can be executed -// type DelegationBondLessDelay = ConstU32<2>; -// /// Rounds before the reward is paid -// type RewardPaymentDelay = ConstU32<2>; -// /// Minimum collators selected per round, default at genesis and minimum forever after -// type MinSelectedCandidates = ConstU32<5>; -// /// Maximum top delegations per candidate -// type MaxTopDelegationsPerCandidate = ConstU32<10>; -// /// Maximum bottom delegations per candidate -// type MaxBottomDelegationsPerCandidate = ConstU32<50>; -// /// Maximum delegations per delegator -// type MaxDelegationsPerDelegator = ConstU32<10>; -// type MinCollatorStk = MinCollatorStk; -// /// Minimum stake required to be reserved to be a candidate -// type MinCandidateStk = ConstU128<{ 500 * DOLLAR }>; -// /// Minimum delegation amount after initial -// type MinDelegation = ConstU128<{ 50 * DOLLAR }>; -// /// Minimum initial stake required to be reserved to be a delegator -// type MinDelegatorStk = ConstU128<{ 50 * DOLLAR }>; -// /// Handler to notify the runtime when a collator is paid -// type OnCollatorPayout = (); -// type PayoutCollatorReward = (); -// /// Handler to notify the runtime when a new round begins -// type OnNewRound = (); -// /// Any additional issuance that should be used for inflation calcs -// type AdditionalIssuance = (); -// type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; -// } +impl pallet_parachain_staking::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = EnsureRoot; + /// Minimum round length is 2 minutes (10 * 12 second block times) + type MinBlocksPerRound = ConstU32<10>; + /// Rounds before the collator leaving the candidates request can be executed + type LeaveCandidatesDelay = ConstU32<2>; + /// Rounds before the candidate bond increase/decrease can be executed + type CandidateBondLessDelay = ConstU32<2>; + /// Rounds before the delegator exit can be executed + type LeaveDelegatorsDelay = ConstU32<2>; + /// Rounds before the delegator revocation can be executed + type RevokeDelegationDelay = ConstU32<2>; + /// Rounds before the delegator bond increase/decrease can be executed + type DelegationBondLessDelay = ConstU32<2>; + /// Rounds before the reward is paid + type RewardPaymentDelay = ConstU32<2>; + /// Minimum collators selected per round, default at genesis and minimum forever after + type MinSelectedCandidates = ConstU32<5>; + /// Maximum top delegations per candidate + type MaxTopDelegationsPerCandidate = ConstU32<10>; + /// Maximum bottom delegations per candidate + type MaxBottomDelegationsPerCandidate = ConstU32<50>; + /// Maximum delegations per delegator + type MaxDelegationsPerDelegator = ConstU32<10>; + type MinCollatorStk = MinCollatorStk; + /// Minimum stake required to be reserved to be a candidate + type MinCandidateStk = ConstU128<{ 500 * DOLLAR }>; + /// Minimum delegation amount after initial + type MinDelegation = ConstU128<{ 50 * DOLLAR }>; + /// Minimum initial stake required to be reserved to be a delegator + type MinDelegatorStk = ConstU128<{ 50 * DOLLAR }>; + /// Handler to notify the runtime when a collator is paid + type OnCollatorPayout = (); + type PayoutCollatorReward = (); + /// Handler to notify the runtime when a new round begins + type OnNewRound = (); + /// Any additional issuance that should be used for inflation calcs + type AdditionalIssuance = (); + type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; +} pub struct MockDelegatorActions(PhantomData<(T, C)>); impl< - T: Config + pallet::Config, + T: Config + pallet::Config + pallet_parachain_staking::Config, C: frame_support::traits::ReservableCurrency, > pallet_parachain_staking::DelegatorActions> for MockDelegatorActions { fn delegator_bond_more( delegator: &T::AccountId, - _candidate: &T::AccountId, + candidate: &T::AccountId, amount: BalanceOf, ) -> Result { + if *delegator != T::AccountId::decode(&mut DELEGATOR_ACCOUNT.as_ref()).unwrap() { + return Err(>::DelegatorDNE.into()); + } + + if *candidate != T::AccountId::decode(&mut COLLATOR_ACCOUNT.as_ref()).unwrap() { + return Err(>::DelegationDNE.into()); + } + let delegation: u128 = amount.saturated_into(); C::reserve(delegator, delegation.saturated_into())?; Ok(true) @@ -585,9 +596,10 @@ pub fn add_task_to_task_queue( task_id: TaskIdV2, scheduled_times: Vec, action: ActionOf, + cancel_errors: Vec, ) -> TaskIdV2 { let schedule = Schedule::new_fixed_schedule::(scheduled_times).unwrap(); - add_to_task_queue(owner, task_id, schedule, action) + add_to_task_queue(owner, task_id, schedule, action, cancel_errors) } pub fn add_recurring_task_to_task_queue( @@ -596,9 +608,10 @@ pub fn add_recurring_task_to_task_queue( scheduled_time: u64, frequency: u64, action: ActionOf, + abort_errors: Vec, ) -> TaskIdV2 { let schedule = Schedule::new_recurring_schedule::(scheduled_time, frequency).unwrap(); - add_to_task_queue(owner, task_id, schedule, action) + add_to_task_queue(owner, task_id, schedule, action, abort_errors) } pub fn add_to_task_queue( @@ -606,8 +619,9 @@ pub fn add_to_task_queue( task_id: TaskIdV2, schedule: Schedule, action: ActionOf, + abort_errors: Vec, ) -> TaskIdV2 { - let task_id = create_task(owner, task_id, schedule, action); + let task_id = create_task(owner, task_id, schedule, action, abort_errors); let mut task_queue = AutomationTime::get_task_queue(); task_queue.push((AccountId32::new(owner), task_id.clone())); TaskQueueV2::::put(task_queue); @@ -619,9 +633,10 @@ pub fn add_task_to_missed_queue( task_id: TaskIdV2, scheduled_times: Vec, action: ActionOf, + cancel_errors: Vec, ) -> TaskIdV2 { let schedule = Schedule::new_fixed_schedule::(scheduled_times.clone()).unwrap(); - let task_id = create_task(owner, task_id.clone(), schedule, action); + let task_id = create_task(owner, task_id.clone(), schedule, action, cancel_errors); let missed_task = MissedTaskV2Of::::new(AccountId32::new(owner), task_id.clone(), scheduled_times[0]); let mut missed_queue = AutomationTime::get_missed_queue(); @@ -635,8 +650,9 @@ pub fn create_task( task_id: TaskIdV2, schedule: Schedule, action: ActionOf, + abort_errors: Vec, ) -> TaskIdV2 { - let task = TaskOf::::new(owner.into(), task_id.clone(), schedule, action, vec![]); + let task = TaskOf::::new(owner.into(), task_id.clone(), schedule, action, abort_errors); AccountTasks::::insert(AccountId::new(owner), task_id.clone(), task); task_id } diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index bf5f0c303..33c578cd8 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -35,8 +35,6 @@ use sp_runtime::{ AccountId32, }; use xcm::latest::{prelude::*, Junction::Parachain, MultiLocation}; -// use sp_runtime::DispatchError::Module; -// use sp_runtime::ModuleError; use frame_support::pallet_prelude::DispatchError; use sp_std::collections::btree_map::BTreeMap; @@ -356,6 +354,10 @@ fn schedule_transfer_with_dynamic_dispatch() { to: recipient.clone(), amount: 127, }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: account_id.clone(), + task_id: task_id.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: account_id, task_id, @@ -1534,6 +1536,10 @@ fn cancel_works_for_an_executed_task() { sender: owner.clone(), hash: BlakeTwo256::hash(&vec![50]), }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id1.clone(), + }), ] ); match AutomationTime::get_account_task(owner.clone(), task_id1.clone()) { @@ -1585,6 +1591,7 @@ fn cancel_works_for_tasks_in_queue() { vec![40], vec![SCHEDULED_TIME], Action::Notify { message: vec![2, 4, 5] }, + vec![], ); LastTimeSlot::::put((SCHEDULED_TIME, SCHEDULED_TIME)); @@ -1892,6 +1899,7 @@ fn trigger_tasks_updates_queues() { vec![40], vec![SCHEDULED_TIME - 3600], Action::Notify { message: vec![40] }, + vec![], ); let missed_task = MissedTaskV2Of::::new( AccountId32::new(ALICE), @@ -1932,6 +1940,7 @@ fn trigger_tasks_handles_missed_slots() { vec![40], vec![SCHEDULED_TIME], Action::DynamicDispatch { encoded_call: call.encode() }, + vec![], ); assert_eq!(AutomationTime::get_missed_queue().len(), 0); @@ -1983,6 +1992,10 @@ fn trigger_tasks_handles_missed_slots() { sender: AccountId32::new(ALICE), hash: BlakeTwo256::hash(&remark_message), }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_will_be_run_id.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: AccountId32::new(ALICE), task_id: task_will_be_run_id.clone(), @@ -2007,7 +2020,6 @@ fn trigger_tasks_handles_missed_slots() { #[test] fn trigger_tasks_limits_missed_slots() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - let _ = env_logger::try_init(); let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: vec![50] }.into(); @@ -2016,6 +2028,7 @@ fn trigger_tasks_limits_missed_slots() { vec![40], vec![SCHEDULED_TIME], Action::DynamicDispatch { encoded_call: call.clone().encode() }, + vec![], ); assert_eq!(AutomationTime::get_missed_queue().len(), 0); @@ -2067,6 +2080,10 @@ fn trigger_tasks_limits_missed_slots() { sender: owner.clone(), hash: BlakeTwo256::hash(&remark_message), }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id, @@ -2145,6 +2162,7 @@ fn trigger_tasks_completes_all_tasks() { vec![40], vec![SCHEDULED_TIME], Action::Notify { message: message_one.clone() }, + vec![], ); let message_two: Vec = vec![2, 4]; let task_id2 = add_task_to_task_queue( @@ -2152,6 +2170,7 @@ fn trigger_tasks_completes_all_tasks() { vec![50], vec![SCHEDULED_TIME], Action::Notify { message: message_two.clone() }, + vec![], ); LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); @@ -2172,20 +2191,28 @@ fn trigger_tasks_completes_all_tasks() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id1.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: AccountId32::new(ALICE), + who: owner.clone(), task_id: task_id1.clone(), }), RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { - who: owner, + who: owner.clone(), task_id: task_id2.clone(), condition, encoded_call: vec![], abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id2.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: AccountId32::new(ALICE), + who: owner, task_id: task_id2.clone(), }), ] @@ -2222,12 +2249,14 @@ fn trigger_tasks_handles_nonexisting_tasks() { #[test] fn trigger_tasks_completes_some_tasks() { new_test_ext(START_BLOCK_TIME).execute_with(|| { + let owner = AccountId32::new(ALICE); let message_one: Vec = vec![2, 4, 5]; let task_id1 = add_task_to_task_queue( ALICE, vec![40], vec![SCHEDULED_TIME], Action::Notify { message: message_one.clone() }, + vec![], ); let message_two: Vec = vec![2, 4]; let task_id2 = add_task_to_task_queue( @@ -2235,6 +2264,7 @@ fn trigger_tasks_completes_some_tasks() { vec![50], vec![SCHEDULED_TIME], Action::Notify { message: message_two.clone() }, + vec![], ); LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); @@ -2248,23 +2278,27 @@ fn trigger_tasks_completes_some_tasks() { events(), [ RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { - who: AccountId32::new(ALICE), + who: owner.clone(), task_id: task_id1.clone(), condition, encoded_call: vec![], abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id1.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: AccountId32::new(ALICE), + who: owner.clone(), task_id: task_id1.clone(), }), ] ); assert_eq!(1, AutomationTime::get_task_queue().len()); - assert_eq!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id1), None); - assert_ne!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id2), None); + assert_eq!(AutomationTime::get_account_task(owner.clone(), task_id1), None); + assert_ne!(AutomationTime::get_account_task(owner, task_id2), None); }) } @@ -2276,12 +2310,14 @@ fn trigger_tasks_completes_all_missed_tasks() { vec![40], vec![SCHEDULED_TIME], Action::Notify { message: vec![40] }, + vec![], ); let task_id2 = add_task_to_missed_queue( ALICE, vec![50], vec![SCHEDULED_TIME], Action::Notify { message: vec![40] }, + vec![], ); LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); @@ -2334,12 +2370,14 @@ fn missed_tasks_updates_executions_left() { vec![40], vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600], Action::Notify { message: vec![40] }, + vec![], ); let task_id2 = add_task_to_missed_queue( ALICE, vec![50], vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600], Action::Notify { message: vec![40] }, + vec![], ); match AutomationTime::get_account_task(owner.clone(), task_id1.clone()) { @@ -2408,6 +2446,7 @@ fn missed_tasks_removes_completed_tasks() { vec![40], vec![SCHEDULED_TIME, SCHEDULED_TIME - 3600], Action::Notify { message: message_one.clone() }, + vec![], ); let mut task_queue = AutomationTime::get_task_queue(); @@ -2447,13 +2486,17 @@ fn missed_tasks_removes_completed_tasks() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id01.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskMissed { - who: AccountId32::new(ALICE), + who: owner.clone(), task_id: task_id01.clone(), execution_time: SCHEDULED_TIME }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: AccountId32::new(ALICE), + who: owner.clone(), task_id: task_id01.clone(), }), ] @@ -2478,6 +2521,7 @@ fn trigger_tasks_completes_some_native_transfer_tasks() { recipient: AccountId32::new(BOB), amount: transfer_amount, }, + vec![], ); add_task_to_task_queue( ALICE, @@ -2488,6 +2532,7 @@ fn trigger_tasks_completes_some_native_transfer_tasks() { recipient: AccountId32::new(BOB), amount: transfer_amount, }, + vec![], ); LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); @@ -2526,6 +2571,7 @@ fn trigger_tasks_completes_some_xcmp_tasks() { schedule_as: None, instruction_sequence: InstructionSequence::PayThroughSovereignAccount, }, + vec![], ); LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); @@ -2547,6 +2593,10 @@ fn trigger_tasks_completes_some_xcmp_tasks() { encoded_call, abort_errors: vec![], }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner, task_id }) ] ); @@ -2571,16 +2621,26 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, + vec![], ); LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); System::reset_events(); AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + let emitted_events = events(); let new_balance = Balances::free_balance(delegator.clone()); assert!(new_balance < before_balance); assert_eq!(new_balance, account_minimum); + + emitted_events + .clone() + .into_iter() + .find(|e| { + matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { .. })) + }) + .expect("TaskExecuted event should have been emitted"); }) } @@ -2612,6 +2672,7 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, + vec![], ); System::reset_events(); @@ -2620,8 +2681,15 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { let emitted_events = events(); - // // Expected result: - // // 1. Current execution will run + // Expected result: + // 1. Current execution will run + emitted_events + .clone() + .into_iter() + .find(|e| { + matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { .. })) + }) + .expect("TaskExecuted event should have been emitted"); // 2. Next execution will be scheduled emitted_events @@ -2684,6 +2752,7 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { collator: AccountId32::new(COLLATOR_ACCOUNT), account_minimum, }, + vec![], ); System::reset_events(); @@ -2718,7 +2787,7 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { }) } -// Scheduling an auto compound delegated stake task will failed if the account has a sufficient balance and no delegation with the specificed collator. +// Scheduling an auto compound delegated stake task will failed if the account has a sufficient balance and no delegator with the specificed collator. // Condition: // 1. User's wallet balance >= minimum balance + execution fee // 2. User has no delegation with the specificed collator @@ -2726,9 +2795,9 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound // 2. Next execution will not be scheduled #[test] -fn auto_compound_delegated_stake_enough_balance_no_delegation() { +fn auto_compound_delegated_stake_enough_balance_no_delegator() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - let delegator = AccountId32::new(DELEGATOR_ACCOUNT); + let delegator = AccountId32::new(ALICE); get_funds(delegator.clone()); let before_balance = Balances::free_balance(delegator.clone()); // Minimum balance is half of the user's wallet balance @@ -2745,33 +2814,39 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { collator: AccountId32::new(BOB), account_minimum, }, + vec![String::from("DelegatorDNE"), String::from("DelegationDNE")], ); System::reset_events(); AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + let emitted_events = events(); + // Expected result: - // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationDNE - let delegation_error: DispatchError = Error::::DelegationNotFound.into(); - events() + // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegationDNE + let delegator_error: DispatchError = >::DelegatorDNE.into(); + emitted_events.clone() .into_iter() - .find(|e| match e { - RuntimeEvent::AutomationTime(crate::Event::TaskScheduled { .. }) => true, - _ => false, + .find(|e| { + matches!(e, + RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { + error, + .. + }) if *error == delegator_error.clone()) }) - .expect("TaskScheduled event should have been emitted"); - let next_scheduled_time = SCHEDULED_TIME + frequency; - AutomationTime::get_scheduled_tasks(next_scheduled_time) - .expect("Task should have been rescheduled") - .tasks + .expect("TaskExecutionFailed event should have been emitted"); + + emitted_events .into_iter() - .find(|t| *t == (AccountId32::new(ALICE), task_id.clone())) - .expect("Task should have been rescheduled"); - let task = AutomationTime::get_account_task(AccountId32::new(ALICE), task_id.clone()) - .expect("Task should not have been removed from task map"); - assert_eq!(task.schedule.known_executions_left(), 1); - assert_eq!(task.execution_times(), vec![next_scheduled_time]); + .find(|e| { + matches!(e, + RuntimeEvent::AutomationTime(crate::Event::TaskNotRescheduled { + error, + .. + }) if *error == delegator_error.clone()) + }) + .expect("TaskNotRescheduled event should have been emitted");; // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) @@ -2783,6 +2858,77 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { }) } +// Scheduling an auto compound delegated stake task will failed if the account has a sufficient balance and no delegation with the specificed collator. +// Condition: +// 1. User's wallet balance >= minimum balance + execution fee +// 2. User has no delegation with the specificed collator +// Expected result: +// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound +// 2. Next execution will not be scheduled +#[test] +fn auto_compound_delegated_stake_enough_balance_no_delegation() { + new_test_ext(START_BLOCK_TIME).execute_with(|| { + let delegator = AccountId32::new(DELEGATOR_ACCOUNT); + get_funds(delegator.clone()); + let before_balance = Balances::free_balance(delegator.clone()); + // Minimum balance is half of the user's wallet balance + let account_minimum = before_balance / 2; + let frequency = 3_600; + + let task_id = add_recurring_task_to_task_queue( + DELEGATOR_ACCOUNT, + vec![1], + SCHEDULED_TIME, + frequency, + Action::AutoCompoundDelegatedStake { + delegator: delegator.clone(), + collator: AccountId32::new(BOB), + account_minimum, + }, + vec![String::from("DelegatorDNE"), String::from("DelegationDNE")], + ); + + System::reset_events(); + + AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); + + let emitted_events = events(); + + // Expected result: + // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegationDNE + let delegation_error: DispatchError = >::DelegationDNE.into(); + emitted_events.clone() + .into_iter() + .find(|e| { + matches!(e, + RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { + error, + .. + }) if *error == delegation_error.clone()) + }) + .expect("TaskExecutionFailed event should have been emitted"); + + emitted_events + .into_iter() + .find(|e| { + matches!(e, + RuntimeEvent::AutomationTime(crate::Event::TaskNotRescheduled { + error, + .. + }) if *error == delegation_error.clone()) + }) + .expect("TaskNotRescheduled event should have been emitted");; + + // 2. Next execution will not be scheduled + assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) + .filter(|scheduled| { + scheduled.tasks.iter().any(|t| *t == (AccountId32::new(DELEGATOR_ACCOUNT), task_id.clone())) + }) + .is_none()); + assert!(AutomationTime::get_account_task(AccountId32::new(DELEGATOR_ACCOUNT), task_id).is_none()); + }) +} + // Scheduling an auto compound delegated stake task will failed if the account has not enough balance and no delegation with the specificed collator. // Condition: // 1. User's wallet balance < minimum balance + execution fee @@ -2796,13 +2942,13 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { let delegator = AccountId32::new(DELEGATOR_ACCOUNT); let collator = AccountId32::new(BOB); get_funds(delegator.clone()); - let before_balance = Balances::free_balance(AccountId32::new(ALICE)); + let before_balance = Balances::free_balance(delegator.clone()); // Minimum balance is twice of the user's wallet balance let account_minimum = before_balance * 2; let frequency = 3_600; let task_id = add_recurring_task_to_task_queue( - ALICE, + DELEGATOR_ACCOUNT, vec![1], SCHEDULED_TIME, frequency, @@ -2811,39 +2957,47 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { collator: collator.clone(), account_minimum, }, + vec![String::from("DelegatorDNE"), String::from("DelegationDNE")], ); System::reset_events(); AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - let emit_events = events(); + let emitted_events = events(); // Expected result: - // 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationDNE - // let delegation_error: DispatchError = Error::::DelegationNotFound.into(); - // emit_events.clone() - // .into_iter() - // .find(|e| { - // matches!(e, - // RuntimeEvent::AutomationTime(crate::Event::AutoCompoundDelegatorStakeFailed { - // error: DispatchErrorWithDataMap { error, .. }, - // .. - // }) if *error == delegation_error.clone()) - // }) - // .expect("AutoCompoundDelegatorStakeFailed event should have been emitted"); - - // emit_events.into_iter() - // .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { error, .. }) if *error == delegation_error )).expect("TaskExecutionFailed event should have been emitted"); - - // 2. Next execution will not be scheduled - assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) - .filter(|scheduled| { - scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id.clone())) + // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: InsufficientBalance + let insufficient_balance_error: DispatchError = Error::::InsufficientBalance.into(); + emitted_events.clone() + .into_iter() + .find(|e| { + matches!(e, + RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { + error, + .. + }) if *error == insufficient_balance_error.clone()) }) - .is_none()); - assert!( - AutomationTime::get_account_task(AccountId32::new(ALICE), task_id.clone()).is_none() - ); + .expect("TaskExecutionFailed event should have been emitted"); + + // 2. Next execution will be scheduled + emitted_events + .into_iter() + .find(|e| { + matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { .. })) + }) + .expect("TaskRescheduled event should have been emitted"); + + let next_scheduled_time = SCHEDULED_TIME + frequency; + AutomationTime::get_scheduled_tasks(next_scheduled_time) + .expect("Task should have been rescheduled") + .tasks + .into_iter() + .find(|t| *t == (delegator.clone(), task_id.clone())) + .expect("Task should have been rescheduled"); + let task = AutomationTime::get_account_task(delegator.clone(), task_id) + .expect("Task should not have been removed from task map"); + assert_eq!(task.schedule.known_executions_left(), 1); + assert_eq!(task.execution_times(), vec![next_scheduled_time]); }) } @@ -2859,6 +3013,7 @@ fn trigger_tasks_updates_executions_left() { vec![40], vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600], Action::Notify { message: message_one.clone() }, + vec![], ); match AutomationTime::get_account_task(owner.clone(), task_id01.clone()) { @@ -2890,6 +3045,10 @@ fn trigger_tasks_updates_executions_left() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id01.clone(), + }), ] ); match AutomationTime::get_account_task(owner.clone(), task_id01) { @@ -2913,6 +3072,7 @@ fn trigger_tasks_removes_completed_tasks() { vec![40], vec![SCHEDULED_TIME], Action::Notify { message: message_one.clone() }, + vec![], ); match AutomationTime::get_account_task(owner.clone(), task_id01.clone()) { @@ -2944,6 +3104,10 @@ fn trigger_tasks_removes_completed_tasks() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id01.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: task_id01.clone(), @@ -2964,6 +3128,7 @@ fn on_init_runs_tasks() { vec![40], vec![SCHEDULED_TIME], Action::Notify { message: message_one.clone() }, + vec![], ); let message_two: Vec = vec![2, 4]; let task_id2 = add_task_to_task_queue( @@ -2971,12 +3136,14 @@ fn on_init_runs_tasks() { vec![50], vec![SCHEDULED_TIME], Action::Notify { message: message_two.clone() }, + vec![], ); let task_id3 = add_task_to_task_queue( ALICE, vec![60], vec![SCHEDULED_TIME], Action::Notify { message: vec![50] }, + vec![], ); LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); @@ -2997,6 +3164,10 @@ fn on_init_runs_tasks() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id1.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: task_id1.clone(), @@ -3009,6 +3180,10 @@ fn on_init_runs_tasks() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: task_id2.clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: task_id2.clone(), @@ -3058,6 +3233,7 @@ fn on_init_check_task_queue() { vec![i], vec![SCHEDULED_TIME], Action::Notify { message: vec![i] }, + vec![], ); tasks.push(task_id.clone()); } @@ -3081,6 +3257,10 @@ fn on_init_check_task_queue() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![0] }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: tasks[0].clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: tasks[0].clone(), @@ -3093,6 +3273,10 @@ fn on_init_check_task_queue() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![1] }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: tasks[1].clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: tasks[1].clone(), @@ -3115,6 +3299,10 @@ fn on_init_check_task_queue() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![2] }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: tasks[2].clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: tasks[2].clone(), @@ -3127,6 +3315,10 @@ fn on_init_check_task_queue() { abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![3] }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: owner.clone(), + task_id: tasks[3].clone(), + }), RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: owner.clone(), task_id: tasks[3].clone(), @@ -3169,6 +3361,7 @@ fn on_init_shutdown() { vec![40], vec![SCHEDULED_TIME], Action::Notify { message: message_one.clone() }, + vec![], ); let message_two: Vec = vec![2, 4]; let task_id2 = add_task_to_task_queue( @@ -3176,12 +3369,14 @@ fn on_init_shutdown() { vec![50], vec![SCHEDULED_TIME], Action::Notify { message: message_two.clone() }, + vec![], ); let task_id3 = add_task_to_task_queue( ALICE, vec![60], vec![SCHEDULED_TIME], Action::Notify { message: vec![50] }, + vec![], ); LastTimeSlot::::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME)); From 8e126764b8e162c0fb6456a6dcc0a7949d26fa30 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Mon, 31 Jul 2023 07:26:52 +0000 Subject: [PATCH 22/37] fixup: auto format Rust code --- pallets/automation-time/src/mock.rs | 8 ++--- pallets/automation-time/src/tests.rs | 49 +++++++++++++++------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 0fbb4961e..e351a8bc0 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -22,11 +22,11 @@ use crate::TaskIdV2; use frame_benchmarking::frame_support::assert_ok; use frame_support::{ construct_runtime, parameter_types, - traits::{ConstU32, Everything, ConstU128}, + traits::{ConstU128, ConstU32, Everything}, weights::Weight, PalletId, }; -use frame_system::{self as system, RawOrigin, EnsureRoot}; +use frame_system::{self as system, EnsureRoot, RawOrigin}; use orml_traits::parameter_type_with_key; use primitives::EnsureProxy; use sp_core::H256; @@ -257,11 +257,11 @@ impl< amount: BalanceOf, ) -> Result { if *delegator != T::AccountId::decode(&mut DELEGATOR_ACCOUNT.as_ref()).unwrap() { - return Err(>::DelegatorDNE.into()); + return Err(>::DelegatorDNE.into()) } if *candidate != T::AccountId::decode(&mut COLLATOR_ACCOUNT.as_ref()).unwrap() { - return Err(>::DelegationDNE.into()); + return Err(>::DelegationDNE.into()) } let delegation: u128 = amount.saturated_into(); diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 33c578cd8..6e387fa81 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -24,6 +24,7 @@ use codec::Encode; use frame_support::{ assert_noop, assert_ok, dispatch::GetDispatchInfo, + pallet_prelude::DispatchError, traits::OnInitialize, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, }; @@ -34,9 +35,8 @@ use sp_runtime::{ traits::{BlakeTwo256, Hash}, AccountId32, }; -use xcm::latest::{prelude::*, Junction::Parachain, MultiLocation}; -use frame_support::pallet_prelude::DispatchError; use sp_std::collections::btree_map::BTreeMap; +use xcm::latest::{prelude::*, Junction::Parachain, MultiLocation}; use pallet_balances; use pallet_valve::Shutdown; @@ -2637,9 +2637,7 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { emitted_events .clone() .into_iter() - .find(|e| { - matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { .. })) - }) + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { .. }))) .expect("TaskExecuted event should have been emitted"); }) } @@ -2686,9 +2684,7 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { emitted_events .clone() .into_iter() - .find(|e| { - matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { .. })) - }) + .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { .. }))) .expect("TaskExecuted event should have been emitted"); // 2. Next execution will be scheduled @@ -2825,8 +2821,10 @@ fn auto_compound_delegated_stake_enough_balance_no_delegator() { // Expected result: // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegationDNE - let delegator_error: DispatchError = >::DelegatorDNE.into(); - emitted_events.clone() + let delegator_error: DispatchError = + >::DelegatorDNE.into(); + emitted_events + .clone() .into_iter() .find(|e| { matches!(e, @@ -2846,7 +2844,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegator() { .. }) if *error == delegator_error.clone()) }) - .expect("TaskNotRescheduled event should have been emitted");; + .expect("TaskNotRescheduled event should have been emitted"); // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) @@ -2896,8 +2894,10 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { // Expected result: // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegationDNE - let delegation_error: DispatchError = >::DelegationDNE.into(); - emitted_events.clone() + let delegation_error: DispatchError = + >::DelegationDNE.into(); + emitted_events + .clone() .into_iter() .find(|e| { matches!(e, @@ -2917,15 +2917,19 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { .. }) if *error == delegation_error.clone()) }) - .expect("TaskNotRescheduled event should have been emitted");; + .expect("TaskNotRescheduled event should have been emitted"); // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) .filter(|scheduled| { - scheduled.tasks.iter().any(|t| *t == (AccountId32::new(DELEGATOR_ACCOUNT), task_id.clone())) + scheduled + .tasks + .iter() + .any(|t| *t == (AccountId32::new(DELEGATOR_ACCOUNT), task_id.clone())) }) .is_none()); - assert!(AutomationTime::get_account_task(AccountId32::new(DELEGATOR_ACCOUNT), task_id).is_none()); + assert!(AutomationTime::get_account_task(AccountId32::new(DELEGATOR_ACCOUNT), task_id) + .is_none()); }) } @@ -2968,7 +2972,8 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { // Expected result: // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: InsufficientBalance let insufficient_balance_error: DispatchError = Error::::InsufficientBalance.into(); - emitted_events.clone() + emitted_events + .clone() .into_iter() .find(|e| { matches!(e, @@ -2981,11 +2986,11 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { // 2. Next execution will be scheduled emitted_events - .into_iter() - .find(|e| { - matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { .. })) - }) - .expect("TaskRescheduled event should have been emitted"); + .into_iter() + .find(|e| { + matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { .. })) + }) + .expect("TaskRescheduled event should have been emitted"); let next_scheduled_time = SCHEDULED_TIME + frequency; AutomationTime::get_scheduled_tasks(next_scheduled_time) From 19e9eecc516eee4327a07eeba016ae3323c8275d Mon Sep 17 00:00:00 2001 From: imstar15 Date: Mon, 31 Jul 2023 19:48:08 +0800 Subject: [PATCH 23/37] Fix tests --- Cargo.lock | 1 - pallets/automation-time/Cargo.toml | 1 - pallets/automation-time/src/lib.rs | 16 ---------------- pallets/automation-time/src/tests.rs | 14 +++++++------- pallets/automation-time/src/types.rs | 12 ------------ 5 files changed, 7 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b39f4d08..46bc48e04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5935,7 +5935,6 @@ version = "1.0.0" dependencies = [ "cumulus-pallet-xcm", "cumulus-primitives-core", - "env_logger", "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", "frame-system 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", diff --git a/pallets/automation-time/Cargo.toml b/pallets/automation-time/Cargo.toml index dfa7234b6..6ff71f011 100644 --- a/pallets/automation-time/Cargo.toml +++ b/pallets/automation-time/Cargo.toml @@ -63,7 +63,6 @@ pallet-xcmp-handler = { path = "../xcmp-handler", default-features = false } primitives = { path = "../../primitives", default-features = false } [dev-dependencies] -env_logger = "0.9" rand = { version = "0.7.3" } serde = { version = "1.0.144" } sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 0320fff60..55e622f94 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -82,17 +82,6 @@ use sp_std::{boxed::Box, collections::btree_map::BTreeMap, vec, vec::Vec}; pub use weights::WeightInfo; use xcm::{latest::prelude::*, VersionedMultiLocation}; -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)] -pub struct DispatchErrorDataMap(BTreeMap); -impl sp_runtime::traits::Printable for DispatchErrorDataMap { - fn print(&self) { - for (key, value) in self.0.iter() { - sp_io::misc::print_utf8(format!("{:?}: {:?}, ", key, value).as_bytes()); - } - } -} -pub type DispatchErrorWithDataMap = DispatchErrorWithData; - const AUTO_COMPOUND_DELEGATION_ABORT_ERRORS: [&str; 2] = ["DelegatorDNE", "DelegationDNE"]; #[frame_support::pallet] @@ -324,11 +313,6 @@ pub mod pallet { task_id: TaskIdV2, amount: BalanceOf, }, - AutoCompoundDelegatorStakeFailed { - task_id: TaskIdV2, - error_message: Vec, - error: DispatchErrorWithPostInfo, - }, /// The task could not be run at the scheduled time. TaskMissed { who: AccountOf, diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 6e387fa81..ea55dbc53 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -2726,7 +2726,7 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { // 1. User's wallet balance < minimum balance + execution fee // 2. User has a delegation with the specificed collator // Expected result: -// 1. Emit TaskExecutionFailed event with error: InsufficientBalance +// 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegationDNE // 2. Next execution will be scheduled #[test] fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { @@ -2788,7 +2788,7 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { // 1. User's wallet balance >= minimum balance + execution fee // 2. User has no delegation with the specificed collator // Expected result: -// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound +// 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegatorDNE // 2. Next execution will not be scheduled #[test] fn auto_compound_delegated_stake_enough_balance_no_delegator() { @@ -2849,10 +2849,10 @@ fn auto_compound_delegated_stake_enough_balance_no_delegator() { // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) .filter(|scheduled| { - scheduled.tasks.iter().any(|t| *t == (AccountId32::new(ALICE), task_id.clone())) + scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id.clone())) }) .is_none()); - assert!(AutomationTime::get_account_task(AccountId32::new(ALICE), task_id).is_none()); + assert!(AutomationTime::get_account_task(delegator, task_id).is_none()); }) } @@ -2861,7 +2861,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegator() { // 1. User's wallet balance >= minimum balance + execution fee // 2. User has no delegation with the specificed collator // Expected result: -// 1. The current execution will result in failure, triggering the emission of an AutoCompoundDelegatorStakeFailed event, error: DelegationNotFound +// 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegationDNE // 2. Next execution will not be scheduled #[test] fn auto_compound_delegated_stake_enough_balance_no_delegation() { @@ -2925,10 +2925,10 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { scheduled .tasks .iter() - .any(|t| *t == (AccountId32::new(DELEGATOR_ACCOUNT), task_id.clone())) + .any(|t| *t == (delegator.clone(), task_id.clone())) }) .is_none()); - assert!(AutomationTime::get_account_task(AccountId32::new(DELEGATOR_ACCOUNT), task_id) + assert!(AutomationTime::get_account_task(delegator, task_id) .is_none()); }) } diff --git a/pallets/automation-time/src/types.rs b/pallets/automation-time/src/types.rs index 238835a22..d930bec20 100644 --- a/pallets/automation-time/src/types.rs +++ b/pallets/automation-time/src/types.rs @@ -361,18 +361,6 @@ impl ScheduledTasks { } } -#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct DispatchErrorWithData -where - Data: Eq + PartialEq + Clone + Encode + Decode + Printable, -{ - /// Additional data - pub data: Data, - pub message: Option, - /// The actual `DispatchResult` indicating whether the dispatch was successful. - pub error: DispatchError, -} - #[cfg(test)] mod tests { use super::*; From eb25f2811badbf38e06c5b2ba22eb1f1acc2d7a6 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Mon, 31 Jul 2023 11:48:26 +0000 Subject: [PATCH 24/37] fixup: auto format Rust code --- pallets/automation-time/src/tests.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index ea55dbc53..f5326c731 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -2922,14 +2922,10 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) .filter(|scheduled| { - scheduled - .tasks - .iter() - .any(|t| *t == (delegator.clone(), task_id.clone())) + scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id.clone())) }) .is_none()); - assert!(AutomationTime::get_account_task(delegator, task_id) - .is_none()); + assert!(AutomationTime::get_account_task(delegator, task_id).is_none()); }) } From 5afe04b32a377e12ce9c66d9db5f3b7dab9edc56 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Mon, 31 Jul 2023 20:03:16 +0800 Subject: [PATCH 25/37] Remove DynamicDispatchResult in benchmarking --- pallets/automation-time/src/benchmarking.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/pallets/automation-time/src/benchmarking.rs b/pallets/automation-time/src/benchmarking.rs index 10ae92099..2982089c8 100644 --- a/pallets/automation-time/src/benchmarking.rs +++ b/pallets/automation-time/src/benchmarking.rs @@ -327,9 +327,6 @@ benchmarks! { let call: ::Call = frame_system::Call::remark { remark: vec![] }.into(); let encoded_call = call.encode(); }: { AutomationTime::::run_dynamic_dispatch_action(caller.clone(), encoded_call, task_id.clone()) } - verify { - // assert_last_event::(Event::DynamicDispatchResult{ who: caller, task_id: task_id.clone(), result: Ok(()) }.into()) - } run_dynamic_dispatch_action_fail_decode { let caller: T::AccountId = account("caller", 0, SEED); From 0a33b0d614aad811864d05381b107cfa092fb0cb Mon Sep 17 00:00:00 2001 From: imstar15 Date: Mon, 31 Jul 2023 20:21:21 +0800 Subject: [PATCH 26/37] Rename TaskFailedToReschedule to TaskRescheduleFailed --- pallets/automation-time/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 55e622f94..c4ff38fd4 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -337,7 +337,7 @@ pub mod pallet { error: DispatchError, }, /// A recurring task attempted but failed to be rescheduled - TaskFailedToReschedule { + TaskRescheduleFailed { who: AccountOf, task_id: TaskIdV2, error: DispatchError, @@ -1486,7 +1486,7 @@ pub mod pallet { AccountTasks::::insert(owner_id.clone(), task_id, task.clone()); }, Err(err) => { - Self::deposit_event(Event::::TaskFailedToReschedule { + Self::deposit_event(Event::::TaskRescheduleFailed { who: task.owner_id.clone(), task_id: task_id.clone(), error: err, From 0a9f2020eed565b855691a3db2ddff2737d0ffc6 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Mon, 31 Jul 2023 20:55:27 +0800 Subject: [PATCH 27/37] Add comments --- pallets/automation-time/src/lib.rs | 5 ++++- pallets/automation-time/src/tests.rs | 32 ++++++++++++++++------------ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index c4ff38fd4..dac948ba5 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -351,6 +351,7 @@ pub mod pallet { task_id: TaskIdV2, condition: BTreeMap, encoded_call: Vec, + /// List of errors causing task abortion. abort_errors: Vec, }, TaskExecuted { @@ -535,6 +536,7 @@ pub mod pallet { }; let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; + // List of errors causing the auto compound task to be terminated. let errors: Vec = AUTO_COMPOUND_DELEGATION_ABORT_ERRORS .iter() .map(|&error| String::from(error)) @@ -1459,7 +1461,8 @@ pub mod pallet { mut task: TaskOf, dispatch_error: Option, ) { - // When the error can be found in the abort_errors list, the next task execution will not be scheduled. Otherwise, continue to execute the next task. + // When the error can be found in the abort_errors list, the next task execution will not be scheduled. + // Otherwise, continue to schedule next execution. match dispatch_error { Some(err) if task.abort_errors.contains(&String::from(Into::<&str>::into(err))) => { Self::deposit_event(Event::::TaskNotRescheduled { diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index f5326c731..df21f867a 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -2721,13 +2721,14 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { }) } -// Scheduling an auto compound delegated stake task will succeed if the account has not enough balance and a delegation with the specificed collator. +// If the account has not enough balance and a delegation with the specificed collator, +// the next execution of the task will be re-scheduled because the InsufficientBalance error is not an abort error // Condition: // 1. User's wallet balance < minimum balance + execution fee // 2. User has a delegation with the specificed collator // Expected result: // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegationDNE -// 2. Next execution will be scheduled +// 2. The next execution will be scheduled because the InsufficientBalance error is not an abort error #[test] fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { @@ -2763,7 +2764,7 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { emitted_events.clone().into_iter() .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { error, .. }) if *error == insufficient_balance_error )).expect("TaskExecutionFailed event should have been emitted"); - // 2. Next execution will be scheduled + // The next execution will be scheduled because the InsufficientBalance error is not an abort error emitted_events .into_iter() .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { .. }))) @@ -2783,13 +2784,14 @@ fn auto_compound_delegated_stake_not_enough_balance_has_delegation() { }) } -// Scheduling an auto compound delegated stake task will failed if the account has a sufficient balance and no delegator with the specificed collator. +// If the account has a sufficient balance and no delegator with the specificed collator, +// the next execution of the task will not be re-scheduled because the DelegatorDNE error is an abort error. // Condition: // 1. User's wallet balance >= minimum balance + execution fee -// 2. User has no delegation with the specificed collator +// 2. User has no delegator // Expected result: // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegatorDNE -// 2. Next execution will not be scheduled +// 2. The next execution will be scheduled because the DelegatorDNE error is not an abort error #[test] fn auto_compound_delegated_stake_enough_balance_no_delegator() { new_test_ext(START_BLOCK_TIME).execute_with(|| { @@ -2835,6 +2837,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegator() { }) .expect("TaskExecutionFailed event should have been emitted"); + // 2. The next execution will be scheduled because the DelegatorDNE error is not an abort error emitted_events .into_iter() .find(|e| { @@ -2846,7 +2849,6 @@ fn auto_compound_delegated_stake_enough_balance_no_delegator() { }) .expect("TaskNotRescheduled event should have been emitted"); - // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) .filter(|scheduled| { scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id.clone())) @@ -2856,13 +2858,14 @@ fn auto_compound_delegated_stake_enough_balance_no_delegator() { }) } -// Scheduling an auto compound delegated stake task will failed if the account has a sufficient balance and no delegation with the specificed collator. +// If the account has a sufficient balance and no delegator with the specificed collator, +// the next execution of the task will not be re-scheduled because the DelegationDNE error is an abort error. // Condition: // 1. User's wallet balance >= minimum balance + execution fee // 2. User has no delegation with the specificed collator // Expected result: // 1. The current execution will result in failure, triggering the emission of an TaskExecutionFailed event, error: DelegationDNE -// 2. Next execution will not be scheduled +// 2. The next execution will be scheduled because the DelegationDNE error is not an abort error #[test] fn auto_compound_delegated_stake_enough_balance_no_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { @@ -2908,6 +2911,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { }) .expect("TaskExecutionFailed event should have been emitted"); + // 2. The next execution will be scheduled because the DelegationDNE error is not an abort error emitted_events .into_iter() .find(|e| { @@ -2919,7 +2923,6 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { }) .expect("TaskNotRescheduled event should have been emitted"); - // 2. Next execution will not be scheduled assert!(AutomationTime::get_scheduled_tasks(SCHEDULED_TIME + frequency) .filter(|scheduled| { scheduled.tasks.iter().any(|t| *t == (delegator.clone(), task_id.clone())) @@ -2929,13 +2932,14 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { }) } -// Scheduling an auto compound delegated stake task will failed if the account has not enough balance and no delegation with the specificed collator. +// If the account has a sufficient balance and no delegator with the specificed collator, +// the next execution of the task will not be re-scheduled because the InsufficientBalance error is an abort error. // Condition: // 1. User's wallet balance < minimum balance + execution fee // 2. User has no delegation with the specificed collator // Expected result: -// 1. Emit TaskExecutionFailed event with error: DelegationDNE -// 2. Next execution will not be scheduled +// 1. Emit TaskExecutionFailed event with error: InsufficientBalance +// 2. The next execution will be scheduled because the InsufficientBalance error is not an abort error #[test] fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { new_test_ext(START_BLOCK_TIME).execute_with(|| { @@ -2980,7 +2984,7 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { }) .expect("TaskExecutionFailed event should have been emitted"); - // 2. Next execution will be scheduled + // 2. The next execution will be scheduled because the InsufficientBalance error is not an abort error emitted_events .into_iter() .find(|e| { From f8f67bd1ca9e2a19772bbb1d4b6f7253ed923fb0 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Tue, 1 Aug 2023 23:55:24 +0800 Subject: [PATCH 28/37] Add more checks in tests --- pallets/automation-time/src/tests.rs | 171 +++++++++++++++++++-------- 1 file changed, 123 insertions(+), 48 deletions(-) diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index df21f867a..eff2ed992 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -141,6 +141,43 @@ pub fn assert_last_event(event: RuntimeEvent) { assert_eq!(events().last().expect("events expected"), &event); } +/// Check that events appear in the emitted_events list in order, +fn contains_events(emitted_events: Vec, events: Vec) -> bool { + // If the target events list is empty, consider it satisfied as there are no specific order requirements + if events.is_empty() { + return true; + } + + // Convert both lists to iterators + let mut emitted_iter = emitted_events.iter(); + let mut events_iter = events.iter(); + + // Iterate through the target events + while let Some(target_event) = events_iter.next() { + // Initialize a boolean variable to track whether the target event is found + let mut found = false; + + // Continue iterating through the emitted events until a match is found or there are no more emitted events + while let Some(emitted_event) = emitted_iter.next() { + // Compare event type and event data for a match + if emitted_event == target_event { + // Target event found, mark as found and advance the emitted iterator + found = true; + break; + } + } + + // If the target event is not found, return false + if !found { + return false; + } + } + + // If all target events are found in order, return true + return true; +} + + // when schedule with a Fixed Time schedule and passing an epoch that isn't the // beginning of hour, raise an error // the smallest granularity unit we allow is hour @@ -332,38 +369,29 @@ fn schedule_transfer_with_dynamic_dispatch() { let mut condition: BTreeMap = BTreeMap::new(); condition.insert(String::from("type"), String::from("time")); condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); - assert_eq!( - my_events, - [ - RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { - who: account_id.clone(), - task_id: task_id.clone(), - condition, - encoded_call: call.encode(), - abort_errors: vec![], - }), - RuntimeEvent::System(frame_system::Event::NewAccount { - account: recipient.clone() - }), - RuntimeEvent::Balances(pallet_balances::pallet::Event::Endowed { - account: recipient.clone(), - free_balance: 127, - }), - RuntimeEvent::Balances(pallet_balances::pallet::Event::Transfer { - from: account_id.clone(), - to: recipient.clone(), - amount: 127, - }), - RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { - who: account_id.clone(), - task_id: task_id.clone(), - }), - RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: account_id, - task_id, - }), - ] - ); + + assert!(contains_events(my_events, vec![ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: account_id.clone(), + task_id: task_id.clone(), + condition, + encoded_call: call.encode(), + abort_errors: vec![], + }), + RuntimeEvent::Balances(pallet_balances::pallet::Event::Transfer { + from: account_id.clone(), + to: recipient.clone(), + amount: 127, + }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: account_id.clone(), + task_id: task_id.clone(), + }), + RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { + who: account_id, + task_id, + }), + ])); }) } @@ -498,7 +526,7 @@ fn will_emit_task_completed_event_when_task_failed() { assert_ok!(AutomationTime::schedule_dynamic_dispatch_task( RuntimeOrigin::signed(account_id.clone()), ScheduleParam::Fixed { execution_times: vec![SCHEDULED_TIME, next_execution_time] }, - Box::new(call), + Box::new(call.clone()), )); // First execution @@ -523,11 +551,31 @@ fn will_emit_task_completed_event_when_task_failed() { AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000)); let my_events = events(); - // When a task fails, the TaskCompleted event will still be emitted. - my_events - .into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. }))) - .expect("When a task fails, the TaskCompleted event will still be emitted"); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", next_execution_time)); + + assert!(contains_events( + my_events, + vec![ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: account_id.clone(), + task_id: task_id.clone(), + condition, + encoded_call: call.encode(), + abort_errors: vec![], + }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { + who: account_id.clone(), + task_id: task_id.clone(), + error: >::InsufficientBalance.into(), + }), + RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { + who: account_id.clone(), + task_id: task_id.clone(), + }), + ] + )) }) } @@ -1813,11 +1861,13 @@ mod run_dynamic_dispatch_action { let call: RuntimeCall = frame_system::Call::set_code { code: vec![] }.into(); let encoded_call = call.encode(); - AutomationTime::run_dynamic_dispatch_action( + let (_, error) = AutomationTime::run_dynamic_dispatch_action( account_id.clone(), encoded_call, task_id.clone(), ); + + assert_eq!(error, Some(DispatchError::BadOrigin)); }) } @@ -1829,11 +1879,13 @@ mod run_dynamic_dispatch_action { let call: RuntimeCall = pallet_timestamp::Call::set { now: 100 }.into(); let encoded_call = call.encode(); - AutomationTime::run_dynamic_dispatch_action( + let (_, error) = AutomationTime::run_dynamic_dispatch_action( account_id.clone(), encoded_call, task_id.clone(), ); + + assert_eq!(error, Some(DispatchError::from(frame_system::Error::::CallFiltered))); }) } @@ -1845,11 +1897,13 @@ mod run_dynamic_dispatch_action { let call: RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); let encoded_call = call.encode(); - AutomationTime::run_dynamic_dispatch_action( + let (_, error) = AutomationTime::run_dynamic_dispatch_action( account_id.clone(), encoded_call, task_id.clone(), ); + + assert_eq!(error, None); }) } } @@ -2069,6 +2123,7 @@ fn trigger_tasks_limits_missed_slots() { assert_eq!( my_events, [ + // The execution of encoded call task RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { who: owner.clone(), task_id: task_id.clone(), @@ -2088,6 +2143,7 @@ fn trigger_tasks_limits_missed_slots() { who: owner.clone(), task_id, }), + // The task 0 missed RuntimeEvent::AutomationTime(crate::Event::TaskMissed { who: owner.clone(), task_id: missing_task_id0.clone(), @@ -2097,6 +2153,7 @@ fn trigger_tasks_limits_missed_slots() { who: owner.clone(), task_id: missing_task_id0, }), + // The task 5 missed RuntimeEvent::AutomationTime(crate::Event::TaskMissed { who: owner.clone(), task_id: missing_task_id5.clone(), @@ -2106,6 +2163,7 @@ fn trigger_tasks_limits_missed_slots() { who: owner.clone(), task_id: missing_task_id5, }), + // The task 4 missed RuntimeEvent::AutomationTime(crate::Event::TaskMissed { who: owner.clone(), task_id: missing_task_id4.clone(), @@ -2115,6 +2173,7 @@ fn trigger_tasks_limits_missed_slots() { who: owner.clone(), task_id: missing_task_id4, }), + // The task 3 missed RuntimeEvent::AutomationTime(crate::Event::TaskMissed { who: owner.clone(), task_id: missing_task_id3.clone(), @@ -2610,10 +2669,11 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { get_funds(delegator.clone()); let before_balance = Balances::free_balance(delegator.clone()); let account_minimum = before_balance / 2; + let task_id = vec![1]; add_recurring_task_to_task_queue( DELEGATOR_ACCOUNT, - vec![1], + task_id.clone(), SCHEDULED_TIME, 3600, Action::AutoCompoundDelegatedStake { @@ -2634,11 +2694,24 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { assert!(new_balance < before_balance); assert_eq!(new_balance, account_minimum); - emitted_events - .clone() - .into_iter() - .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { .. }))) - .expect("TaskExecuted event should have been emitted"); + let mut condition: BTreeMap = BTreeMap::new(); + condition.insert(String::from("type"), String::from("time")); + condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + + assert!(contains_events(emitted_events, vec![ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: delegator.clone(), + task_id: task_id.clone(), + condition, + encoded_call: vec![], + abort_errors: vec![], + }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: delegator.clone(), + task_id: task_id.clone(), + }), + RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { who: delegator, task_id, schedule_as: None }) + ])); }) } @@ -2717,7 +2790,7 @@ fn auto_compound_delegated_stake_enough_balance_has_delegation() { events() .into_iter() .find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { .. }))) - .expect("AutoCompoundDelegatorStakeSucceeded event should have been emitted again!"); + .expect("TaskTriggered event should have been emitted again!"); }) } @@ -3161,6 +3234,7 @@ fn on_init_runs_tasks() { assert_eq!( events(), [ + // The execution of task 1 RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { who: owner.clone(), task_id: task_id1.clone(), @@ -3177,6 +3251,7 @@ fn on_init_runs_tasks() { who: owner.clone(), task_id: task_id1.clone(), }), + // The execution of task 2 RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { who: owner.clone(), task_id: task_id2.clone(), From 269dacfe21b9f7d77c934fb49b072109f4e64829 Mon Sep 17 00:00:00 2001 From: oak-code-formatter Date: Tue, 1 Aug 2023 15:56:14 +0000 Subject: [PATCH 29/37] fixup: auto format Rust code --- pallets/automation-time/src/tests.rs | 97 +++++++++++++++------------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index eff2ed992..e4e31bfba 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -145,7 +145,7 @@ pub fn assert_last_event(event: RuntimeEvent) { fn contains_events(emitted_events: Vec, events: Vec) -> bool { // If the target events list is empty, consider it satisfied as there are no specific order requirements if events.is_empty() { - return true; + return true } // Convert both lists to iterators @@ -163,21 +163,20 @@ fn contains_events(emitted_events: Vec, events: Vec) if emitted_event == target_event { // Target event found, mark as found and advance the emitted iterator found = true; - break; + break } } // If the target event is not found, return false if !found { - return false; + return false } } // If all target events are found in order, return true - return true; + return true } - // when schedule with a Fixed Time schedule and passing an epoch that isn't the // beginning of hour, raise an error // the smallest granularity unit we allow is hour @@ -370,28 +369,31 @@ fn schedule_transfer_with_dynamic_dispatch() { condition.insert(String::from("type"), String::from("time")); condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); - assert!(contains_events(my_events, vec![ - RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { - who: account_id.clone(), - task_id: task_id.clone(), - condition, - encoded_call: call.encode(), - abort_errors: vec![], - }), - RuntimeEvent::Balances(pallet_balances::pallet::Event::Transfer { - from: account_id.clone(), - to: recipient.clone(), - amount: 127, - }), - RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { - who: account_id.clone(), - task_id: task_id.clone(), - }), - RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { - who: account_id, - task_id, - }), - ])); + assert!(contains_events( + my_events, + vec![ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: account_id.clone(), + task_id: task_id.clone(), + condition, + encoded_call: call.encode(), + abort_errors: vec![], + }), + RuntimeEvent::Balances(pallet_balances::pallet::Event::Transfer { + from: account_id.clone(), + to: recipient.clone(), + amount: 127, + }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: account_id.clone(), + task_id: task_id.clone(), + }), + RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { + who: account_id, + task_id, + }), + ] + )); }) } @@ -565,12 +567,12 @@ fn will_emit_task_completed_event_when_task_failed() { encoded_call: call.encode(), abort_errors: vec![], }), - RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { + RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { who: account_id.clone(), task_id: task_id.clone(), error: >::InsufficientBalance.into(), }), - RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { + RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { who: account_id.clone(), task_id: task_id.clone(), }), @@ -2123,7 +2125,7 @@ fn trigger_tasks_limits_missed_slots() { assert_eq!( my_events, [ - // The execution of encoded call task + // The execution of encoded call task RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { who: owner.clone(), task_id: task_id.clone(), @@ -2698,20 +2700,27 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { condition.insert(String::from("type"), String::from("time")); condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); - assert!(contains_events(emitted_events, vec![ - RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { - who: delegator.clone(), - task_id: task_id.clone(), - condition, - encoded_call: vec![], - abort_errors: vec![], - }), - RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { - who: delegator.clone(), - task_id: task_id.clone(), - }), - RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { who: delegator, task_id, schedule_as: None }) - ])); + assert!(contains_events( + emitted_events, + vec![ + RuntimeEvent::AutomationTime(crate::Event::TaskTriggered { + who: delegator.clone(), + task_id: task_id.clone(), + condition, + encoded_call: vec![], + abort_errors: vec![], + }), + RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { + who: delegator.clone(), + task_id: task_id.clone(), + }), + RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { + who: delegator, + task_id, + schedule_as: None + }) + ] + )); }) } From 0584ce2ef45cba49d96c116e61cbcdbbc359439d Mon Sep 17 00:00:00 2001 From: imstar15 Date: Wed, 2 Aug 2023 11:30:08 +0800 Subject: [PATCH 30/37] Check dynamic dispatch error in bechmarking --- pallets/automation-time/src/benchmarking.rs | 11 +++--- pallets/automation-time/src/lib.rs | 36 +++++++------------ .../src/migrations/update_task_idv2.rs | 1 - .../src/migrations/update_xcmp_task.rs | 14 ++++---- .../automation-time/src/migrations/utils.rs | 2 +- pallets/automation-time/src/tests.rs | 32 +++-------------- pallets/automation-time/src/types.rs | 2 +- 7 files changed, 33 insertions(+), 65 deletions(-) diff --git a/pallets/automation-time/src/benchmarking.rs b/pallets/automation-time/src/benchmarking.rs index 2982089c8..c30dcbe17 100644 --- a/pallets/automation-time/src/benchmarking.rs +++ b/pallets/automation-time/src/benchmarking.rs @@ -326,16 +326,19 @@ benchmarks! { let task_id = vec![49, 45, 48, 45, 52]; let call: ::Call = frame_system::Call::remark { remark: vec![] }.into(); let encoded_call = call.encode(); - }: { AutomationTime::::run_dynamic_dispatch_action(caller.clone(), encoded_call, task_id.clone()) } + }: { + let (_, error) = AutomationTime::::run_dynamic_dispatch_action(caller.clone(), encoded_call, task_id.clone()); + assert_eq!(error, None); + } run_dynamic_dispatch_action_fail_decode { let caller: T::AccountId = account("caller", 0, SEED); let task_id = vec![49, 45, 48, 45, 52]; let bad_encoded_call: Vec = vec![1]; - }: { AutomationTime::::run_dynamic_dispatch_action(caller.clone(), bad_encoded_call, task_id.clone()) } - verify { - assert_last_event::(Event::CallCannotBeDecoded{ who: caller, task_id: task_id.clone() }.into()) + }: { + let (_, error) = AutomationTime::::run_dynamic_dispatch_action(caller.clone(), bad_encoded_call, task_id.clone()); + assert_eq!(error, Some(DispatchError::from(Error::::CallCannotBeDecoded))); } /* diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index dac948ba5..0837f85be 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -53,9 +53,9 @@ use codec::Decode; use core::convert::TryInto; use cumulus_primitives_core::ParaId; use frame_support::{ - dispatch::{DispatchErrorWithPostInfo, GetDispatchInfo, PostDispatchInfo}, + dispatch::{GetDispatchInfo, PostDispatchInfo}, pallet_prelude::*, - sp_runtime::traits::{CheckedSub, Hash}, + sp_runtime::traits::CheckedSub, storage::{ with_transaction, TransactionOutcome::{Commit, Rollback}, @@ -319,11 +319,6 @@ pub mod pallet { task_id: TaskIdV2, execution_time: UnixTime, }, - /// The call for the DynamicDispatch action can no longer be decoded. - CallCannotBeDecoded { - who: AccountOf, - task_id: TaskIdV2, - }, /// A recurring task was rescheduled TaskRescheduled { who: AccountOf, @@ -1216,15 +1211,10 @@ pub mod pallet { result.err(), ) }, - Err(_) => { - // TODO: If the call cannot be decoded then cancel the task. - - Self::deposit_event(Event::CallCannotBeDecoded { who: caller, task_id }); - ( - ::WeightInfo::run_dynamic_dispatch_action_fail_decode(), - Some(Error::::CallCannotBeDecoded.into()), - ) - }, + Err(_) => ( + ::WeightInfo::run_dynamic_dispatch_action_fail_decode(), + Some(Error::::CallCannotBeDecoded.into()), + ), } } @@ -1456,15 +1446,15 @@ pub mod pallet { Ok(()) } - fn reschedule_or_remove_task( - task_id: TaskIdV2, - mut task: TaskOf, - dispatch_error: Option, - ) { + fn reschedule_or_remove_task(mut task: TaskOf, dispatch_error: Option) { + let task_id = task.task_id.clone(); // When the error can be found in the abort_errors list, the next task execution will not be scheduled. // Otherwise, continue to schedule next execution. match dispatch_error { - Some(err) if task.abort_errors.contains(&String::from(Into::<&str>::into(err))) => { + Some(err) + if err == DispatchError::from(Error::::CallCannotBeDecoded) || + task.abort_errors.contains(&String::from(Into::<&str>::into(err))) => + { Self::deposit_event(Event::::TaskNotRescheduled { who: task.owner_id.clone(), task_id: task_id.clone(), @@ -1533,7 +1523,7 @@ pub mod pallet { match task.schedule { Schedule::Fixed { .. } => Self::decrement_task_and_remove_if_complete(task_id, task), - Schedule::Recurring { .. } => Self::reschedule_or_remove_task(task_id, task, error), + Schedule::Recurring { .. } => Self::reschedule_or_remove_task(task, error), } } diff --git a/pallets/automation-time/src/migrations/update_task_idv2.rs b/pallets/automation-time/src/migrations/update_task_idv2.rs index a61e33975..4202daa4b 100644 --- a/pallets/automation-time/src/migrations/update_task_idv2.rs +++ b/pallets/automation-time/src/migrations/update_task_idv2.rs @@ -202,7 +202,6 @@ mod test { }; use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; use sp_runtime::AccountId32; - use xcm::latest::prelude::*; #[test] fn on_runtime_upgrade() { diff --git a/pallets/automation-time/src/migrations/update_xcmp_task.rs b/pallets/automation-time/src/migrations/update_xcmp_task.rs index 37e8fce34..46acffb87 100644 --- a/pallets/automation-time/src/migrations/update_xcmp_task.rs +++ b/pallets/automation-time/src/migrations/update_xcmp_task.rs @@ -1,16 +1,13 @@ use core::marker::PhantomData; use crate::{ - weights::WeightInfo, AccountOf, ActionOf, AssetPayment, BalanceOf, Config, InstructionSequence, - Schedule, TaskOf, + weights::WeightInfo, AccountOf, ActionOf, AssetPayment, Config, InstructionSequence, TaskOf, }; use codec::{Decode, Encode}; -use cumulus_primitives_core::ParaId; use frame_support::{traits::OnRuntimeUpgrade, weights::Weight, Twox64Concat}; -use scale_info::TypeInfo; use sp_runtime::traits::Convert; use sp_std::{vec, vec::Vec}; -use xcm::{latest::prelude::*, VersionedMultiLocation}; +use xcm::latest::prelude::*; use crate::migrations::utils::{ deprecate::{generate_old_task_id, old_taskid_to_idv2}, @@ -75,7 +72,7 @@ impl OnRuntimeUpgrade for UpdateXcmpTask { log::info!(target: "automation-time", "UpdateXcmpTask migration"); let mut migrated_tasks = 0u32; - AccountTasks::::iter().for_each(|(account_id, task_id, task)| { + AccountTasks::::iter().for_each(|(account_id, _task_id, task)| { let migrated_task: TaskOf = task.into(); crate::AccountTasks::::insert( account_id, @@ -115,10 +112,11 @@ impl OnRuntimeUpgrade for UpdateXcmpTask { #[cfg(test)] mod test { use super::{ - generate_old_task_id, OldAction, OldTask, ParaId, UpdateXcmpTask, EXECUTION_FEE_AMOUNT, + generate_old_task_id, OldAction, OldTask, UpdateXcmpTask, EXECUTION_FEE_AMOUNT, INSTRUCTION_WEIGHT_REF_TIME, TEST_TASKID1, }; - use crate::{mock::*, ActionOf, AssetPayment, InstructionSequence, Pallet, Schedule, TaskOf}; + use crate::{mock::*, ActionOf, AssetPayment, InstructionSequence, Schedule, TaskOf}; + use cumulus_primitives_core::ParaId; use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; use sp_runtime::AccountId32; use xcm::latest::prelude::*; diff --git a/pallets/automation-time/src/migrations/utils.rs b/pallets/automation-time/src/migrations/utils.rs index 5efd49086..4faa8499f 100644 --- a/pallets/automation-time/src/migrations/utils.rs +++ b/pallets/automation-time/src/migrations/utils.rs @@ -16,7 +16,7 @@ use frame_support::{ use scale_info::{prelude::format, TypeInfo}; use sp_runtime::traits::Convert; use sp_std::{vec, vec::Vec}; -use xcm::{latest::prelude::*, VersionedMultiLocation}; +use xcm::VersionedMultiLocation; // These are H256/BlakeTwo256 hex generate from our old task id generation from hashing // These cons are used for our unit test diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index e4e31bfba..bb5de0724 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -135,12 +135,6 @@ pub fn assert_has_event(event: RuntimeEvent) { assert!(evts.iter().any(|record| record == &event)) } -/// Assert the last event equal to the given `event`. -#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))] -pub fn assert_last_event(event: RuntimeEvent) { - assert_eq!(events().last().expect("events expected"), &event); -} - /// Check that events appear in the emitted_events list in order, fn contains_events(emitted_events: Vec, events: Vec) -> bool { // If the target events list is empty, consider it satisfied as there are no specific order requirements @@ -174,7 +168,7 @@ fn contains_events(emitted_events: Vec, events: Vec) } // If all target events are found in order, return true - return true + true } // when schedule with a Fixed Time schedule and passing an epoch that isn't the @@ -403,7 +397,6 @@ fn will_emit_task_completed_event_when_task_completed() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let frequency = 3_600; let account_id = AccountId32::new(ALICE); - let provided_id = vec![1, 2]; let task_id = FIRST_TASK_ID.to_vec().clone(); fund_account(&account_id, 900_000_000, 2, Some(0)); @@ -454,7 +447,6 @@ fn will_not_emit_task_completed_event_when_task_canceled() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let frequency = 3_600; let account_id = AccountId32::new(ALICE); - let provided_id = vec![1, 2]; let task_id = FIRST_TASK_ID.to_vec(); fund_account(&account_id, 900_000_000, 2, Some(0)); @@ -510,7 +502,6 @@ fn will_emit_task_completed_event_when_task_failed() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let frequency = 3_600; let account_id = AccountId32::new(ALICE); - let provided_id = vec![1, 2]; let task_id = FIRST_TASK_ID.to_vec(); fund_account(&account_id, 900_000_000, 2, Some(0)); @@ -1668,14 +1659,6 @@ fn cancel_works_for_tasks_in_queue() { #[test] fn cancel_task_must_exist() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - let task = TaskOf::::create_event_task::( - AccountId32::new(ALICE), - vec![40], - vec![SCHEDULED_TIME], - vec![2, 4, 5], - vec![], - ) - .unwrap(); //let task_id = BlakeTwo256::hash_of(&task); let task_id = vec![49, 45, 48, 45, 52]; @@ -1835,7 +1818,7 @@ mod run_dynamic_dispatch_action { let task_id = vec![49, 45, 48, 45, 52]; let bad_encoded_call: Vec = vec![1]; - let (weight, _) = AutomationTime::run_dynamic_dispatch_action( + let (weight, error) = AutomationTime::run_dynamic_dispatch_action( account_id.clone(), bad_encoded_call, task_id.clone(), @@ -1845,13 +1828,8 @@ mod run_dynamic_dispatch_action { weight, ::WeightInfo::run_dynamic_dispatch_action_fail_decode() ); - assert_eq!( - events(), - [RuntimeEvent::AutomationTime(crate::Event::CallCannotBeDecoded { - who: account_id, - task_id: task_id.clone(), - }),] - ); + + assert_eq!(error, Some(DispatchError::from(Error::::CallCannotBeDecoded))); }) } @@ -2717,7 +2695,7 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { RuntimeEvent::AutomationTime(crate::Event::TaskRescheduled { who: delegator, task_id, - schedule_as: None + schedule_as: None, }) ] )); diff --git a/pallets/automation-time/src/types.rs b/pallets/automation-time/src/types.rs index d930bec20..9b231dbc3 100644 --- a/pallets/automation-time/src/types.rs +++ b/pallets/automation-time/src/types.rs @@ -3,7 +3,7 @@ use crate::{weights::WeightInfo, Config, Error, InstructionSequence, Pallet}; use frame_support::{dispatch::GetDispatchInfo, pallet_prelude::*, traits::Get}; use scale_info::prelude::string::String; -use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion, Printable}; +use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion}; use sp_std::prelude::*; use pallet_automation_time_rpc_runtime_api::AutomationAction; From 588c0ee8ff42b0ef9b10976771e747197d739f4e Mon Sep 17 00:00:00 2001 From: imstar15 Date: Wed, 2 Aug 2023 12:11:03 +0800 Subject: [PATCH 31/37] Remove abort_errors in TaskTriggered event --- pallets/automation-time/src/benchmarking.rs | 6 +-- pallets/automation-time/src/lib.rs | 11 ----- pallets/automation-time/src/tests.rs | 54 ++++----------------- 3 files changed, 12 insertions(+), 59 deletions(-) diff --git a/pallets/automation-time/src/benchmarking.rs b/pallets/automation-time/src/benchmarking.rs index c30dcbe17..9702c2ac3 100644 --- a/pallets/automation-time/src/benchmarking.rs +++ b/pallets/automation-time/src/benchmarking.rs @@ -319,7 +319,7 @@ benchmarks! { T::DelegatorActions::setup_delegator(&collator, &delegator)?; let (task_id, task) = schedule_auto_compound_delegated_stake_tasks::(delegator.clone(), 3600, 1).pop().unwrap(); - }: { AutomationTime::::run_auto_compound_delegated_stake_task(delegator, collator, account_minimum, task_id.clone(), &task) } + }: { AutomationTime::::run_auto_compound_delegated_stake_task(delegator, collator, account_minimum, &task) } run_dynamic_dispatch_action { let caller: T::AccountId = account("caller", 0, SEED); @@ -327,7 +327,7 @@ benchmarks! { let call: ::Call = frame_system::Call::remark { remark: vec![] }.into(); let encoded_call = call.encode(); }: { - let (_, error) = AutomationTime::::run_dynamic_dispatch_action(caller.clone(), encoded_call, task_id.clone()); + let (_, error) = AutomationTime::::run_dynamic_dispatch_action(caller.clone(), encoded_call); assert_eq!(error, None); } @@ -337,7 +337,7 @@ benchmarks! { let bad_encoded_call: Vec = vec![1]; }: { - let (_, error) = AutomationTime::::run_dynamic_dispatch_action(caller.clone(), bad_encoded_call, task_id.clone()); + let (_, error) = AutomationTime::::run_dynamic_dispatch_action(caller.clone(), bad_encoded_call); assert_eq!(error, Some(DispatchError::from(Error::::CallCannotBeDecoded))); } diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 0837f85be..7c30132c8 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -309,10 +309,6 @@ pub mod pallet { task_id: TaskIdV2, error: DispatchError, }, - SuccesfullyAutoCompoundedDelegatorStake { - task_id: TaskIdV2, - amount: BalanceOf, - }, /// The task could not be run at the scheduled time. TaskMissed { who: AccountOf, @@ -346,8 +342,6 @@ pub mod pallet { task_id: TaskIdV2, condition: BTreeMap, encoded_call: Vec, - /// List of errors causing task abortion. - abort_errors: Vec, }, TaskExecuted { who: AccountOf, @@ -929,7 +923,6 @@ pub mod pallet { task_id: task_id.clone(), condition, encoded_call, - abort_errors: task.abort_errors.clone(), }); let (task_action_weight, dispatch_error) = match task.action.clone() { @@ -968,14 +961,12 @@ pub mod pallet { delegator, collator, account_minimum, - task_id.clone(), &task, ), Action::DynamicDispatch { encoded_call } => Self::run_dynamic_dispatch_action( task.owner_id.clone(), encoded_call, - task_id.clone(), ), }; @@ -1138,7 +1129,6 @@ pub mod pallet { delegator: AccountOf, collator: AccountOf, account_minimum: BalanceOf, - task_id: TaskIdV2, task: &TaskOf, ) -> (Weight, Option) { let fee_amount = Self::calculate_schedule_fee_amount(&task.action, 1); @@ -1183,7 +1173,6 @@ pub mod pallet { pub fn run_dynamic_dispatch_action( caller: AccountOf, encoded_call: Vec, - task_id: TaskIdV2, ) -> (Weight, Option) { match ::Call::decode(&mut &*encoded_call) { Ok(scheduled_call) => { diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index bb5de0724..25994da41 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -371,7 +371,6 @@ fn schedule_transfer_with_dynamic_dispatch() { task_id: task_id.clone(), condition, encoded_call: call.encode(), - abort_errors: vec![], }), RuntimeEvent::Balances(pallet_balances::pallet::Event::Transfer { from: account_id.clone(), @@ -556,7 +555,6 @@ fn will_emit_task_completed_event_when_task_failed() { task_id: task_id.clone(), condition, encoded_call: call.encode(), - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { who: account_id.clone(), @@ -1267,7 +1265,6 @@ fn schedule_time_slot_full_rolls_back() { #[test] fn taskid_changed_per_block() { new_test_ext(START_BLOCK_TIME).execute_with(|| { - let owner = AccountId32::new(ALICE); let task_id1 = schedule_task( ALICE, vec![SCHEDULED_TIME, SCHEDULED_TIME + 3600, SCHEDULED_TIME + 7200], @@ -1571,7 +1568,6 @@ fn cancel_works_for_an_executed_task() { task_id: task_id1.clone(), condition, encoded_call: call.encode(), - abort_errors: vec![], }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), @@ -1815,14 +1811,10 @@ mod run_dynamic_dispatch_action { fn cannot_decode() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let account_id = AccountId32::new(ALICE); - let task_id = vec![49, 45, 48, 45, 52]; let bad_encoded_call: Vec = vec![1]; - let (weight, error) = AutomationTime::run_dynamic_dispatch_action( - account_id.clone(), - bad_encoded_call, - task_id.clone(), - ); + let (weight, error) = + AutomationTime::run_dynamic_dispatch_action(account_id.clone(), bad_encoded_call); assert_eq!( weight, @@ -1837,15 +1829,11 @@ mod run_dynamic_dispatch_action { fn call_errors() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let account_id = AccountId32::new(ALICE); - let task_id = vec![49, 45, 48, 45, 52]; let call: RuntimeCall = frame_system::Call::set_code { code: vec![] }.into(); let encoded_call = call.encode(); - let (_, error) = AutomationTime::run_dynamic_dispatch_action( - account_id.clone(), - encoded_call, - task_id.clone(), - ); + let (_, error) = + AutomationTime::run_dynamic_dispatch_action(account_id.clone(), encoded_call); assert_eq!(error, Some(DispatchError::BadOrigin)); }) @@ -1855,15 +1843,11 @@ mod run_dynamic_dispatch_action { fn call_filtered() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let account_id = AccountId32::new(ALICE); - let task_id = FIRST_TASK_ID.to_vec(); let call: RuntimeCall = pallet_timestamp::Call::set { now: 100 }.into(); let encoded_call = call.encode(); - let (_, error) = AutomationTime::run_dynamic_dispatch_action( - account_id.clone(), - encoded_call, - task_id.clone(), - ); + let (_, error) = + AutomationTime::run_dynamic_dispatch_action(account_id.clone(), encoded_call); assert_eq!(error, Some(DispatchError::from(frame_system::Error::::CallFiltered))); }) @@ -1873,15 +1857,11 @@ mod run_dynamic_dispatch_action { fn call_works() { new_test_ext(START_BLOCK_TIME).execute_with(|| { let account_id = AccountId32::new(ALICE); - let task_id = FIRST_TASK_ID.to_vec(); let call: RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); let encoded_call = call.encode(); - let (_, error) = AutomationTime::run_dynamic_dispatch_action( - account_id.clone(), - encoded_call, - task_id.clone(), - ); + let (_, error) = + AutomationTime::run_dynamic_dispatch_action(account_id.clone(), encoded_call); assert_eq!(error, None); }) @@ -2020,7 +2000,6 @@ fn trigger_tasks_handles_missed_slots() { task_id: task_will_be_run_id.clone(), condition, encoded_call: call.encode(), - abort_errors: vec![], }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: AccountId32::new(ALICE), @@ -2084,7 +2063,7 @@ fn trigger_tasks_limits_missed_slots() { LastTimeSlot::::put((SCHEDULED_TIME - 25200, SCHEDULED_TIME - 25200)); System::reset_events(); - let left_weight = AutomationTime::trigger_tasks(Weight::from_ref_time(7_769_423 + 200_000)); + AutomationTime::trigger_tasks(Weight::from_ref_time(7_769_423 + 200_000)); let my_events = events(); @@ -2109,7 +2088,6 @@ fn trigger_tasks_limits_missed_slots() { task_id: task_id.clone(), condition: condition.clone(), encoded_call: call.encode(), - abort_errors: vec![], }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), @@ -2227,7 +2205,6 @@ fn trigger_tasks_completes_all_tasks() { task_id: task_id1.clone(), condition: condition.clone(), encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -2243,7 +2220,6 @@ fn trigger_tasks_completes_all_tasks() { task_id: task_id2.clone(), condition, encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -2321,7 +2297,6 @@ fn trigger_tasks_completes_some_tasks() { task_id: task_id1.clone(), condition, encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -2522,7 +2497,6 @@ fn missed_tasks_removes_completed_tasks() { task_id: task_id01.clone(), condition: condition.clone(), encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -2630,7 +2604,6 @@ fn trigger_tasks_completes_some_xcmp_tasks() { task_id: task_id.clone(), condition, encoded_call, - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { who: owner.clone(), @@ -2686,7 +2659,6 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { task_id: task_id.clone(), condition, encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { who: delegator.clone(), @@ -3107,7 +3079,6 @@ fn trigger_tasks_updates_executions_left() { task_id: task_id01.clone(), condition, encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3166,7 +3137,6 @@ fn trigger_tasks_removes_completed_tasks() { task_id: task_id01.clone(), condition, encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3227,7 +3197,6 @@ fn on_init_runs_tasks() { task_id: task_id1.clone(), condition: condition.clone(), encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3244,7 +3213,6 @@ fn on_init_runs_tasks() { task_id: task_id2.clone(), condition, encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3321,7 +3289,6 @@ fn on_init_check_task_queue() { task_id: tasks[0].clone(), condition: condition.clone(), encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![0] }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3337,7 +3304,6 @@ fn on_init_check_task_queue() { task_id: tasks[1].clone(), condition: condition.clone(), encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![1] }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3363,7 +3329,6 @@ fn on_init_check_task_queue() { task_id: tasks[2].clone(), condition: condition.clone(), encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![2] }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3379,7 +3344,6 @@ fn on_init_check_task_queue() { task_id: tasks[3].clone(), condition: condition.clone(), encoded_call: vec![], - abort_errors: vec![], }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![3] }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { From 70acadec2b9561f59874c8672f3415e467680f0f Mon Sep 17 00:00:00 2001 From: imstar15 Date: Thu, 3 Aug 2023 01:20:35 +0800 Subject: [PATCH 32/37] Deposit DelegationIncreased event in MockDelegatorActions --- pallets/automation-time/src/mock.rs | 6 ++++++ pallets/automation-time/src/tests.rs | 24 +++++++++++++++++++----- runtime/turing/src/lib.rs | 2 -- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index e351a8bc0..85b9482bb 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -266,6 +266,12 @@ impl< let delegation: u128 = amount.saturated_into(); C::reserve(delegator, delegation.saturated_into())?; + System::deposit_event(pallet_parachain_staking::Event::DelegationIncreased { + delegator: AccountId::from(DELEGATOR_ACCOUNT), + candidate: AccountId::from(COLLATOR_ACCOUNT), + amount: delegation, + in_top: true, + }); Ok(true) } diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 25994da41..5c2251b9e 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -2624,16 +2624,18 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { let account_minimum = before_balance / 2; let task_id = vec![1]; + let action = Action::AutoCompoundDelegatedStake { + delegator: delegator.clone(), + collator: AccountId32::new(COLLATOR_ACCOUNT), + account_minimum, + }; + add_recurring_task_to_task_queue( DELEGATOR_ACCOUNT, task_id.clone(), SCHEDULED_TIME, 3600, - Action::AutoCompoundDelegatedStake { - delegator: delegator.clone(), - collator: AccountId32::new(COLLATOR_ACCOUNT), - account_minimum, - }, + action.clone(), vec![], ); @@ -2647,6 +2649,10 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { assert!(new_balance < before_balance); assert_eq!(new_balance, account_minimum); + let fee_amount = AutomationTime::calculate_schedule_fee_amount(&action, 1) + .expect(EXPECT_CALCULATE_SCHEDULE_FEE_AMOUNT); + let delegation = before_balance - fee_amount - account_minimum; + let mut condition: BTreeMap = BTreeMap::new(); condition.insert(String::from("type"), String::from("time")); condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); @@ -2660,6 +2666,14 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { condition, encoded_call: vec![], }), + RuntimeEvent::ParachainStaking( + pallet_parachain_staking::Event::DelegationIncreased { + delegator: AccountId::from(DELEGATOR_ACCOUNT), + candidate: AccountId::from(COLLATOR_ACCOUNT), + amount: delegation, + in_top: true, + } + ), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { who: delegator.clone(), task_id: task_id.clone(), diff --git a/runtime/turing/src/lib.rs b/runtime/turing/src/lib.rs index af156d929..17cab9d2e 100644 --- a/runtime/turing/src/lib.rs +++ b/runtime/turing/src/lib.rs @@ -1205,8 +1205,6 @@ impl_runtime_apis! { let fee_handler = ::FeeHandler::new(&nobody, &action, executions) .map_err(|_| "Unable to parse fee".as_bytes())?; - log::error!("fee_handler.schedule_fee_amount: {:?}", fee_handler.schedule_fee_amount); - log::error!("fee_handler.execution_fee_amount: {:?}", fee_handler.execution_fee_amount); Ok(AutomationFeeDetails { schedule_fee: fee_handler.schedule_fee_amount.into(), execution_fee: fee_handler.execution_fee_amount.into() From ac9d6009df97193a513436f967c747d3f95a4088 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Thu, 3 Aug 2023 10:14:00 +0800 Subject: [PATCH 33/37] Rename cancel_errors to abort_errors in mock.rs --- pallets/automation-time/src/mock.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 85b9482bb..3cb386f30 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -602,10 +602,10 @@ pub fn add_task_to_task_queue( task_id: TaskIdV2, scheduled_times: Vec, action: ActionOf, - cancel_errors: Vec, + abort_errors: Vec, ) -> TaskIdV2 { let schedule = Schedule::new_fixed_schedule::(scheduled_times).unwrap(); - add_to_task_queue(owner, task_id, schedule, action, cancel_errors) + add_to_task_queue(owner, task_id, schedule, action, abort_errors) } pub fn add_recurring_task_to_task_queue( @@ -639,10 +639,10 @@ pub fn add_task_to_missed_queue( task_id: TaskIdV2, scheduled_times: Vec, action: ActionOf, - cancel_errors: Vec, + abort_errors: Vec, ) -> TaskIdV2 { let schedule = Schedule::new_fixed_schedule::(scheduled_times.clone()).unwrap(); - let task_id = create_task(owner, task_id.clone(), schedule, action, cancel_errors); + let task_id = create_task(owner, task_id.clone(), schedule, action, abort_errors); let missed_task = MissedTaskV2Of::::new(AccountId32::new(owner), task_id.clone(), scheduled_times[0]); let mut missed_queue = AutomationTime::get_missed_queue(); From 03137e2695f3b2315121ed8927599ae4826acd0a Mon Sep 17 00:00:00 2001 From: imstar15 Date: Thu, 3 Aug 2023 10:27:11 +0800 Subject: [PATCH 34/37] Revert assert_last_event and add allow(dead_code) annotation on it --- pallets/automation-time/src/migrations/update_xcmp_task.rs | 2 +- pallets/automation-time/src/tests.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pallets/automation-time/src/migrations/update_xcmp_task.rs b/pallets/automation-time/src/migrations/update_xcmp_task.rs index 886629cf6..51be2a7b3 100644 --- a/pallets/automation-time/src/migrations/update_xcmp_task.rs +++ b/pallets/automation-time/src/migrations/update_xcmp_task.rs @@ -74,7 +74,7 @@ impl OnRuntimeUpgrade for UpdateXcmpTask { let mut migrated_tasks = 0u32; let mut tasks: Vec<(AccountOf, TaskOf)> = vec![]; - AccountTasks::::drain().for_each(|(account_id, task_id, task)| { + AccountTasks::::drain().for_each(|(account_id, _task_id, task)| { let migrated_task: TaskOf = task.into(); tasks.push((account_id, migrated_task)); migrated_tasks += 1; diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index 5c2251b9e..f68b08f3f 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -135,6 +135,12 @@ pub fn assert_has_event(event: RuntimeEvent) { assert!(evts.iter().any(|record| record == &event)) } +#[allow(dead_code)] +#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))] +pub fn assert_last_event(event: RuntimeEvent) { + assert_eq!(events().last().expect("events expected"), &event); +} + /// Check that events appear in the emitted_events list in order, fn contains_events(emitted_events: Vec, events: Vec) -> bool { // If the target events list is empty, consider it satisfied as there are no specific order requirements From 0843dda8206c93cde009b0757d1042762fa0fe63 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Thu, 3 Aug 2023 15:27:44 +0800 Subject: [PATCH 35/37] Update parachain-staking library --- Cargo.lock | 2 +- pallets/automation-time/src/mock.rs | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46bc48e04..0dab0812c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6483,7 +6483,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-staging#f9541fe1a0a3005947c5bc87ecc3d272f7741b1e" +source = "git+https://github.com/OAK-Foundation/moonbeam?branch=oak-staging#ff1ac38ebac1cab57c43620cd65369450357f971" dependencies = [ "frame-benchmarking", "frame-support 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 3cb386f30..0d850b469 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -275,14 +275,6 @@ impl< Ok(true) } - fn is_delegation_exist(delegator: &T::AccountId, candidate: &T::AccountId) -> bool { - let has_delegator = - *delegator == T::AccountId::decode(&mut DELEGATOR_ACCOUNT.as_ref()).unwrap(); - let has_delegation = - *candidate == T::AccountId::decode(&mut COLLATOR_ACCOUNT.as_ref()).unwrap(); - has_delegator && has_delegation - } - fn get_delegator_stakable_free_balance(delegator: &T::AccountId) -> BalanceOf { C::free_balance(delegator) } From 4049d667fc7fb69259549ae165e98f8d16c45e13 Mon Sep 17 00:00:00 2001 From: imstar15 Date: Thu, 3 Aug 2023 15:42:21 +0800 Subject: [PATCH 36/37] Change the type of encoded_call in TaskTriggered event --- pallets/automation-time/src/lib.rs | 8 +++--- pallets/automation-time/src/tests.rs | 38 ++++++++++++++-------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 7c30132c8..9c11ec4fe 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -341,7 +341,7 @@ pub mod pallet { who: AccountOf, task_id: TaskIdV2, condition: BTreeMap, - encoded_call: Vec, + encoded_call: Option>, }, TaskExecuted { who: AccountOf, @@ -913,9 +913,9 @@ pub mod pallet { condition.insert(String::from("timestamp"), format!("{}", time_slot)); let encoded_call = match task.action.clone() { - Action::XCMP { encoded_call, .. } => encoded_call, - Action::DynamicDispatch { encoded_call } => encoded_call, - _ => vec![], + Action::XCMP { encoded_call, .. } => Some(encoded_call), + Action::DynamicDispatch { encoded_call } => Some(encoded_call), + _ => None, }; Self::deposit_event(Event::TaskTriggered { diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index f68b08f3f..c667b9a4d 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -376,7 +376,7 @@ fn schedule_transfer_with_dynamic_dispatch() { who: account_id.clone(), task_id: task_id.clone(), condition, - encoded_call: call.encode(), + encoded_call: Some(call.encode()), }), RuntimeEvent::Balances(pallet_balances::pallet::Event::Transfer { from: account_id.clone(), @@ -560,7 +560,7 @@ fn will_emit_task_completed_event_when_task_failed() { who: account_id.clone(), task_id: task_id.clone(), condition, - encoded_call: call.encode(), + encoded_call: Some(call.encode()), }), RuntimeEvent::AutomationTime(crate::Event::TaskExecutionFailed { who: account_id.clone(), @@ -1573,7 +1573,7 @@ fn cancel_works_for_an_executed_task() { who: owner.clone(), task_id: task_id1.clone(), condition, - encoded_call: call.encode(), + encoded_call: Some(call.encode()), }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), @@ -2005,7 +2005,7 @@ fn trigger_tasks_handles_missed_slots() { who: owner.clone(), task_id: task_will_be_run_id.clone(), condition, - encoded_call: call.encode(), + encoded_call: Some(call.encode()), }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: AccountId32::new(ALICE), @@ -2093,7 +2093,7 @@ fn trigger_tasks_limits_missed_slots() { who: owner.clone(), task_id: task_id.clone(), condition: condition.clone(), - encoded_call: call.encode(), + encoded_call: Some(call.encode()), }), RuntimeEvent::System(frame_system::pallet::Event::Remarked { sender: owner.clone(), @@ -2210,7 +2210,7 @@ fn trigger_tasks_completes_all_tasks() { who: owner.clone(), task_id: task_id1.clone(), condition: condition.clone(), - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -2225,7 +2225,7 @@ fn trigger_tasks_completes_all_tasks() { who: owner.clone(), task_id: task_id2.clone(), condition, - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -2302,7 +2302,7 @@ fn trigger_tasks_completes_some_tasks() { who: owner.clone(), task_id: task_id1.clone(), condition, - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -2502,7 +2502,7 @@ fn missed_tasks_removes_completed_tasks() { who: owner.clone(), task_id: task_id01.clone(), condition: condition.clone(), - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -2609,7 +2609,7 @@ fn trigger_tasks_completes_some_xcmp_tasks() { who: owner.clone(), task_id: task_id.clone(), condition, - encoded_call, + encoded_call: Some(encoded_call), }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { who: owner.clone(), @@ -2670,7 +2670,7 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { who: delegator.clone(), task_id: task_id.clone(), condition, - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::ParachainStaking( pallet_parachain_staking::Event::DelegationIncreased { @@ -3098,7 +3098,7 @@ fn trigger_tasks_updates_executions_left() { who: owner.clone(), task_id: task_id01.clone(), condition, - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3156,7 +3156,7 @@ fn trigger_tasks_removes_completed_tasks() { who: owner.clone(), task_id: task_id01.clone(), condition, - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3216,7 +3216,7 @@ fn on_init_runs_tasks() { who: owner.clone(), task_id: task_id1.clone(), condition: condition.clone(), - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_one.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3232,7 +3232,7 @@ fn on_init_runs_tasks() { who: owner.clone(), task_id: task_id2.clone(), condition, - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: message_two.clone() }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3308,7 +3308,7 @@ fn on_init_check_task_queue() { who: owner.clone(), task_id: tasks[0].clone(), condition: condition.clone(), - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![0] }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3323,7 +3323,7 @@ fn on_init_check_task_queue() { who: owner.clone(), task_id: tasks[1].clone(), condition: condition.clone(), - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![1] }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3348,7 +3348,7 @@ fn on_init_check_task_queue() { who: owner.clone(), task_id: tasks[2].clone(), condition: condition.clone(), - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![2] }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { @@ -3363,7 +3363,7 @@ fn on_init_check_task_queue() { who: owner.clone(), task_id: tasks[3].clone(), condition: condition.clone(), - encoded_call: vec![], + encoded_call: None, }), RuntimeEvent::AutomationTime(crate::Event::Notify { message: vec![3] }), RuntimeEvent::AutomationTime(crate::Event::TaskExecuted { From aa620dd6094c34119f5485440f146e5121f18b9c Mon Sep 17 00:00:00 2001 From: imstar15 Date: Thu, 3 Aug 2023 17:04:55 +0800 Subject: [PATCH 37/37] Change the type of abort_errors to Vec> --- pallets/automation-time/src/lib.rs | 25 ++--- .../src/migrations/update_xcmp_task.rs | 1 + pallets/automation-time/src/mock.rs | 10 +- pallets/automation-time/src/tests.rs | 92 ++++++++++--------- pallets/automation-time/src/types.rs | 11 +-- 5 files changed, 71 insertions(+), 68 deletions(-) diff --git a/pallets/automation-time/src/lib.rs b/pallets/automation-time/src/lib.rs index 9c11ec4fe..93c9daaf4 100644 --- a/pallets/automation-time/src/lib.rs +++ b/pallets/automation-time/src/lib.rs @@ -70,10 +70,7 @@ use pallet_timestamp::{self as timestamp}; pub use pallet_xcmp_handler::InstructionSequence; use pallet_xcmp_handler::XcmpTransactor; use primitives::EnsureProxy; -use scale_info::{ - prelude::{format, string::String}, - TypeInfo, -}; +use scale_info::{prelude::format, TypeInfo}; use sp_runtime::{ traits::{CheckedConversion, Convert, Dispatchable, SaturatedConversion, Saturating}, ArithmeticError, DispatchError, Perbill, @@ -340,7 +337,7 @@ pub mod pallet { TaskTriggered { who: AccountOf, task_id: TaskIdV2, - condition: BTreeMap, + condition: BTreeMap, Vec>, encoded_call: Option>, }, TaskExecuted { @@ -526,9 +523,9 @@ pub mod pallet { let schedule = Schedule::new_recurring_schedule::(execution_time, frequency)?; // List of errors causing the auto compound task to be terminated. - let errors: Vec = AUTO_COMPOUND_DELEGATION_ABORT_ERRORS + let errors: Vec> = AUTO_COMPOUND_DELEGATION_ABORT_ERRORS .iter() - .map(|&error| String::from(error)) + .map(|&error| error.as_bytes().to_vec()) .collect(); Self::validate_and_schedule_task(action, who, schedule, errors)?; @@ -908,9 +905,12 @@ pub mod pallet { ::WeightInfo::run_tasks_many_missing(1) }, Some(task) => { - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", time_slot)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert( + "timestamp".as_bytes().to_vec(), + format!("{}", time_slot).into_bytes(), + ); let encoded_call = match task.action.clone() { Action::XCMP { encoded_call, .. } => Some(encoded_call), @@ -1385,7 +1385,7 @@ pub mod pallet { action: ActionOf, owner_id: AccountOf, schedule: Schedule, - abort_errors: Vec, + abort_errors: Vec>, ) -> DispatchResult { match action.clone() { Action::XCMP { execution_fee, instruction_sequence, .. } => { @@ -1442,7 +1442,8 @@ pub mod pallet { match dispatch_error { Some(err) if err == DispatchError::from(Error::::CallCannotBeDecoded) || - task.abort_errors.contains(&String::from(Into::<&str>::into(err))) => + task.abort_errors + .contains(&Into::<&str>::into(err).as_bytes().to_vec()) => { Self::deposit_event(Event::::TaskNotRescheduled { who: task.owner_id.clone(), diff --git a/pallets/automation-time/src/migrations/update_xcmp_task.rs b/pallets/automation-time/src/migrations/update_xcmp_task.rs index 51be2a7b3..8abf8d9a2 100644 --- a/pallets/automation-time/src/migrations/update_xcmp_task.rs +++ b/pallets/automation-time/src/migrations/update_xcmp_task.rs @@ -3,6 +3,7 @@ use core::marker::PhantomData; use crate::{ weights::WeightInfo, AccountOf, ActionOf, AssetPayment, Config, InstructionSequence, TaskOf, }; +#[cfg(feature = "try-runtime")] use codec::{Decode, Encode}; use frame_support::{traits::OnRuntimeUpgrade, weights::Weight, Twox64Concat}; use sp_runtime::traits::Convert; diff --git a/pallets/automation-time/src/mock.rs b/pallets/automation-time/src/mock.rs index 0d850b469..785377ef2 100644 --- a/pallets/automation-time/src/mock.rs +++ b/pallets/automation-time/src/mock.rs @@ -594,7 +594,7 @@ pub fn add_task_to_task_queue( task_id: TaskIdV2, scheduled_times: Vec, action: ActionOf, - abort_errors: Vec, + abort_errors: Vec>, ) -> TaskIdV2 { let schedule = Schedule::new_fixed_schedule::(scheduled_times).unwrap(); add_to_task_queue(owner, task_id, schedule, action, abort_errors) @@ -606,7 +606,7 @@ pub fn add_recurring_task_to_task_queue( scheduled_time: u64, frequency: u64, action: ActionOf, - abort_errors: Vec, + abort_errors: Vec>, ) -> TaskIdV2 { let schedule = Schedule::new_recurring_schedule::(scheduled_time, frequency).unwrap(); add_to_task_queue(owner, task_id, schedule, action, abort_errors) @@ -617,7 +617,7 @@ pub fn add_to_task_queue( task_id: TaskIdV2, schedule: Schedule, action: ActionOf, - abort_errors: Vec, + abort_errors: Vec>, ) -> TaskIdV2 { let task_id = create_task(owner, task_id, schedule, action, abort_errors); let mut task_queue = AutomationTime::get_task_queue(); @@ -631,7 +631,7 @@ pub fn add_task_to_missed_queue( task_id: TaskIdV2, scheduled_times: Vec, action: ActionOf, - abort_errors: Vec, + abort_errors: Vec>, ) -> TaskIdV2 { let schedule = Schedule::new_fixed_schedule::(scheduled_times.clone()).unwrap(); let task_id = create_task(owner, task_id.clone(), schedule, action, abort_errors); @@ -648,7 +648,7 @@ pub fn create_task( task_id: TaskIdV2, schedule: Schedule, action: ActionOf, - abort_errors: Vec, + abort_errors: Vec>, ) -> TaskIdV2 { let task = TaskOf::::new(owner.into(), task_id.clone(), schedule, action, abort_errors); AccountTasks::::insert(AccountId::new(owner), task_id.clone(), task); diff --git a/pallets/automation-time/src/tests.rs b/pallets/automation-time/src/tests.rs index c667b9a4d..31ad076c8 100644 --- a/pallets/automation-time/src/tests.rs +++ b/pallets/automation-time/src/tests.rs @@ -365,9 +365,9 @@ fn schedule_transfer_with_dynamic_dispatch() { let recipient = AccountId32::new(BOB); assert_eq!(Balances::free_balance(recipient.clone()), 127); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), SCHEDULED_TIME.to_string().into_bytes()); assert!(contains_events( my_events, @@ -549,9 +549,10 @@ fn will_emit_task_completed_event_when_task_failed() { AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000)); let my_events = events(); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", next_execution_time)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition + .insert("timestamp".as_bytes().to_vec(), next_execution_time.to_string().into_bytes()); assert!(contains_events( my_events, @@ -1563,9 +1564,9 @@ fn cancel_works_for_an_executed_task() { AutomationTime::trigger_tasks(Weight::from_ref_time(200_000)); let my_events = events(); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), SCHEDULED_TIME.to_string().into_bytes()); assert_eq!( my_events, [ @@ -1994,9 +1995,9 @@ fn trigger_tasks_handles_missed_slots() { assert_eq!(AutomationTime::get_task_queue().len(), 1); assert_eq!(AutomationTime::get_task_queue()[0].1, scheduled_task_id); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), SCHEDULED_TIME.to_string().into_bytes()); assert_eq!( events(), @@ -2081,9 +2082,10 @@ fn trigger_tasks_limits_missed_slots() { assert_eq!(updated_last_time_slot, SCHEDULED_TIME); assert_eq!(updated_last_missed_slot, SCHEDULED_TIME - 10800); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", SCHEDULED_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition + .insert("timestamp".as_bytes().to_vec(), SCHEDULED_TIME.to_string().into_bytes()); assert_eq!( my_events, @@ -2199,9 +2201,9 @@ fn trigger_tasks_completes_all_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert_eq!( events(), @@ -2291,9 +2293,9 @@ fn trigger_tasks_completes_some_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(80_000)); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert_eq!( events(), @@ -2491,9 +2493,9 @@ fn missed_tasks_removes_completed_tasks() { assert_eq!(AutomationTime::get_task_queue().len(), 0); assert_eq!(AutomationTime::get_missed_queue().len(), 0); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert_eq!( events(), @@ -2598,9 +2600,9 @@ fn trigger_tasks_completes_some_xcmp_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert_eq!( events(), @@ -2659,9 +2661,9 @@ fn trigger_tasks_completes_auto_compound_delegated_stake_task() { .expect(EXPECT_CALCULATE_SCHEDULE_FEE_AMOUNT); let delegation = before_balance - fee_amount - account_minimum; - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert!(contains_events( emitted_events, @@ -2864,7 +2866,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegator() { collator: AccountId32::new(BOB), account_minimum, }, - vec![String::from("DelegatorDNE"), String::from("DelegationDNE")], + vec!["DelegatorDNE".as_bytes().to_vec(), "DelegationDNE".as_bytes().to_vec()], ); System::reset_events(); @@ -2938,7 +2940,7 @@ fn auto_compound_delegated_stake_enough_balance_no_delegation() { collator: AccountId32::new(BOB), account_minimum, }, - vec![String::from("DelegatorDNE"), String::from("DelegationDNE")], + vec!["DelegatorDNE".as_bytes().to_vec(), "DelegationDNE".as_bytes().to_vec()], ); System::reset_events(); @@ -3013,7 +3015,7 @@ fn auto_compound_delegated_stake_not_enough_balance_no_delegation() { collator: collator.clone(), account_minimum, }, - vec![String::from("DelegatorDNE"), String::from("DelegationDNE")], + vec!["DelegatorDNE".as_bytes().to_vec(), "DelegationDNE".as_bytes().to_vec()], ); System::reset_events(); @@ -3087,9 +3089,9 @@ fn trigger_tasks_updates_executions_left() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert_eq!( events(), @@ -3145,9 +3147,9 @@ fn trigger_tasks_removes_completed_tasks() { AutomationTime::trigger_tasks(Weight::from_ref_time(120_000)); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert_eq!( events(), @@ -3204,9 +3206,9 @@ fn on_init_runs_tasks() { AutomationTime::on_initialize(1); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert_eq!( events(), @@ -3297,9 +3299,9 @@ fn on_init_check_task_queue() { let owner = AccountId32::new(ALICE); - let mut condition: BTreeMap = BTreeMap::new(); - condition.insert(String::from("type"), String::from("time")); - condition.insert(String::from("timestamp"), format!("{}", LAST_BLOCK_TIME)); + let mut condition: BTreeMap, Vec> = BTreeMap::new(); + condition.insert("type".as_bytes().to_vec(), "time".as_bytes().to_vec()); + condition.insert("timestamp".as_bytes().to_vec(), LAST_BLOCK_TIME.to_string().into_bytes()); assert_eq!( events(), diff --git a/pallets/automation-time/src/types.rs b/pallets/automation-time/src/types.rs index 9b231dbc3..96b149a2c 100644 --- a/pallets/automation-time/src/types.rs +++ b/pallets/automation-time/src/types.rs @@ -2,7 +2,6 @@ use crate::{weights::WeightInfo, Config, Error, InstructionSequence, Pallet}; use frame_support::{dispatch::GetDispatchInfo, pallet_prelude::*, traits::Get}; -use scale_info::prelude::string::String; use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedConversion}; use sp_std::prelude::*; @@ -214,7 +213,7 @@ pub struct Task { pub task_id: Vec, pub schedule: Schedule, pub action: Action, - pub abort_errors: Vec, + pub abort_errors: Vec>, } impl PartialEq for Task { @@ -234,7 +233,7 @@ impl Task { task_id: Vec, schedule: Schedule, action: Action, - abort_errors: Vec, + abort_errors: Vec>, ) -> Self { Self { owner_id, task_id, schedule, action, abort_errors } } @@ -244,7 +243,7 @@ impl Task { task_id: Vec, execution_times: Vec, message: Vec, - abort_errors: Vec, + abort_errors: Vec>, ) -> Result { let call: ::RuntimeCall = frame_system::Call::remark_with_event { remark: message }.into(); @@ -264,7 +263,7 @@ impl Task { encoded_call_weight: Weight, overall_weight: Weight, instruction_sequence: InstructionSequence, - abort_errors: Vec, + abort_errors: Vec>, ) -> Result { let destination = MultiLocation::try_from(destination).map_err(|_| Error::::BadVersion)?; @@ -289,7 +288,7 @@ impl Task { frequency: Seconds, collator_id: AccountId, account_minimum: Balance, - abort_errors: Vec, + abort_errors: Vec>, ) -> Result { let action = Action::AutoCompoundDelegatedStake { delegator: owner_id.clone(),