diff --git a/Cargo.lock b/Cargo.lock index 2ab2e7263f..cd6c86e981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5523,11 +5523,18 @@ dependencies = [ "frame-system", "integration-tests-helpers", "kusama-system-emulated-network", + "pallet-asset-rate", + "pallet-collator-selection", + "pallet-core-fellowship", + "pallet-ranked-collective", "pallet-utility", "pallet-whitelist", "pallet-xcm", "parity-scale-codec", "people-kusama-runtime", + "polkadot-runtime-common", + "sp-keyring", + "sp-npos-elections", "sp-runtime", "staging-kusama-runtime", "staging-xcm", @@ -5543,12 +5550,20 @@ dependencies = [ "frame-support", "frame-system", "integration-tests-helpers", + "pallet-asset-rate", + "pallet-collator-selection", + "pallet-core-fellowship", + "pallet-ranked-collective", + "pallet-treasury", "pallet-utility", "pallet-whitelist", "pallet-xcm", "parity-scale-codec", "polkadot-runtime", + "polkadot-runtime-common", "polkadot-system-emulated-network", + "sp-keyring", + "sp-npos-elections", "sp-runtime", "staging-xcm", ] @@ -6413,11 +6428,24 @@ version = "1.0.0" dependencies = [ "cumulus-pallet-xcmp-queue", "emulated-integration-tests-common", + "frame-system", "hex-literal", + "pallet-asset-rate", "pallet-balances", + "pallet-collator-selection", + "pallet-core-fellowship", + "pallet-election-provider-multi-phase", "pallet-message-queue", + "pallet-ranked-collective", + "pallet-staking", + "pallet-treasury", "pallet-xcm", + "parity-scale-codec", "paste", + "polkadot-parachain-primitives", + "polkadot-runtime-parachains", + "sp-npos-elections", + "sp-runtime", "staging-xcm", "xcm-emulator", ] @@ -10598,10 +10626,8 @@ dependencies = [ "cumulus-primitives-core", "emulated-integration-tests-common", "frame-support", - "kusama-emulated-chain", "parachains-common", "penpal-runtime", - "polkadot-emulated-chain", "sp-core 38.0.0", "sp-keyring", "staging-xcm", diff --git a/integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/Cargo.toml b/integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/Cargo.toml index 9d0567dbca..d9d1db2e51 100644 --- a/integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/Cargo.toml +++ b/integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/Cargo.toml @@ -36,7 +36,6 @@ runtime-benchmarks = [ "asset-hub-kusama-runtime/runtime-benchmarks", "cumulus-primitives-core/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "kusama-emulated-chain/runtime-benchmarks", "parachains-common/runtime-benchmarks", "penpal-emulated-chain/runtime-benchmarks", diff --git a/integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/Cargo.toml b/integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/Cargo.toml index 0352b5f33e..aaa176ceb5 100644 --- a/integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/Cargo.toml +++ b/integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/Cargo.toml @@ -37,7 +37,6 @@ runtime-benchmarks = [ "asset-hub-polkadot-runtime/runtime-benchmarks", "cumulus-primitives-core/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "parachains-common/runtime-benchmarks", "penpal-emulated-chain/runtime-benchmarks", "polkadot-emulated-chain/runtime-benchmarks", diff --git a/integration-tests/emulated/chains/parachains/collectives/collectives-polkadot/src/lib.rs b/integration-tests/emulated/chains/parachains/collectives/collectives-polkadot/src/lib.rs index d8ffbdcaf6..3050c8283a 100644 --- a/integration-tests/emulated/chains/parachains/collectives/collectives-polkadot/src/lib.rs +++ b/integration-tests/emulated/chains/parachains/collectives/collectives-polkadot/src/lib.rs @@ -43,6 +43,7 @@ decl_test_parachains! { Balances: collectives_polkadot_runtime::Balances, FellowshipTreasury: collectives_polkadot_runtime::FellowshipTreasury, AssetRate: collectives_polkadot_runtime::AssetRate, + FellowshipCore: collectives_polkadot_runtime::FellowshipCore, } }, } diff --git a/integration-tests/emulated/chains/parachains/encointer/encointer-kusama/Cargo.toml b/integration-tests/emulated/chains/parachains/encointer/encointer-kusama/Cargo.toml index a0390644bd..d4a2fac4e7 100644 --- a/integration-tests/emulated/chains/parachains/encointer/encointer-kusama/Cargo.toml +++ b/integration-tests/emulated/chains/parachains/encointer/encointer-kusama/Cargo.toml @@ -35,7 +35,6 @@ runtime-benchmarks = [ "cumulus-primitives-core/runtime-benchmarks", "encointer-kusama-runtime/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "kusama-emulated-chain/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml b/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml index f067b61ec4..8ad96143e8 100644 --- a/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml +++ b/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml @@ -21,18 +21,12 @@ emulated-integration-tests-common = { workspace = true } penpal-runtime = { workspace = true } xcm = { workspace = true, default-features = true } -# Runtimes -kusama-emulated-chain = { workspace = true } -polkadot-emulated-chain = { workspace = true } - [features] runtime-benchmarks = [ "cumulus-primitives-core/runtime-benchmarks", "frame-support/runtime-benchmarks", - "kusama-emulated-chain/runtime-benchmarks", "parachains-common/runtime-benchmarks", "penpal-runtime/runtime-benchmarks", - "polkadot-emulated-chain/runtime-benchmarks", "xcm/runtime-benchmarks", ] try-runtime = [ diff --git a/integration-tests/emulated/helpers/Cargo.toml b/integration-tests/emulated/helpers/Cargo.toml index e99d68cb69..fc3805a22e 100644 --- a/integration-tests/emulated/helpers/Cargo.toml +++ b/integration-tests/emulated/helpers/Cargo.toml @@ -10,10 +10,23 @@ publish = false [dependencies] paste = { workspace = true } hex-literal = { workspace = true } +codec = { workspace = true, default-features = true } # Substrate +sp-runtime = { workspace = true, default-features = true } +frame-system = { workspace = true, default-features = true } pallet-balances = { workspace = true, default-features = true } pallet-message-queue = { workspace = true, default-features = true } +pallet-core-fellowship = { workspace = true, default-features = true } +pallet-ranked-collective = { workspace = true, default-features = true } +pallet-staking = { workspace = true, default-features = true } +pallet-collator-selection = { workspace = true, default-features = true } +runtime-parachains = { workspace = true, default-features = true } +polkadot-parachain-primitives = { workspace = true, default-features = true } +pallet-election-provider-multi-phase = { workspace = true, default-features = true } +sp-npos-elections = { workspace = true, default-features = true } +pallet-asset-rate = { workspace = true, default-features = true } +pallet-treasury = { workspace = true, default-features = true } # Polkadot xcm = { workspace = true, default-features = true } @@ -23,12 +36,3 @@ pallet-xcm = { workspace = true, default-features = true } xcm-emulator = { workspace = true } cumulus-pallet-xcmp-queue = { workspace = true, default-features = true } emulated-integration-tests-common = { workspace = true } - -[features] -runtime-benchmarks = [ - "cumulus-pallet-xcmp-queue/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "xcm/runtime-benchmarks", -] diff --git a/integration-tests/emulated/helpers/src/lib.rs b/integration-tests/emulated/helpers/src/lib.rs index 84718238e8..3cfb830da6 100644 --- a/integration-tests/emulated/helpers/src/lib.rs +++ b/integration-tests/emulated/helpers/src/lib.rs @@ -21,7 +21,7 @@ pub use pallet_message_queue; // Polkadot pub use pallet_xcm; -pub use xcm::prelude::{AccountId32, VersionedAssets, Weight, WeightLimit}; +pub use xcm::{latest::prelude::*, VersionedLocation, VersionedXcm}; // Cumulus pub use cumulus_pallet_xcmp_queue; @@ -29,6 +29,9 @@ pub use emulated_integration_tests_common::{macros::Dmp, test_chain_can_claim_as pub use xcm_emulator::Chain; pub mod common; +use codec::Encode; +use emulated_integration_tests_common::impls::bx; +use sp_runtime::traits::StaticLookup; #[macro_export] macro_rules! test_relay_is_trusted_teleporter { @@ -450,3 +453,535 @@ macro_rules! test_parachain_is_trusted_teleporter { } }; } + +/// Builds a `pallet_xcm::send` call wrapped in an unpaid XCM `Transact` +pub fn build_xcm_send_call( + location: Location, + fallback_max_weight: Option, + transact_call: D::RuntimeCall, + origin_kind: OriginKind, +) -> T::RuntimeCall +where + T: Chain, + T::Runtime: pallet_xcm::Config, + T::RuntimeCall: Encode + From>, + D: Chain, + D::RuntimeCall: Encode, +{ + let call: T::RuntimeCall = pallet_xcm::Call::send { + dest: bx!(VersionedLocation::from(location)), + message: bx!(VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { origin_kind, fallback_max_weight, call: transact_call.encode().into() }, + ExpectTransactStatus(MaybeErrorCode::Success) + ]))), + } + .into(); + call +} + +/// Builds a `pallet_xcm::send` call to induct Fellowship member, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_induct_member( + dest: Location, + who: ::AccountId, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_core_fellowship::Config, + DestChain::RuntimeCall: + Encode + From>, + Instance: 'static, +{ + let call: DestChain::RuntimeCall = + pallet_core_fellowship::Call::::induct { who }.into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to add Fellowship member, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_fellowship_add_member( + dest: Location, + who: ::AccountId, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_ranked_collective::Config, + DestChain::RuntimeCall: + Encode + From>, + Instance: 'static, +{ + // Convert AccountId -> Lookup::Source expected by call + type LookupSrcOf = <::Lookup as StaticLookup>::Source; + + let who_lookup: LookupSrcOf = + <::Lookup as StaticLookup>::unlookup(who); + + let call: DestChain::RuntimeCall = + pallet_ranked_collective::Call::::add_member { + who: who_lookup, + } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to remove Fellowship member, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_fellowship_remove_member( + dest: Location, + who: ::AccountId, + min_rank: u16, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_ranked_collective::Config, + DestChain::RuntimeCall: + Encode + From>, + Instance: 'static, +{ + // Convert AccountId -> Lookup::Source expected by call + type LookupSrcOf = <::Lookup as StaticLookup>::Source; + + let who_lookup: LookupSrcOf = + <::Lookup as StaticLookup>::unlookup(who); + + let call: DestChain::RuntimeCall = + pallet_ranked_collective::Call::::remove_member { + who: who_lookup, + min_rank, + } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to promote Fellowship member, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_fellowship_promote_member( + dest: Location, + who: ::AccountId, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_ranked_collective::Config, + DestChain::RuntimeCall: + Encode + From>, + Instance: 'static, +{ + // Convert AccountId -> Lookup::Source expected by call + type LookupSrcOf = <::Lookup as StaticLookup>::Source; + + let who_lookup: LookupSrcOf = + <::Lookup as StaticLookup>::unlookup(who); + + let call: DestChain::RuntimeCall = + pallet_ranked_collective::Call::::promote_member { + who: who_lookup, + } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to promote Fellowship Core member, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_fellowship_core_promote_member( + dest: Location, + who: ::AccountId, + to_rank: pallet_core_fellowship::pallet::RankOf, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_core_fellowship::Config, + DestChain::RuntimeCall: + Encode + From>, + Instance: 'static, +{ + let call: DestChain::RuntimeCall = + pallet_core_fellowship::Call::::promote { who, to_rank } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to demote Fellowship member, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_fellowship_demote_member( + dest: Location, + who: ::AccountId, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_ranked_collective::Config, + DestChain::RuntimeCall: + Encode + From>, + Instance: 'static, +{ + // Convert AccountId -> Lookup::Source expected by add_member + type LookupSrcOf = <::Lookup as StaticLookup>::Source; + + let who_lookup: LookupSrcOf = + <::Lookup as StaticLookup>::unlookup(who); + + let call: DestChain::RuntimeCall = + pallet_ranked_collective::Call::::demote_member { + who: who_lookup, + } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to exchange Fellowship member, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_fellowship_exchange_member( + dest: Location, + who: ::AccountId, + new_who: ::AccountId, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_ranked_collective::Config, + DestChain::RuntimeCall: + Encode + From>, + Instance: 'static, +{ + // Convert AccountId -> Lookup::Source expected by add_member + type LookupSrcOf = <::Lookup as StaticLookup>::Source; + + let who_lookup: LookupSrcOf = + <::Lookup as StaticLookup>::unlookup(who); + + let new_who_lookup: LookupSrcOf = + <::Lookup as StaticLookup>::unlookup(new_who); + + let call: DestChain::RuntimeCall = + pallet_ranked_collective::Call::::exchange_member { + who: who_lookup, + new_who: new_who_lookup, + } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to set min_promotion_period param for Fellowship Core, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm` +/// +/// Note: This call assumes other params are not important and will get overriden by empty/zero +/// values +pub fn build_xcm_send_fellowship_core_set_rank1_min_promotion_period< + SourceChain, + DestChain, + Instance, +>( + dest: Location, + min_promotion_period: frame_system::pallet_prelude::BlockNumberFor, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_core_fellowship::Config, + DestChain::RuntimeCall: + Encode + From>, + Instance: 'static, +{ + use pallet_core_fellowship::pallet::ParamsOf; + use sp_runtime::{bounded_vec, traits::Zero}; + + let params = ParamsOf:: { + active_salary: bounded_vec![], + passive_salary: bounded_vec![], + demotion_period: bounded_vec![], + min_promotion_period: bounded_vec![min_promotion_period], + offboard_timeout: frame_system::pallet_prelude::BlockNumberFor::::zero( + ), + }; + + let dest_call: DestChain::RuntimeCall = + pallet_core_fellowship::Call::::set_params { + params: Box::new(params), + } + .into(); + + build_xcm_send_call::( + dest, + fallback_max_weight, + dest_call, + OriginKind::Xcm, + ) +} + +/// Builds a `pallet_xcm::send` call set desired Collator candidates, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_set_desired_candidates( + dest: Location, + max: u32, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_collator_selection::Config, + DestChain::RuntimeCall: Encode + From>, +{ + let call: DestChain::RuntimeCall = + pallet_collator_selection::Call::::set_desired_candidates { max } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to force hrmp clean, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_force_clean_hrmp( + dest: Location, + para: polkadot_parachain_primitives::primitives::Id, + num_inbound: u32, + num_outbound: u32, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + runtime_parachains::hrmp::Config, + DestChain::RuntimeCall: Encode + From>, +{ + let call: DestChain::RuntimeCall = + runtime_parachains::hrmp::Call::::force_clean_hrmp { + para, + num_inbound, + num_outbound, + } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to set min commisions, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_set_min_commissions( + dest: Location, + new_commissions: sp_runtime::Perbill, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_staking::Config, + DestChain::RuntimeCall: Encode + From>, +{ + let call: DestChain::RuntimeCall = + pallet_staking::Call::::set_min_commission { new: new_commissions } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to set min untrusted score, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_set_minimum_untrusted_score( + dest: Location, + maybe_next_score: Option, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_election_provider_multi_phase::Config, + DestChain::RuntimeCall: + Encode + From>, +{ + let call: DestChain::RuntimeCall = pallet_election_provider_multi_phase::Call::< + DestChain::Runtime, + >::set_minimum_untrusted_score { + maybe_next_score, + } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to create asset rate, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_asset_rate_create( + dest: Location, + asset_kind: ::AssetKind, + rate: sp_runtime::FixedU128, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_asset_rate::Config, + DestChain::RuntimeCall: Encode + From>, +{ + let call: DestChain::RuntimeCall = + pallet_asset_rate::Call::::create { asset_kind: bx!(asset_kind), rate } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to update asset rate, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_asset_rate_update( + dest: Location, + asset_kind: ::AssetKind, + rate: sp_runtime::FixedU128, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_asset_rate::Config, + DestChain::RuntimeCall: Encode + From>, +{ + let call: DestChain::RuntimeCall = + pallet_asset_rate::Call::::update { asset_kind: bx!(asset_kind), rate } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to remote asset rate, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_asset_rate_remove( + dest: Location, + asset_kind: ::AssetKind, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_asset_rate::Config, + DestChain::RuntimeCall: Encode + From>, +{ + let call: DestChain::RuntimeCall = + pallet_asset_rate::Call::::remove { asset_kind: bx!(asset_kind) } + .into(); + + build_xcm_send_call::(dest, fallback_max_weight, call, OriginKind::Xcm) +} + +/// Builds a `pallet_xcm::send` call to create treasury spend, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_treasury_spend( + dest: Location, + asset_kind: >::AssetKind, + amount: pallet_treasury::AssetBalanceOf, + beneficiary: Beneficiary, + valid_from: Option>, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_treasury::Config, + DestChain::RuntimeCall: Encode + From>, + + Instance: 'static, + + Beneficiary: Into<>::Beneficiary>, +{ + // Convert AccountId -> Lookup::Source expected by treasury::spend + type BenLookupSrcOf = + <>::BeneficiaryLookup as StaticLookup>::Source; + + let ben_lookup: BenLookupSrcOf = + <>::BeneficiaryLookup as StaticLookup> + ::unlookup(beneficiary.into()); + + let dest_call: DestChain::RuntimeCall = + pallet_treasury::Call::::spend { + asset_kind: bx!(asset_kind), + amount, + beneficiary: bx!(ben_lookup), + valid_from, + } + .into(); + + build_xcm_send_call::( + dest, + fallback_max_weight, + dest_call, + OriginKind::Xcm, + ) +} + +/// Builds a `pallet_xcm::send` call to void existing treasury spend, +/// wrapped in an unpaid XCM `Transact` with `OriginKind::Xcm`. +pub fn build_xcm_send_treasury_void_spend( + dest: Location, + index: pallet_treasury::SpendIndex, + fallback_max_weight: Option, +) -> SourceChain::RuntimeCall +where + SourceChain: Chain, + SourceChain::Runtime: pallet_xcm::Config, + SourceChain::RuntimeCall: Encode + From>, + DestChain: Chain, + DestChain::Runtime: frame_system::Config + pallet_treasury::Config, + DestChain::RuntimeCall: Encode + From>, + + Instance: 'static, +{ + let dest_call: DestChain::RuntimeCall = + pallet_treasury::Call::::void_spend { index }.into(); + + build_xcm_send_call::( + dest, + fallback_max_weight, + dest_call, + OriginKind::Xcm, + ) +} diff --git a/integration-tests/emulated/tests/assets/asset-hub-kusama/Cargo.toml b/integration-tests/emulated/tests/assets/asset-hub-kusama/Cargo.toml index ae68ae432c..d3ff0de733 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-kusama/Cargo.toml +++ b/integration-tests/emulated/tests/assets/asset-hub-kusama/Cargo.toml @@ -48,7 +48,6 @@ runtime-benchmarks = [ "asset-hub-kusama-runtime/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "kusama-runtime-constants/runtime-benchmarks", "kusama-runtime/runtime-benchmarks", "kusama-system-emulated-network/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/assets/asset-hub-polkadot/Cargo.toml b/integration-tests/emulated/tests/assets/asset-hub-polkadot/Cargo.toml index 8521d59648..1987f15a76 100644 --- a/integration-tests/emulated/tests/assets/asset-hub-polkadot/Cargo.toml +++ b/integration-tests/emulated/tests/assets/asset-hub-polkadot/Cargo.toml @@ -49,7 +49,6 @@ runtime-benchmarks = [ "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/bridges/bridge-hub-kusama/Cargo.toml b/integration-tests/emulated/tests/bridges/bridge-hub-kusama/Cargo.toml index e886eec66a..5489b1b905 100644 --- a/integration-tests/emulated/tests/bridges/bridge-hub-kusama/Cargo.toml +++ b/integration-tests/emulated/tests/bridges/bridge-hub-kusama/Cargo.toml @@ -58,7 +58,6 @@ runtime-benchmarks = [ "bridge-hub-kusama-runtime/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "kusama-polkadot-system-emulated-network/runtime-benchmarks", "kusama-system-emulated-network/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/bridges/bridge-hub-polkadot/Cargo.toml b/integration-tests/emulated/tests/bridges/bridge-hub-polkadot/Cargo.toml index 9e171cb00f..cad0212067 100644 --- a/integration-tests/emulated/tests/bridges/bridge-hub-polkadot/Cargo.toml +++ b/integration-tests/emulated/tests/bridges/bridge-hub-polkadot/Cargo.toml @@ -75,7 +75,6 @@ runtime-benchmarks = [ "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "kusama-polkadot-system-emulated-network/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-assets/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/collectives/collectives-polkadot/Cargo.toml b/integration-tests/emulated/tests/collectives/collectives-polkadot/Cargo.toml index 84cbe885d9..9d56abc6a7 100644 --- a/integration-tests/emulated/tests/collectives/collectives-polkadot/Cargo.toml +++ b/integration-tests/emulated/tests/collectives/collectives-polkadot/Cargo.toml @@ -54,7 +54,6 @@ runtime-benchmarks = [ "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "pallet-asset-rate/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/coretime/coretime-kusama/Cargo.toml b/integration-tests/emulated/tests/coretime/coretime-kusama/Cargo.toml index 1c3396fad4..b2e90cda2b 100644 --- a/integration-tests/emulated/tests/coretime/coretime-kusama/Cargo.toml +++ b/integration-tests/emulated/tests/coretime/coretime-kusama/Cargo.toml @@ -44,7 +44,6 @@ runtime-benchmarks = [ "coretime-kusama-runtime/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "kusama-runtime-constants/runtime-benchmarks", "kusama-runtime/runtime-benchmarks", "kusama-system-emulated-network/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/coretime/coretime-polkadot/Cargo.toml b/integration-tests/emulated/tests/coretime/coretime-polkadot/Cargo.toml index 3bad48fa52..721a6ee3b9 100644 --- a/integration-tests/emulated/tests/coretime/coretime-polkadot/Cargo.toml +++ b/integration-tests/emulated/tests/coretime/coretime-polkadot/Cargo.toml @@ -43,7 +43,6 @@ runtime-benchmarks = [ "coretime-polkadot-runtime/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-broker/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/encointer/encointer-kusama/Cargo.toml b/integration-tests/emulated/tests/encointer/encointer-kusama/Cargo.toml index 8f6b41edda..cec8522318 100644 --- a/integration-tests/emulated/tests/encointer/encointer-kusama/Cargo.toml +++ b/integration-tests/emulated/tests/encointer/encointer-kusama/Cargo.toml @@ -49,7 +49,6 @@ runtime-benchmarks = [ "cumulus-pallet-parachain-system/runtime-benchmarks", "encointer-kusama-runtime/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "kusama-runtime-constants/runtime-benchmarks", "kusama-runtime/runtime-benchmarks", "kusama-system-emulated-network/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/governance/kusama/Cargo.toml b/integration-tests/emulated/tests/governance/kusama/Cargo.toml index 646b902d43..3dfee3950e 100644 --- a/integration-tests/emulated/tests/governance/kusama/Cargo.toml +++ b/integration-tests/emulated/tests/governance/kusama/Cargo.toml @@ -12,10 +12,17 @@ codec = { workspace = true, default-features = true } # Substrate sp-runtime = { workspace = true, default-features = true } +sp-keyring = { workspace = true, default-features = true } frame-support = { workspace = true, default-features = true } frame-system = { workspace = true, default-features = true } pallet-whitelist = { workspace = true, default-features = true } pallet-utility = { workspace = true, default-features = true } +pallet-core-fellowship = { workspace = true, default-features = true } +pallet-ranked-collective = { workspace = true, default-features = true } +pallet-collator-selection = { workspace = true, default-features = true } +sp-npos-elections = { workspace = true, default-features = true } +polkadot-runtime-common = { workspace = true, default-features = true } +pallet-asset-rate = { workspace = true, default-features = true } # Cumulus emulated-integration-tests-common = { workspace = true } diff --git a/integration-tests/emulated/tests/governance/kusama/src/lib.rs b/integration-tests/emulated/tests/governance/kusama/src/lib.rs index 023a451564..3bef155e1a 100644 --- a/integration-tests/emulated/tests/governance/kusama/src/lib.rs +++ b/integration-tests/emulated/tests/governance/kusama/src/lib.rs @@ -36,6 +36,9 @@ mod imports { CoretimeKusamaPara as CoretimeKusama, KusamaRelay as Kusama, PeopleKusamaPara as PeopleKusama, }; + + pub(crate) use integration_tests_helpers::*; + pub(crate) use sp_keyring::Sr25519Keyring::Charlie; } #[cfg(test)] @@ -46,3 +49,6 @@ mod open_gov_on_asset_hub; #[cfg(test)] mod open_gov_on_relay; + +#[cfg(test)] +mod open_gov_on_asset_hub_via_relay; diff --git a/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_asset_hub.rs b/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_asset_hub.rs index 153de3f2c9..1c512e2efc 100644 --- a/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_asset_hub.rs +++ b/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_asset_hub.rs @@ -24,11 +24,7 @@ fn assethub_can_authorize_upgrade_for_itself() { type AssetHubRuntimeOrigin = ::RuntimeOrigin; let authorize_upgrade = - AssetHubRuntimeCall::Utility(pallet_utility::Call::::force_batch { - calls: vec![AssetHubRuntimeCall::System(frame_system::Call::authorize_upgrade { - code_hash, - })], - }); + AssetHubRuntimeCall::System(frame_system::Call::authorize_upgrade { code_hash }); // bad origin let invalid_origin: AssetHubRuntimeOrigin = Origin::StakingAdmin.into(); @@ -100,14 +96,11 @@ fn assethub_can_authorize_upgrade_for_relay_chain() { type AssetHubRuntimeOrigin = ::RuntimeOrigin; let code_hash = [1u8; 32].into(); - let authorize_upgrade = - AssetHubRuntimeCall::Utility(pallet_utility::Call::::force_batch { - calls: vec![build_xcm_send_authorize_upgrade_call::( - AssetHubKusama::parent_location(), - &code_hash, - None, - )], - }); + let authorize_upgrade = build_xcm_send_authorize_upgrade_call::( + AssetHubKusama::parent_location(), + &code_hash, + None, + ); // bad origin let invalid_origin: AssetHubRuntimeOrigin = Origin::StakingAdmin.into(); @@ -278,3 +271,371 @@ fn assethub_can_authorize_upgrade_for_system_chains() { ) }); } + +#[test] +fn assethub_fellowship_admin_can_manage_fellowship_on_relay() { + type AssetHubOrigin = ::RuntimeOrigin; + + type KusamaRuntime = ::Runtime; + type KusamaRuntimeEvent = ::RuntimeEvent; + + let account: ::AccountId = Charlie.to_account_id(); + let ok_origin: AssetHubOrigin = Origin::FellowshipAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + + let add_member_xcm = build_xcm_send_fellowship_add_member::< + AssetHubKusama, + Kusama, + pallet_ranked_collective::Instance1, + >(AssetHubKusama::parent_location(), account.clone(), None); + let promote_member_xcm = build_xcm_send_fellowship_promote_member::< + AssetHubKusama, + Kusama, + pallet_ranked_collective::Instance1, + >(AssetHubKusama::parent_location(), account.clone(), None); + let demote_member_xcm = build_xcm_send_fellowship_demote_member::< + AssetHubKusama, + Kusama, + pallet_ranked_collective::Instance1, + >(AssetHubKusama::parent_location(), account.clone(), None); + let remove_member_xcm = build_xcm_send_fellowship_remove_member::< + AssetHubKusama, + Kusama, + pallet_ranked_collective::Instance1, + >(AssetHubKusama::parent_location(), account.clone(), 0, None); + + AssetHubKusama::execute_with(|| { + assert_ok!(add_member_xcm.clone().dispatch(bad_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(add_member_xcm.dispatch(ok_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::FellowshipCollective(pallet_ranked_collective::Event::MemberAdded { who }) => { + who: *who == account, + }, + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubKusama::execute_with(|| { + assert_ok!(promote_member_xcm.clone().dispatch(bad_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(promote_member_xcm.dispatch(ok_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::FellowshipCollective(pallet_ranked_collective::Event::RankChanged { who, rank: 1 }) => { + who: *who == account, + }, + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubKusama::execute_with(|| { + assert_ok!(demote_member_xcm.clone().dispatch(bad_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(demote_member_xcm.dispatch(ok_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::FellowshipCollective(pallet_ranked_collective::Event::RankChanged { who, rank: 0 }) => { + who: *who == account, + }, + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubKusama::execute_with(|| { + assert_ok!(remove_member_xcm.clone().dispatch(bad_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(remove_member_xcm.dispatch(ok_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::FellowshipCollective(pallet_ranked_collective::Event::MemberRemoved { who, rank }) => { + who: *who == account, + rank: *rank == 0, + }, + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_staking_admin_can_manage_collator_config_on_other_chains() { + type AssetHubOrigin = ::RuntimeOrigin; + type CoretimeRuntimeEvent = ::RuntimeEvent; + type BridgeHubRuntimeEvent = ::RuntimeEvent; + type PeopleRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::FellowshipAdmin.into(); + + let new_desired_candidates = 23; // random number + + let set_candidates_xcm_coretime = + build_xcm_send_set_desired_candidates::( + AssetHubKusama::sibling_location_of(CoretimeKusama::para_id()), + new_desired_candidates, + None, + ); + let set_candidates_xcm_bridge_hub = + build_xcm_send_set_desired_candidates::( + AssetHubKusama::sibling_location_of(BridgeHubKusama::para_id()), + new_desired_candidates, + None, + ); + let set_candidates_xcm_people = + build_xcm_send_set_desired_candidates::( + AssetHubKusama::sibling_location_of(PeopleKusama::para_id()), + new_desired_candidates, + None, + ); + + AssetHubKusama::execute_with(|| { + assert_ok!(set_candidates_xcm_coretime.clone().dispatch(bad_origin.clone())); + }); + CoretimeKusama::execute_with(|| { + assert_expected_events!( + CoretimeKusama, + vec![ + CoretimeRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(set_candidates_xcm_coretime.dispatch(ok_origin.clone())); + }); + CoretimeKusama::execute_with(|| { + assert_expected_events!( + CoretimeKusama, + vec![ + CoretimeRuntimeEvent::CollatorSelection(pallet_collator_selection::Event::NewDesiredCandidates { desired_candidates }) => { + desired_candidates: *desired_candidates == new_desired_candidates, + }, + CoretimeRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubKusama::execute_with(|| { + assert_ok!(set_candidates_xcm_bridge_hub.clone().dispatch(bad_origin.clone())); + }); + BridgeHubKusama::execute_with(|| { + assert_expected_events!( + BridgeHubKusama, + vec![ + BridgeHubRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(set_candidates_xcm_bridge_hub.dispatch(ok_origin.clone())); + }); + BridgeHubKusama::execute_with(|| { + assert_expected_events!( + BridgeHubKusama, + vec![ + BridgeHubRuntimeEvent::CollatorSelection(pallet_collator_selection::Event::NewDesiredCandidates { desired_candidates }) => { + desired_candidates: *desired_candidates == new_desired_candidates, + }, + BridgeHubRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubKusama::execute_with(|| { + assert_ok!(set_candidates_xcm_people.clone().dispatch(bad_origin.clone())); + }); + PeopleKusama::execute_with(|| { + assert_expected_events!( + PeopleKusama, + vec![ + PeopleRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(set_candidates_xcm_people.dispatch(ok_origin.clone())); + }); + PeopleKusama::execute_with(|| { + assert_expected_events!( + PeopleKusama, + vec![ + PeopleRuntimeEvent::CollatorSelection(pallet_collator_selection::Event::NewDesiredCandidates { desired_candidates }) => { + desired_candidates: *desired_candidates == new_desired_candidates, + }, + PeopleRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_general_admin_can_manage_hrmp_on_relay() { + type AssetHubOrigin = ::RuntimeOrigin; + type KusamaRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + + let force_clean_hrmp_xcm = build_xcm_send_force_clean_hrmp::( + AssetHubKusama::parent_location(), + PeopleKusama::para_id(), + 0, + 0, + None, + ); + + AssetHubKusama::execute_with(|| { + assert_ok!(force_clean_hrmp_xcm.clone().dispatch(bad_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(force_clean_hrmp_xcm.dispatch(ok_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_staking_admin_can_manage_staking_on_relay() { + type AssetHubOrigin = ::RuntimeOrigin; + type KusamaRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + + let set_min_commisions_xcm = build_xcm_send_set_min_commissions::( + AssetHubKusama::parent_location(), + sp_runtime::Perbill::from_percent(80), + None, + ); + + AssetHubKusama::execute_with(|| { + assert_ok!(set_min_commisions_xcm.clone().dispatch(bad_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(set_min_commisions_xcm.dispatch(ok_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_staking_admin_can_manage_elections_on_relay() { + type AssetHubOrigin = ::RuntimeOrigin; + type KusamaRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + + let new_score = + sp_npos_elections::ElectionScore { minimal_stake: 0, sum_stake: 0, sum_stake_squared: 0 }; + + let set_minimum_untrusted_score_xcm = + build_xcm_send_set_minimum_untrusted_score::( + AssetHubKusama::parent_location(), + Some(new_score), + None, + ); + + AssetHubKusama::execute_with(|| { + assert_ok!(set_minimum_untrusted_score_xcm.clone().dispatch(bad_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubKusama::execute_with(|| { + assert_ok!(set_minimum_untrusted_score_xcm.dispatch(ok_origin.clone())); + }); + Kusama::execute_with(|| { + assert_expected_events!( + Kusama, + vec![ + KusamaRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} diff --git a/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_asset_hub_via_relay.rs b/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_asset_hub_via_relay.rs new file mode 100644 index 0000000000..03c7666e2b --- /dev/null +++ b/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_asset_hub_via_relay.rs @@ -0,0 +1,152 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{common::collectives_send_whitelist, imports::*}; +use asset_hub_kusama_runtime::governance::pallet_custom_origins::Origin; + +#[test] +fn assethub_can_authorize_upgrade_for_system_chains_via_relay_chain() { + type AssetHubRuntime = ::Runtime; + type AssetHubRuntimeCall = ::RuntimeCall; + type AssetHubRuntimeOrigin = ::RuntimeOrigin; + + let code_hash_bridge_hub = [2u8; 32].into(); + let code_hash_coretime = [4u8; 32].into(); + let code_hash_people = [5u8; 32].into(); + + Kusama::execute_with(|| { + Dmp::make_parachain_reachable(BridgeHubKusama::para_id()); + Dmp::make_parachain_reachable(CoretimeKusama::para_id()); + Dmp::make_parachain_reachable(PeopleKusama::para_id()); + }); + + let authorize_upgrade = + AssetHubRuntimeCall::Utility(pallet_utility::Call::::force_batch { + calls: vec![ + build_xcm_send_call::( + AssetHubKusama::parent_location(), + None, + build_xcm_send_authorize_upgrade_call::( + Kusama::child_location_of(BridgeHubKusama::para_id()), + &code_hash_bridge_hub, + None, + ), + OriginKind::Superuser, + ), + build_xcm_send_call::( + AssetHubKusama::parent_location(), + None, + build_xcm_send_authorize_upgrade_call::( + Kusama::child_location_of(CoretimeKusama::para_id()), + &code_hash_coretime, + None, + ), + OriginKind::Superuser, + ), + build_xcm_send_call::( + AssetHubKusama::parent_location(), + None, + build_xcm_send_authorize_upgrade_call::( + Kusama::child_location_of(PeopleKusama::para_id()), + &code_hash_people, + None, + ), + OriginKind::Superuser, + ), + ], + }); + + // bad origin + let invalid_origin: AssetHubRuntimeOrigin = Origin::StakingAdmin.into(); + // ok origin + let ok_origin: AssetHubRuntimeOrigin = Origin::WhitelistedCaller.into(); + + let call_hash = call_hash_of::(&authorize_upgrade); + + // Err - when dispatch non-whitelisted + assert_err!( + dispatch_whitelisted_call_with_preimage::( + authorize_upgrade.clone(), + ok_origin.clone() + ), + DispatchError::Module(sp_runtime::ModuleError { + index: 94, + error: [3, 0, 0, 0], + message: Some("CallIsNotWhitelisted") + }) + ); + + // whitelist from Kusama + collectives_send_whitelist( + Kusama::child_location_of(::para_id()), + || { + AssetHubRuntimeCall::Whitelist( + pallet_whitelist::Call::::whitelist_call { call_hash }, + ) + .encode() + }, + ); + AssetHubKusama::execute_with(|| { + assert_whitelisted!(AssetHubKusama, call_hash); + }); + + // Err - when dispatch wrong origin + assert_err!( + dispatch_whitelisted_call_with_preimage::( + authorize_upgrade.clone(), + invalid_origin + ), + DispatchError::BadOrigin + ); + + // check before + BridgeHubKusama::execute_with(|| { + assert!(::System::authorized_upgrade().is_none()) + }); + CoretimeKusama::execute_with(|| { + assert!(::System::authorized_upgrade().is_none()) + }); + PeopleKusama::execute_with(|| { + assert!(::System::authorized_upgrade().is_none()) + }); + + // ok - authorized + assert_ok!(dispatch_whitelisted_call_with_preimage::( + authorize_upgrade, + ok_origin + )); + + Kusama::execute_with(|| {}); + + // check after - authorized + BridgeHubKusama::execute_with(|| { + assert_eq!( + ::System::authorized_upgrade().unwrap().code_hash(), + &code_hash_bridge_hub + ) + }); + CoretimeKusama::execute_with(|| { + assert_eq!( + ::System::authorized_upgrade().unwrap().code_hash(), + &code_hash_coretime + ) + }); + PeopleKusama::execute_with(|| { + assert_eq!( + ::System::authorized_upgrade().unwrap().code_hash(), + &code_hash_people + ) + }); +} diff --git a/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_relay.rs b/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_relay.rs index 820753e49b..777cd95dfa 100644 --- a/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_relay.rs +++ b/integration-tests/emulated/tests/governance/kusama/src/open_gov_on_relay.rs @@ -27,13 +27,9 @@ fn relaychain_can_authorize_upgrade_for_itself() { type KusamaRuntimeCall = ::RuntimeCall; type KusamaRuntimeOrigin = ::RuntimeOrigin; + // upgrade the relaychain let authorize_upgrade = - KusamaRuntimeCall::Utility(pallet_utility::Call::::force_batch { - calls: vec![ - // upgrade the relaychain - KusamaRuntimeCall::System(frame_system::Call::authorize_upgrade { code_hash }), - ], - }); + KusamaRuntimeCall::System(frame_system::Call::authorize_upgrade { code_hash }); // bad origin let invalid_origin: KusamaRuntimeOrigin = Origin::StakingAdmin.into(); diff --git a/integration-tests/emulated/tests/governance/polkadot/Cargo.toml b/integration-tests/emulated/tests/governance/polkadot/Cargo.toml index c7a7c92415..8b0b61f84c 100644 --- a/integration-tests/emulated/tests/governance/polkadot/Cargo.toml +++ b/integration-tests/emulated/tests/governance/polkadot/Cargo.toml @@ -12,10 +12,18 @@ codec = { workspace = true, default-features = true } # Substrate sp-runtime = { workspace = true, default-features = true } +sp-keyring = { workspace = true, default-features = true } frame-support = { workspace = true, default-features = true } frame-system = { workspace = true, default-features = true } pallet-whitelist = { workspace = true, default-features = true } pallet-utility = { workspace = true, default-features = true } +pallet-core-fellowship = { workspace = true, default-features = true } +pallet-ranked-collective = { workspace = true, default-features = true } +pallet-collator-selection = { workspace = true, default-features = true } +sp-npos-elections = { workspace = true, default-features = true } +polkadot-runtime-common = { workspace = true, default-features = true } +pallet-asset-rate = { workspace = true, default-features = true } +pallet-treasury = { workspace = true, default-features = true } # Polkadot pallet-xcm = { workspace = true, default-features = true } diff --git a/integration-tests/emulated/tests/governance/polkadot/src/lib.rs b/integration-tests/emulated/tests/governance/polkadot/src/lib.rs index 404d0d504e..5cbd4fc3ad 100644 --- a/integration-tests/emulated/tests/governance/polkadot/src/lib.rs +++ b/integration-tests/emulated/tests/governance/polkadot/src/lib.rs @@ -36,6 +36,9 @@ mod imports { CollectivesPolkadotPara as CollectivesPolkadot, CoretimePolkadotPara as CoretimePolkadot, PeoplePolkadotPara as PeoplePolkadot, PolkadotRelay as Polkadot, }; + + pub(crate) use integration_tests_helpers::*; + pub(crate) use sp_keyring::Sr25519Keyring::Charlie; } #[cfg(test)] @@ -46,3 +49,6 @@ mod open_gov_on_asset_hub; #[cfg(test)] mod open_gov_on_relay; + +#[cfg(test)] +mod open_gov_on_asset_hub_via_relay; diff --git a/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_asset_hub.rs b/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_asset_hub.rs index 77d0be7357..d64ece26b5 100644 --- a/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_asset_hub.rs +++ b/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_asset_hub.rs @@ -24,11 +24,7 @@ fn assethub_can_authorize_upgrade_for_itself() { type AssetHubRuntimeOrigin = ::RuntimeOrigin; let authorize_upgrade = - AssetHubRuntimeCall::Utility(pallet_utility::Call::::force_batch { - calls: vec![AssetHubRuntimeCall::System(frame_system::Call::authorize_upgrade { - code_hash, - })], - }); + AssetHubRuntimeCall::System(frame_system::Call::authorize_upgrade { code_hash }); // bad origin let invalid_origin: AssetHubRuntimeOrigin = Origin::StakingAdmin.into(); @@ -101,14 +97,11 @@ fn assethub_can_authorize_upgrade_for_relay_chain() { let code_hash = [1u8; 32].into(); - let authorize_upgrade = - AssetHubRuntimeCall::Utility(pallet_utility::Call::::force_batch { - calls: vec![build_xcm_send_authorize_upgrade_call::( - AssetHubPolkadot::parent_location(), - &code_hash, - None, - )], - }); + let authorize_upgrade = build_xcm_send_authorize_upgrade_call::( + AssetHubPolkadot::parent_location(), + &code_hash, + None, + ); // bad origin let invalid_origin: AssetHubRuntimeOrigin = Origin::StakingAdmin.into(); @@ -299,3 +292,979 @@ fn assethub_can_authorize_upgrade_for_system_chains() { ) }); } + +#[test] +fn assethub_fellowship_admin_can_manage_fellowship_on_collectives() { + type AssetHubOrigin = ::RuntimeOrigin; + type CollectivesRuntime = ::Runtime; + type CollectivesRuntimeEvent = ::RuntimeEvent; + + let account: ::AccountId = Charlie.to_account_id(); + let ok_origin: AssetHubOrigin = Origin::FellowshipAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + + let set_params_xcm = build_xcm_send_fellowship_core_set_rank1_min_promotion_period::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_core_fellowship::Instance1, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + 1, + None, + ); + let induct_member_xcm = build_xcm_send_induct_member::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_core_fellowship::Instance1, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + account.clone(), + None, + ); + let promote_member_xcm = build_xcm_send_fellowship_core_promote_member::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_core_fellowship::Instance1, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + account.clone(), + collectives_polkadot_runtime::fellowship::ranks::DAN_1, + None, + ); + let demote_member_xcm = build_xcm_send_fellowship_demote_member::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_ranked_collective::Instance1, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + account.clone(), + None, + ); + let remove_member_xcm = build_xcm_send_fellowship_remove_member::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_ranked_collective::Instance1, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + account.clone(), + 0, + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_params_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_params_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::FellowshipCore(pallet_core_fellowship::Event::ParamsChanged { .. }) => {}, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(induct_member_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(induct_member_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::FellowshipCollective(pallet_ranked_collective::Event::MemberAdded { who }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::FellowshipCore(pallet_core_fellowship::Event::Inducted { who }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(promote_member_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(promote_member_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::FellowshipCollective(pallet_ranked_collective::Event::RankChanged { who, rank: 1 }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::FellowshipCore(pallet_core_fellowship::Event::Promoted { who, to_rank: 1 }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(demote_member_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(demote_member_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::FellowshipCollective(pallet_ranked_collective::Event::RankChanged { who, rank: 0 }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(remove_member_xcm.clone().dispatch(bad_origin)); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(remove_member_xcm.dispatch(ok_origin)); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::FellowshipCollective(pallet_ranked_collective::Event::MemberRemoved { who, rank }) => { + who: *who == account, + rank: *rank == 0, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_fellowship_admin_can_manage_ambassadors_on_collectives() { + type AssetHubOrigin = ::RuntimeOrigin; + type CollectivesRuntime = ::Runtime; + type CollectivesRuntimeEvent = ::RuntimeEvent; + + let account: ::AccountId = Charlie.to_account_id(); + let ok_origin: AssetHubOrigin = Origin::FellowshipAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + + let set_params_xcm = build_xcm_send_fellowship_core_set_rank1_min_promotion_period::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_core_fellowship::Instance2, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + 1, + None, + ); + let induct_member_xcm = build_xcm_send_induct_member::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_core_fellowship::Instance2, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + account.clone(), + None, + ); + let promote_member_xcm = build_xcm_send_fellowship_core_promote_member::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_core_fellowship::Instance2, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + account.clone(), + collectives_polkadot_runtime::fellowship::ranks::DAN_1, + None, + ); + let demote_member_xcm = build_xcm_send_fellowship_demote_member::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_ranked_collective::Instance2, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + account.clone(), + None, + ); + let remove_member_xcm = build_xcm_send_fellowship_remove_member::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_ranked_collective::Instance2, + >( + AssetHubPolkadot::sibling_location_of(::para_id()), + account.clone(), + 0, + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_params_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_params_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::AmbassadorCore(pallet_core_fellowship::Event::ParamsChanged { .. }) => {}, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(induct_member_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(induct_member_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::AmbassadorCollective(pallet_ranked_collective::Event::MemberAdded { who }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::AmbassadorCore(pallet_core_fellowship::Event::Inducted { who }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(promote_member_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(promote_member_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::AmbassadorCollective(pallet_ranked_collective::Event::RankChanged { who, rank: 1 }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::AmbassadorCore(pallet_core_fellowship::Event::Promoted { who, to_rank: 1 }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(demote_member_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(demote_member_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::AmbassadorCollective(pallet_ranked_collective::Event::RankChanged { who, rank: 0 }) => { + who: *who == account, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(remove_member_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(remove_member_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::AmbassadorCollective(pallet_ranked_collective::Event::MemberRemoved { who, rank }) => { + who: *who == account, + rank: *rank == 0, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_staking_admin_can_manage_collator_config_on_other_chains() { + type AssetHubOrigin = ::RuntimeOrigin; + type CoretimeRuntimeEvent = ::RuntimeEvent; + type BridgeHubRuntimeEvent = ::RuntimeEvent; + type PeopleRuntimeEvent = ::RuntimeEvent; + type CollectivesRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::FellowshipAdmin.into(); + + let new_desired_candidates = 23; // random number + + let set_candidates_xcm_coretime = + build_xcm_send_set_desired_candidates::( + AssetHubPolkadot::sibling_location_of(CoretimePolkadot::para_id()), + new_desired_candidates, + None, + ); + let set_candidates_xcm_bridge_hub = + build_xcm_send_set_desired_candidates::( + AssetHubPolkadot::sibling_location_of(BridgeHubPolkadot::para_id()), + new_desired_candidates, + None, + ); + let set_candidates_xcm_people = + build_xcm_send_set_desired_candidates::( + AssetHubPolkadot::sibling_location_of(PeoplePolkadot::para_id()), + new_desired_candidates, + None, + ); + let set_candidates_xcm_collectives = + build_xcm_send_set_desired_candidates::( + AssetHubPolkadot::sibling_location_of(CollectivesPolkadot::para_id()), + new_desired_candidates, + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_candidates_xcm_coretime.clone().dispatch(bad_origin.clone())); + }); + CoretimePolkadot::execute_with(|| { + assert_expected_events!( + CoretimePolkadot, + vec![ + CoretimeRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_candidates_xcm_coretime.dispatch(ok_origin.clone())); + }); + CoretimePolkadot::execute_with(|| { + assert_expected_events!( + CoretimePolkadot, + vec![ + CoretimeRuntimeEvent::CollatorSelection(pallet_collator_selection::Event::NewDesiredCandidates { desired_candidates }) => { + desired_candidates: *desired_candidates == new_desired_candidates, + }, + CoretimeRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_candidates_xcm_bridge_hub.clone().dispatch(bad_origin.clone())); + }); + BridgeHubPolkadot::execute_with(|| { + assert_expected_events!( + BridgeHubPolkadot, + vec![ + BridgeHubRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_candidates_xcm_bridge_hub.dispatch(ok_origin.clone())); + }); + BridgeHubPolkadot::execute_with(|| { + assert_expected_events!( + BridgeHubPolkadot, + vec![ + BridgeHubRuntimeEvent::CollatorSelection(pallet_collator_selection::Event::NewDesiredCandidates { desired_candidates }) => { + desired_candidates: *desired_candidates == new_desired_candidates, + }, + BridgeHubRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_candidates_xcm_people.clone().dispatch(bad_origin.clone())); + }); + PeoplePolkadot::execute_with(|| { + assert_expected_events!( + PeoplePolkadot, + vec![ + PeopleRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_candidates_xcm_people.dispatch(ok_origin.clone())); + }); + PeoplePolkadot::execute_with(|| { + assert_expected_events!( + PeoplePolkadot, + vec![ + PeopleRuntimeEvent::CollatorSelection(pallet_collator_selection::Event::NewDesiredCandidates { desired_candidates }) => { + desired_candidates: *desired_candidates == new_desired_candidates, + }, + PeopleRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_candidates_xcm_collectives.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_candidates_xcm_collectives.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::CollatorSelection(pallet_collator_selection::Event::NewDesiredCandidates { desired_candidates }) => { + desired_candidates: *desired_candidates == new_desired_candidates, + }, + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_general_admin_can_manage_hrmp_on_relay() { + type AssetHubOrigin = ::RuntimeOrigin; + type PolkadotRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + + let force_clean_hrmp_xcm = build_xcm_send_force_clean_hrmp::( + AssetHubPolkadot::parent_location(), + PeoplePolkadot::para_id(), + 0, + 0, + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(force_clean_hrmp_xcm.clone().dispatch(bad_origin.clone())); + }); + Polkadot::execute_with(|| { + assert_expected_events!( + Polkadot, + vec![ + PolkadotRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(force_clean_hrmp_xcm.dispatch(ok_origin.clone())); + }); + Polkadot::execute_with(|| { + assert_expected_events!( + Polkadot, + vec![ + PolkadotRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_staking_admin_can_manage_staking_on_relay() { + type AssetHubOrigin = ::RuntimeOrigin; + type PolkadotRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + + let set_min_commisions_xcm = build_xcm_send_set_min_commissions::( + AssetHubPolkadot::parent_location(), + sp_runtime::Perbill::from_percent(80), + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_min_commisions_xcm.clone().dispatch(bad_origin.clone())); + }); + Polkadot::execute_with(|| { + assert_expected_events!( + Polkadot, + vec![ + PolkadotRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_min_commisions_xcm.dispatch(ok_origin.clone())); + }); + Polkadot::execute_with(|| { + assert_expected_events!( + Polkadot, + vec![ + PolkadotRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_staking_admin_can_manage_elections_on_relay() { + type AssetHubOrigin = ::RuntimeOrigin; + type PolkadotRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::StakingAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + + let new_score = + sp_npos_elections::ElectionScore { minimal_stake: 0, sum_stake: 0, sum_stake_squared: 0 }; + + let set_minimum_untrusted_score_xcm = + build_xcm_send_set_minimum_untrusted_score::( + AssetHubPolkadot::parent_location(), + Some(new_score), + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_minimum_untrusted_score_xcm.clone().dispatch(bad_origin.clone())); + }); + Polkadot::execute_with(|| { + assert_expected_events!( + Polkadot, + vec![ + PolkadotRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(set_minimum_untrusted_score_xcm.dispatch(ok_origin.clone())); + }); + Polkadot::execute_with(|| { + assert_expected_events!( + Polkadot, + vec![ + PolkadotRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); +} + +#[test] +fn assethub_treasurer_can_manage_asset_rate_on_collectives() { + type AssetHubOrigin = ::RuntimeOrigin; + type CollectivesRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::Treasurer.into(); + let bad_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + + let test_asset_kind = polkadot_runtime_common::impls::VersionedLocatableAsset::V5 { + location: Location::new(0, [Parachain(1004)]), + asset_id: Location::parent().into(), + }; + let test_rate = 100.into(); + let updated_test_rate = test_rate * 2.into(); + + let asset_rate_create_xcm = + build_xcm_send_asset_rate_create::( + AssetHubPolkadot::sibling_location_of(CollectivesPolkadot::para_id()), + test_asset_kind.clone(), + test_rate, + None, + ); + + let asset_rate_update_xcm = + build_xcm_send_asset_rate_update::( + AssetHubPolkadot::sibling_location_of(CollectivesPolkadot::para_id()), + test_asset_kind.clone(), + updated_test_rate, + None, + ); + + let asset_rate_remove_xcm = + build_xcm_send_asset_rate_remove::( + AssetHubPolkadot::sibling_location_of(CollectivesPolkadot::para_id()), + test_asset_kind.clone(), + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(asset_rate_create_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(asset_rate_create_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + CollectivesRuntimeEvent::AssetRate(pallet_asset_rate::Event::AssetRateCreated { asset_kind, rate }) => { + asset_kind: *asset_kind == test_asset_kind, + rate: *rate == test_rate, + }, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(asset_rate_update_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(asset_rate_update_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + CollectivesRuntimeEvent::AssetRate(pallet_asset_rate::Event::AssetRateUpdated { asset_kind, old, new }) => { + asset_kind: *asset_kind == test_asset_kind, + old: *old == test_rate, + new: *new == updated_test_rate, + }, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(asset_rate_remove_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false,.. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(asset_rate_remove_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + CollectivesRuntimeEvent::AssetRate(pallet_asset_rate::Event::AssetRateRemoved { asset_kind }) => { + asset_kind: *asset_kind == test_asset_kind, + }, + ] + ); + }); +} + +#[test] +fn assethub_treasurer_can_manage_spend_from_fellowship_treasury_on_collectives() { + type AssetHubOrigin = ::RuntimeOrigin; + type CollectivesRuntimeEvent = ::RuntimeEvent; + + let ok_origin: AssetHubOrigin = Origin::Treasurer.into(); + let bad_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + + let test_asset_kind = polkadot_runtime_common::impls::VersionedLocatableAsset::V5 { + location: Location::new(1, [Parachain(1004)]), + asset_id: Location::parent().into(), + }; + let test_amount = 1_000u128; + let test_beneficiary: VersionedLocation = VersionedLocation::V5(Location::new( + 0, + [AccountId32 { network: None::, id: Charlie.into() }], + )); + let test_valid_from = 0u32; + let expected_index = 0u32; + + let treasury_spend_xcm: asset_hub_polkadot_runtime::RuntimeCall = build_xcm_send_treasury_spend::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_treasury::Instance1, + _, + >( + AssetHubPolkadot::sibling_location_of(CollectivesPolkadot::para_id()), + test_asset_kind.clone(), + test_amount, + test_beneficiary.clone(), + Some(test_valid_from), + None, + ); + + let treasury_void_spend_xcm: asset_hub_polkadot_runtime::RuntimeCall = + build_xcm_send_treasury_void_spend::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_treasury::Instance1, + >( + AssetHubPolkadot::sibling_location_of(CollectivesPolkadot::para_id()), + expected_index, + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(treasury_spend_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false, .. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(treasury_spend_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + CollectivesRuntimeEvent::FellowshipTreasury(pallet_treasury::Event::AssetSpendApproved { index, asset_kind, amount, beneficiary, valid_from, .. }) => { + index: *index == expected_index, + asset_kind: *asset_kind == test_asset_kind, + amount: *amount == test_amount, + beneficiary: *beneficiary == test_beneficiary, + valid_from: *valid_from == test_valid_from, + }, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(treasury_void_spend_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false, .. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(treasury_void_spend_xcm.dispatch(ok_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + CollectivesRuntimeEvent::FellowshipTreasury(pallet_treasury::Event::AssetSpendVoided { index }) => { + index: *index == expected_index, + }, + ] + ); + }); +} + +#[test] +fn assethub_treasurer_can_manage_spend_from_ambassador_treasury_on_collectives() { + type AssetHubOrigin = ::RuntimeOrigin; + type CollectivesRuntimeEvent = ::RuntimeEvent; + + let ok_origin_spend: AssetHubOrigin = Origin::Treasurer.into(); + let ok_origin_void_spend: AssetHubOrigin = Origin::FellowshipAdmin.into(); + let bad_origin: AssetHubOrigin = Origin::GeneralAdmin.into(); + + let test_asset_kind = polkadot_runtime_common::impls::VersionedLocatableAsset::V5 { + location: Location::new(1, [Parachain(1004)]), + asset_id: Location::parent().into(), + }; + let test_amount = 1_000u128; + let test_beneficiary: VersionedLocation = VersionedLocation::V5(Location::new( + 0, + [AccountId32 { network: None::, id: Charlie.into() }], + )); + let test_valid_from = 0u32; + let expected_index = 0u32; + + let treasury_spend_xcm: asset_hub_polkadot_runtime::RuntimeCall = build_xcm_send_treasury_spend::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_treasury::Instance2, + _, + >( + AssetHubPolkadot::sibling_location_of(CollectivesPolkadot::para_id()), + test_asset_kind.clone(), + test_amount, + test_beneficiary.clone(), + Some(test_valid_from), + None, + ); + + let treasury_void_spend_xcm: asset_hub_polkadot_runtime::RuntimeCall = + build_xcm_send_treasury_void_spend::< + AssetHubPolkadot, + CollectivesPolkadot, + pallet_treasury::Instance2, + >( + AssetHubPolkadot::sibling_location_of(CollectivesPolkadot::para_id()), + expected_index, + None, + ); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(treasury_spend_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false, .. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(treasury_spend_xcm.dispatch(ok_origin_spend.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + CollectivesRuntimeEvent::AmbassadorTreasury(pallet_treasury::Event::AssetSpendApproved { index, asset_kind, amount, beneficiary, valid_from, .. }) => { + index: *index == expected_index, + asset_kind: *asset_kind == test_asset_kind, + amount: *amount == test_amount, + beneficiary: *beneficiary == test_beneficiary, + valid_from: *valid_from == test_valid_from, + }, + ] + ); + }); + + AssetHubPolkadot::execute_with(|| { + assert_ok!(treasury_void_spend_xcm.clone().dispatch(bad_origin.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false, .. }) => {}, + ] + ); + }); + AssetHubPolkadot::execute_with(|| { + assert_ok!(treasury_void_spend_xcm.dispatch(ok_origin_void_spend.clone())); + }); + CollectivesPolkadot::execute_with(|| { + assert_expected_events!( + CollectivesPolkadot, + vec![ + CollectivesRuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + CollectivesRuntimeEvent::AmbassadorTreasury(pallet_treasury::Event::AssetSpendVoided { index }) => { + index: *index == expected_index, + }, + ] + ); + }); +} diff --git a/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_asset_hub_via_relay.rs b/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_asset_hub_via_relay.rs new file mode 100644 index 0000000000..5c273564f6 --- /dev/null +++ b/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_asset_hub_via_relay.rs @@ -0,0 +1,175 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +use crate::{common::*, imports::*}; + +use asset_hub_polkadot_runtime::governance::pallet_custom_origins::Origin; + +#[test] +fn assethub_can_authorize_upgrade_for_system_chains_via_relay_chain() { + type AssetHubRuntime = ::Runtime; + type AssetHubRuntimeCall = ::RuntimeCall; + type AssetHubRuntimeOrigin = ::RuntimeOrigin; + + let code_hash_bridge_hub = [2u8; 32].into(); + let code_hash_collectives = [3u8; 32].into(); + let code_hash_coretime = [4u8; 32].into(); + let code_hash_people = [5u8; 32].into(); + + Polkadot::execute_with(|| { + Dmp::make_parachain_reachable(BridgeHubPolkadot::para_id()); + Dmp::make_parachain_reachable(CollectivesPolkadot::para_id()); + Dmp::make_parachain_reachable(CoretimePolkadot::para_id()); + Dmp::make_parachain_reachable(PeoplePolkadot::para_id()); + }); + + let authorize_upgrade = + AssetHubRuntimeCall::Utility(pallet_utility::Call::::force_batch { + calls: vec![ + build_xcm_send_call::( + AssetHubPolkadot::parent_location(), + None, + build_xcm_send_authorize_upgrade_call::( + Polkadot::child_location_of(BridgeHubPolkadot::para_id()), + &code_hash_bridge_hub, + None, + ), + OriginKind::Superuser, + ), + build_xcm_send_call::( + AssetHubPolkadot::parent_location(), + None, + build_xcm_send_authorize_upgrade_call::( + Polkadot::child_location_of(CollectivesPolkadot::para_id()), + &code_hash_collectives, + None, + ), + OriginKind::Superuser, + ), + build_xcm_send_call::( + AssetHubPolkadot::parent_location(), + None, + build_xcm_send_authorize_upgrade_call::( + Polkadot::child_location_of(CoretimePolkadot::para_id()), + &code_hash_coretime, + None, + ), + OriginKind::Superuser, + ), + build_xcm_send_call::( + AssetHubPolkadot::parent_location(), + None, + build_xcm_send_authorize_upgrade_call::( + Polkadot::child_location_of(PeoplePolkadot::para_id()), + &code_hash_people, + None, + ), + OriginKind::Superuser, + ), + ], + }); + + // bad origin + let invalid_origin: AssetHubRuntimeOrigin = Origin::StakingAdmin.into(); + // ok origin + let ok_origin: AssetHubRuntimeOrigin = Origin::WhitelistedCaller.into(); + + let call_hash = call_hash_of::(&authorize_upgrade); + + // Err - when dispatch non-whitelisted + assert_err!( + dispatch_whitelisted_call_with_preimage::( + authorize_upgrade.clone(), + ok_origin.clone() + ), + DispatchError::Module(sp_runtime::ModuleError { + index: 64, + error: [3, 0, 0, 0], + message: Some("CallIsNotWhitelisted") + }) + ); + + // whitelist + collectives_send_whitelist( + CollectivesPolkadot::sibling_location_of(::para_id()), + || { + AssetHubRuntimeCall::Whitelist( + pallet_whitelist::Call::::whitelist_call { call_hash }, + ) + .encode() + }, + ); + AssetHubPolkadot::execute_with(|| { + assert_whitelisted!(AssetHubPolkadot, call_hash); + }); + + // Err - when dispatch wrong origin + assert_err!( + dispatch_whitelisted_call_with_preimage::( + authorize_upgrade.clone(), + invalid_origin + ), + DispatchError::BadOrigin + ); + + // check before + BridgeHubPolkadot::execute_with(|| { + assert!(::System::authorized_upgrade().is_none()) + }); + CollectivesPolkadot::execute_with(|| { + assert!(::System::authorized_upgrade().is_none()) + }); + CoretimePolkadot::execute_with(|| { + assert!(::System::authorized_upgrade().is_none()) + }); + PeoplePolkadot::execute_with(|| { + assert!(::System::authorized_upgrade().is_none()) + }); + + // ok - authorized + assert_ok!(dispatch_whitelisted_call_with_preimage::( + authorize_upgrade, + ok_origin + )); + + Polkadot::execute_with(|| {}); + + // check after - authorized + BridgeHubPolkadot::execute_with(|| { + assert_eq!( + ::System::authorized_upgrade().unwrap().code_hash(), + &code_hash_bridge_hub + ) + }); + CollectivesPolkadot::execute_with(|| { + assert_eq!( + ::System::authorized_upgrade() + .unwrap() + .code_hash(), + &code_hash_collectives + ) + }); + CoretimePolkadot::execute_with(|| { + assert_eq!( + ::System::authorized_upgrade().unwrap().code_hash(), + &code_hash_coretime + ) + }); + PeoplePolkadot::execute_with(|| { + assert_eq!( + ::System::authorized_upgrade().unwrap().code_hash(), + &code_hash_people + ) + }); +} diff --git a/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_relay.rs b/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_relay.rs index 7044a6c6b6..54804cbe5f 100644 --- a/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_relay.rs +++ b/integration-tests/emulated/tests/governance/polkadot/src/open_gov_on_relay.rs @@ -21,13 +21,9 @@ fn relaychain_can_authorize_upgrade_for_itself() { type PolkadotRuntimeCall = ::RuntimeCall; type PolkadotRuntimeOrigin = ::RuntimeOrigin; + // upgrade the relaychain let authorize_upgrade = - PolkadotRuntimeCall::Utility(pallet_utility::Call::::force_batch { - calls: vec![ - // upgrade the relaychain - PolkadotRuntimeCall::System(frame_system::Call::authorize_upgrade { code_hash }), - ], - }); + PolkadotRuntimeCall::System(frame_system::Call::authorize_upgrade { code_hash }); // bad origin let invalid_origin: PolkadotRuntimeOrigin = Origin::StakingAdmin.into(); diff --git a/integration-tests/emulated/tests/people/people-kusama/Cargo.toml b/integration-tests/emulated/tests/people/people-kusama/Cargo.toml index 90c6d7500d..0d9c995294 100644 --- a/integration-tests/emulated/tests/people/people-kusama/Cargo.toml +++ b/integration-tests/emulated/tests/people/people-kusama/Cargo.toml @@ -43,7 +43,6 @@ runtime-benchmarks = [ "asset-hub-kusama-runtime/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "kusama-runtime-constants/runtime-benchmarks", "kusama-runtime/runtime-benchmarks", "kusama-system-emulated-network/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/people/people-kusama/src/tests/governance.rs b/integration-tests/emulated/tests/people/people-kusama/src/tests/governance.rs index 5b54f37302..65c8d4e7fb 100644 --- a/integration-tests/emulated/tests/people/people-kusama/src/tests/governance.rs +++ b/integration-tests/emulated/tests/people/people-kusama/src/tests/governance.rs @@ -37,14 +37,16 @@ fn relay_commands_add_registrar() { type PeopleCall = ::RuntimeCall; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeopleKusama::para_id()); let add_registrar_call = PeopleCall::Identity(pallet_identity::Call::::add_registrar { account: registrar.into(), }); let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Kusama::child_location_of( + PeopleKusama::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { @@ -154,14 +156,14 @@ fn relay_commands_add_registrar_wrong_origin() { type PeopleCall = ::RuntimeCall; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeopleKusama::para_id()); let add_registrar_call = PeopleCall::Identity(pallet_identity::Call::::add_registrar { account: registrar.into(), }); let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Kusama::child_location_of(PeopleKusama::para_id()))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { @@ -233,22 +235,19 @@ fn relay_commands_kill_identity() { type RuntimeEvent = ::RuntimeEvent; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeopleKusama::para_id()); let kill_identity_call = PeopleCall::Identity(pallet_identity::Call::::kill_identity { target: people_kusama_runtime::MultiAddress::Id(PeopleKusama::account_id_of(ALICE)), }); let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Kusama::child_location_of(PeopleKusama::para_id()))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - // Making the weight's ref time any lower will prevent the XCM from triggering - // execution of the intended extrinsic on the People chain - beware of spurious - // test failure due to this. - fallback_max_weight: Some(Weight::from_parts(11_000_000_000, 500_000)), + fallback_max_weight: None, call: kill_identity_call.encode().into(), } ]))), @@ -293,19 +292,19 @@ fn relay_commands_kill_identity_wrong_origin() { type RuntimeEvent = ::RuntimeEvent; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeopleKusama::para_id()); let kill_identity_call = PeopleCall::Identity(pallet_identity::Call::::kill_identity { target: people_kusama_runtime::MultiAddress::Id(PeopleKusama::account_id_of(ALICE)), }); let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Kusama::child_location_of(PeopleKusama::para_id()))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - fallback_max_weight: Some(Weight::from_parts(11_000_000_000, 500_000)), + fallback_max_weight: None, call: kill_identity_call.encode().into(), } ]))), @@ -351,7 +350,7 @@ fn relay_commands_add_remove_username_authority() { type PeopleCall = ::RuntimeCall; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeopleKusama::para_id()); let add_username_authority = PeopleCall::Identity(pallet_identity::Call::< PeopleRuntime, >::add_username_authority { @@ -361,12 +360,14 @@ fn relay_commands_add_remove_username_authority() { }); let add_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Kusama::child_location_of( + PeopleKusama::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + fallback_max_weight: None, call: add_username_authority.encode().into(), } ]))), @@ -452,7 +453,9 @@ fn relay_commands_add_remove_username_authority() { let remove_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Kusama::child_location_of( + PeopleKusama::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { @@ -504,7 +507,7 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { type PeopleCall = ::RuntimeCall; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeopleKusama::para_id()); let add_username_authority = PeopleCall::Identity(pallet_identity::Call::::add_username_authority { authority: people_kusama_runtime::MultiAddress::Id(people_kusama_alice.clone()), @@ -513,12 +516,12 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { }); let add_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Kusama::child_location_of(PeopleKusama::para_id()))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + fallback_max_weight: None, call: add_username_authority.encode().into(), } ]))), @@ -563,12 +566,12 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { }); let remove_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Kusama::child_location_of(PeopleKusama::para_id()))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind: OriginKind::SovereignAccount, - fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + fallback_max_weight: None, call: remove_username_authority.encode().into(), } ]))), @@ -596,3 +599,162 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { ); }); } + +#[test] +fn asset_hub_commands_add_remove_username_authority() { + let people_kusama_alice = PeopleKusama::account_id_of(ALICE); + let people_kusama_bob = PeopleKusama::account_id_of(BOB); + + let origins = vec![ + (OriginKind::Xcm, GeneralAdminOriginFromAssetHub.into(), "generaladmin.suffix1"), + ( + OriginKind::Superuser, + ::RuntimeOrigin::root(), + "rootusername.suffix1", + ), + ]; + for (origin_kind, origin, usr) in origins { + // First, add a username authority. + AssetHubKusama::execute_with(|| { + type Runtime = ::Runtime; + type RuntimeCall = ::RuntimeCall; + type RuntimeEvent = ::RuntimeEvent; + type PeopleCall = ::RuntimeCall; + type PeopleRuntime = ::Runtime; + + let add_username_authority = PeopleCall::Identity(pallet_identity::Call::< + PeopleRuntime, + >::add_username_authority { + authority: people_kusama_runtime::MultiAddress::Id(people_kusama_alice.clone()), + suffix: b"suffix1".into(), + allocation: 10, + }); + + let add_authority_xcm_msg = + RuntimeCall::PolkadotXcm(pallet_xcm::Call::::send { + dest: bx!(VersionedLocation::from(Location::new(1, [Parachain(1004)]))), + message: bx!(VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { + origin_kind, + fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + call: add_username_authority.encode().into(), + } + ]))), + }); + + assert_ok!(add_authority_xcm_msg.dispatch(origin.clone())); + + assert_expected_events!( + AssetHubKusama, + vec![ + RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + // Check events system-parachain-side + PeopleKusama::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + PeopleKusama, + vec![ + RuntimeEvent::Identity(pallet_identity::Event::AuthorityAdded { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + // Now, use the previously added username authority to concede a username to an account. + PeopleKusama::execute_with(|| { + type PeopleRuntimeEvent = ::RuntimeEvent; + + println!("setting username {usr}"); + + assert_ok!(::Identity::set_username_for( + ::RuntimeOrigin::signed(people_kusama_alice.clone()), + people_kusama_runtime::MultiAddress::Id(people_kusama_bob.clone()), + usr.to_owned().into_bytes(), + None, + false, + )); + + assert_expected_events!( + PeopleKusama, + vec![ + PeopleRuntimeEvent::Identity(pallet_identity::Event::UsernameQueued { .. }) => {}, + ] + ); + }); + + // Accept the given username + PeopleKusama::execute_with(|| { + type PeopleRuntimeEvent = ::RuntimeEvent; + let full_username = usr.to_owned().into_bytes(); + + assert_ok!(::Identity::accept_username( + ::RuntimeOrigin::signed(people_kusama_bob.clone()), + full_username.try_into().unwrap(), + )); + + assert_expected_events!( + PeopleKusama, + vec![ + PeopleRuntimeEvent::Identity(pallet_identity::Event::UsernameSet { .. }) => {}, + ] + ); + }); + + // Now, remove the username authority with another privileged XCM call. + AssetHubKusama::execute_with(|| { + type Runtime = ::Runtime; + type RuntimeCall = ::RuntimeCall; + type RuntimeEvent = ::RuntimeEvent; + type PeopleCall = ::RuntimeCall; + type PeopleRuntime = ::Runtime; + + let remove_username_authority = PeopleCall::Identity(pallet_identity::Call::< + PeopleRuntime, + >::remove_username_authority { + authority: people_kusama_runtime::MultiAddress::Id(people_kusama_alice.clone()), + suffix: b"suffix1".to_vec(), + }); + + let remove_authority_xcm_msg = + RuntimeCall::PolkadotXcm(pallet_xcm::Call::::send { + dest: bx!(VersionedLocation::from(Location::new(1, [Parachain(1004)]))), + message: bx!(VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { + origin_kind, + fallback_max_weight: None, + call: remove_username_authority.encode().into(), + } + ]))), + }); + + assert_ok!(remove_authority_xcm_msg.dispatch(origin)); + + assert_expected_events!( + AssetHubKusama, + vec![ + RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + // Final event check. + PeopleKusama::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + PeopleKusama, + vec![ + RuntimeEvent::Identity(pallet_identity::Event::AuthorityRemoved { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + } +} diff --git a/integration-tests/emulated/tests/people/people-polkadot/Cargo.toml b/integration-tests/emulated/tests/people/people-polkadot/Cargo.toml index 2970e3ada2..d756bd69ca 100644 --- a/integration-tests/emulated/tests/people/people-polkadot/Cargo.toml +++ b/integration-tests/emulated/tests/people/people-polkadot/Cargo.toml @@ -43,7 +43,6 @@ runtime-benchmarks = [ "asset-hub-polkadot-runtime/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "frame-support/runtime-benchmarks", - "integration-tests-helpers/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", diff --git a/integration-tests/emulated/tests/people/people-polkadot/src/tests/governance.rs b/integration-tests/emulated/tests/people/people-polkadot/src/tests/governance.rs index 8088ec03c0..0ab27071c7 100644 --- a/integration-tests/emulated/tests/people/people-polkadot/src/tests/governance.rs +++ b/integration-tests/emulated/tests/people/people-polkadot/src/tests/governance.rs @@ -37,14 +37,16 @@ fn relay_commands_add_registrar() { type PeopleCall = ::RuntimeCall; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeoplePolkadot::para_id()); let add_registrar_call = PeopleCall::Identity(pallet_identity::Call::::add_registrar { account: registrar.into(), }); let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Polkadot::child_location_of( + PeoplePolkadot::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { @@ -154,14 +156,16 @@ fn relay_commands_add_registrar_wrong_origin() { type PeopleCall = ::RuntimeCall; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeoplePolkadot::para_id()); let add_registrar_call = PeopleCall::Identity(pallet_identity::Call::::add_registrar { account: registrar.into(), }); let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Polkadot::child_location_of( + PeoplePolkadot::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { @@ -233,7 +237,7 @@ fn relay_commands_kill_identity() { type RuntimeEvent = ::RuntimeEvent; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeoplePolkadot::para_id()); let kill_identity_call = PeopleCall::Identity(pallet_identity::Call::::kill_identity { target: people_polkadot_runtime::MultiAddress::Id(PeoplePolkadot::account_id_of( @@ -242,15 +246,14 @@ fn relay_commands_kill_identity() { }); let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Polkadot::child_location_of( + PeoplePolkadot::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - // Making the weight's ref time any lower will prevent the XCM from triggering - // execution of the intended extrinsic on the People chain - beware of spurious - // test failure due to this. - fallback_max_weight: Some(Weight::from_parts(11_000_000_000, 500_000)), + fallback_max_weight: None, call: kill_identity_call.encode().into(), } ]))), @@ -295,7 +298,7 @@ fn relay_commands_kill_identity_wrong_origin() { type RuntimeEvent = ::RuntimeEvent; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeoplePolkadot::para_id()); let kill_identity_call = PeopleCall::Identity(pallet_identity::Call::::kill_identity { target: people_polkadot_runtime::MultiAddress::Id(PeoplePolkadot::account_id_of( @@ -304,12 +307,14 @@ fn relay_commands_kill_identity_wrong_origin() { }); let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Polkadot::child_location_of( + PeoplePolkadot::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - fallback_max_weight: Some(Weight::from_parts(11_000_000_000, 500_000)), + fallback_max_weight: None, call: kill_identity_call.encode().into(), } ]))), @@ -355,7 +360,7 @@ fn relay_commands_add_remove_username_authority() { type PeopleCall = ::RuntimeCall; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeoplePolkadot::para_id()); let add_username_authority = PeopleCall::Identity(pallet_identity::Call::< PeopleRuntime, >::add_username_authority { @@ -365,12 +370,14 @@ fn relay_commands_add_remove_username_authority() { }); let add_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Polkadot::child_location_of( + PeoplePolkadot::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + fallback_max_weight: None, call: add_username_authority.encode().into(), } ]))), @@ -454,12 +461,14 @@ fn relay_commands_add_remove_username_authority() { let remove_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Polkadot::child_location_of( + PeoplePolkadot::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + fallback_max_weight: None, call: remove_username_authority.encode().into(), } ]))), @@ -506,7 +515,7 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { type PeopleCall = ::RuntimeCall; type PeopleRuntime = ::Runtime; - Dmp::make_parachain_reachable(1004); + Dmp::make_parachain_reachable(PeoplePolkadot::para_id()); let add_username_authority = PeopleCall::Identity(pallet_identity::Call::::add_username_authority { authority: people_polkadot_runtime::MultiAddress::Id(people_polkadot_alice.clone()), @@ -515,12 +524,14 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { }); let add_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Polkadot::child_location_of( + PeoplePolkadot::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind, - fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + fallback_max_weight: None, call: add_username_authority.encode().into(), } ]))), @@ -565,12 +576,14 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { }); let remove_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::::send { - dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), + dest: bx!(VersionedLocation::from(Polkadot::child_location_of( + PeoplePolkadot::para_id() + ))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { origin_kind: OriginKind::SovereignAccount, - fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + fallback_max_weight: None, call: remove_username_authority.encode().into(), } ]))), @@ -598,3 +611,160 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { ); }); } + +#[test] +fn asset_hub_commands_add_remove_username_authority() { + let people_polkadot_alice = PeoplePolkadot::account_id_of(ALICE); + let people_polkadot_bob = PeoplePolkadot::account_id_of(BOB); + + let origins = vec![ + (OriginKind::Xcm, GeneralAdminOriginFromAssetHub.into(), "generaladmin.suffix1"), + ( + OriginKind::Superuser, + ::RuntimeOrigin::root(), + "rootusername.suffix1", + ), + ]; + for (origin_kind, origin, usr) in origins { + // First, add a username authority. + AssetHubPolkadot::execute_with(|| { + type Runtime = ::Runtime; + type RuntimeCall = ::RuntimeCall; + type RuntimeEvent = ::RuntimeEvent; + type PeopleCall = ::RuntimeCall; + type PeopleRuntime = ::Runtime; + + let add_username_authority = PeopleCall::Identity(pallet_identity::Call::< + PeopleRuntime, + >::add_username_authority { + authority: people_polkadot_runtime::MultiAddress::Id(people_polkadot_alice.clone()), + suffix: b"suffix1".into(), + allocation: 10, + }); + + let add_authority_xcm_msg = + RuntimeCall::PolkadotXcm(pallet_xcm::Call::::send { + dest: bx!(VersionedLocation::from(Location::new(1, [Parachain(1004)]))), + message: bx!(VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { + origin_kind, + fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + call: add_username_authority.encode().into(), + } + ]))), + }); + + assert_ok!(add_authority_xcm_msg.dispatch(origin.clone())); + + assert_expected_events!( + AssetHubPolkadot, + vec![ + RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + // Check events system-parachain-side + PeoplePolkadot::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + PeoplePolkadot, + vec![ + RuntimeEvent::Identity(pallet_identity::Event::AuthorityAdded { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + + // Now, use the previously added username authority to concede a username to an account. + PeoplePolkadot::execute_with(|| { + type PeopleRuntimeEvent = ::RuntimeEvent; + + assert_ok!(::Identity::set_username_for( + ::RuntimeOrigin::signed(people_polkadot_alice.clone()), + people_polkadot_runtime::MultiAddress::Id(people_polkadot_bob.clone()), + usr.to_owned().into_bytes(), + None, + false, + )); + + assert_expected_events!( + PeoplePolkadot, + vec![ + PeopleRuntimeEvent::Identity(pallet_identity::Event::UsernameQueued { .. }) => {}, + ] + ); + }); + + // Accept the given username + PeoplePolkadot::execute_with(|| { + type PeopleRuntimeEvent = ::RuntimeEvent; + let full_username = usr.to_owned().into_bytes(); + + assert_ok!(::Identity::accept_username( + ::RuntimeOrigin::signed(people_polkadot_bob.clone()), + full_username.try_into().unwrap(), + )); + + assert_expected_events!( + PeoplePolkadot, + vec![ + PeopleRuntimeEvent::Identity(pallet_identity::Event::UsernameSet { .. }) => {}, + ] + ); + }); + + // Now, remove the username authority with another privileged XCM call. + AssetHubPolkadot::execute_with(|| { + type Runtime = ::Runtime; + type RuntimeCall = ::RuntimeCall; + type RuntimeEvent = ::RuntimeEvent; + type PeopleCall = ::RuntimeCall; + type PeopleRuntime = ::Runtime; + + let remove_username_authority = PeopleCall::Identity(pallet_identity::Call::< + PeopleRuntime, + >::remove_username_authority { + authority: people_polkadot_runtime::MultiAddress::Id(people_polkadot_alice.clone()), + suffix: b"suffix1".to_vec(), + }); + + let remove_authority_xcm_msg = + RuntimeCall::PolkadotXcm(pallet_xcm::Call::::send { + dest: bx!(VersionedLocation::from(Location::new(1, [Parachain(1004)]))), + message: bx!(VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { + origin_kind, + fallback_max_weight: Some(Weight::from_parts(500_000_000, 500_000)), + call: remove_username_authority.encode().into(), + } + ]))), + }); + + assert_ok!(remove_authority_xcm_msg.dispatch(origin)); + + assert_expected_events!( + AssetHubPolkadot, + vec![ + RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + // Final event check. + PeoplePolkadot::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + PeoplePolkadot, + vec![ + RuntimeEvent::Identity(pallet_identity::Event::AuthorityRemoved { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {}, + ] + ); + }); + } +} diff --git a/relay/kusama/src/governance/fellowship.rs b/relay/kusama/src/governance/fellowship.rs index e1c1eb329e..a609b2866f 100644 --- a/relay/kusama/src/governance/fellowship.rs +++ b/relay/kusama/src/governance/fellowship.rs @@ -336,7 +336,7 @@ impl pallet_ranked_collective::Config for Runtime type WeightInfo = weights::pallet_ranked_collective::WeightInfo; type RuntimeEvent = RuntimeEvent; // Promotion is by any of: - // - Root can demote arbitrarily. + // - Root can promote arbitrarily. // - the FellowshipAdmin origin (i.e. token holder referendum); // - a vote by the rank *above* the new rank. type PromoteOrigin = EitherOf<