feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
||||
[package]
|
||||
name = "people-pezkuwichain-integration-tests"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "People Pezkuwichain runtime integration tests with xcm-emulator"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezpallet-balances = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
xcm = { workspace = true }
|
||||
xcm-executor = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
asset-test-utils = { workspace = true, default-features = true }
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
pezkuwichain-system-emulated-network = { workspace = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"asset-test-utils/runtime-benchmarks",
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezpallet-balances/runtime-benchmarks",
|
||||
"pezkuwichain-system-emulated-network/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm-executor/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// 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.
|
||||
|
||||
#[cfg(test)]
|
||||
mod imports {
|
||||
// Bizinikiwi
|
||||
pub(crate) use pezframe_support::pezsp_runtime::DispatchResult;
|
||||
|
||||
// Pezkuwi
|
||||
pub(crate) use xcm::{latest::PEZKUWICHAIN_GENESIS_HASH, prelude::*};
|
||||
|
||||
// Pezcumulus
|
||||
pub(crate) use asset_test_utils::xcm_helpers;
|
||||
pub(crate) use emulated_integration_tests_common::xcm_emulator::{
|
||||
assert_expected_events, bx, Chain, Test, TestArgs, TestContext, TestExt, Teyrchain as Para,
|
||||
};
|
||||
pub(crate) use pezkuwichain_system_emulated_network::{
|
||||
people_pezkuwichain_emulated_chain::{
|
||||
people_pezkuwichain_runtime::{
|
||||
xcm_config::XcmConfig as PeoplePezkuwichainXcmConfig,
|
||||
ExistentialDeposit as PeoplePezkuwichainExistentialDeposit,
|
||||
},
|
||||
PeoplePezkuwichainParaPallet as PeoplePezkuwichainPallet,
|
||||
},
|
||||
pezkuwichain_emulated_chain::{
|
||||
genesis::ED as PEZKUWICHAIN_ED, PezkuwichainRelayPallet as PezkuwichainPallet,
|
||||
},
|
||||
AssetHubPezkuwichainPara as AssetHubPezkuwichain,
|
||||
AssetHubPezkuwichainParaReceiver as AssetHubPezkuwichainReceiver,
|
||||
PeoplePezkuwichainPara as PeoplePezkuwichain,
|
||||
PeoplePezkuwichainParaReceiver as PeoplePezkuwichainReceiver,
|
||||
PeoplePezkuwichainParaSender as PeoplePezkuwichainSender,
|
||||
PezkuwichainRelay as Pezkuwichain, PezkuwichainRelayReceiver as PezkuwichainReceiver,
|
||||
PezkuwichainRelaySender as PezkuwichainSender,
|
||||
};
|
||||
pub(crate) use teyrchains_common::Balance;
|
||||
|
||||
pub(crate) type SystemParaToRelayTest = Test<PeoplePezkuwichain, Pezkuwichain>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
//! Tests related to claiming assets trapped during XCM execution.
|
||||
|
||||
use crate::imports::*;
|
||||
|
||||
use emulated_integration_tests_common::test_chain_can_claim_assets;
|
||||
|
||||
#[test]
|
||||
fn assets_can_be_claimed() {
|
||||
let amount = PeoplePezkuwichainExistentialDeposit::get();
|
||||
let assets: Assets = (Parent, amount).into();
|
||||
|
||||
test_chain_can_claim_assets!(
|
||||
PeoplePezkuwichain,
|
||||
RuntimeCall,
|
||||
NetworkId::ByGenesis(PEZKUWICHAIN_GENESIS_HASH),
|
||||
assets,
|
||||
amount
|
||||
);
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
mod claim_assets;
|
||||
mod teleport;
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
// 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::imports::*;
|
||||
use emulated_integration_tests_common::{
|
||||
test_relay_is_trusted_teleporter, test_teyrchain_is_trusted_teleporter,
|
||||
test_teyrchain_is_trusted_teleporter_for_relay,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn teleport_via_limited_teleport_assets_from_and_to_relay() {
|
||||
let amount = PEZKUWICHAIN_ED * 100;
|
||||
|
||||
test_relay_is_trusted_teleporter!(
|
||||
Pezkuwichain,
|
||||
vec![PeoplePezkuwichain],
|
||||
amount,
|
||||
limited_teleport_assets
|
||||
);
|
||||
|
||||
test_teyrchain_is_trusted_teleporter_for_relay!(
|
||||
PeoplePezkuwichain,
|
||||
Pezkuwichain,
|
||||
amount,
|
||||
limited_teleport_assets
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_transfer_assets_from_and_to_relay() {
|
||||
let amount = PEZKUWICHAIN_ED * 100;
|
||||
|
||||
test_relay_is_trusted_teleporter!(
|
||||
Pezkuwichain,
|
||||
vec![PeoplePezkuwichain],
|
||||
amount,
|
||||
transfer_assets
|
||||
);
|
||||
|
||||
test_teyrchain_is_trusted_teleporter_for_relay!(
|
||||
PeoplePezkuwichain,
|
||||
Pezkuwichain,
|
||||
amount,
|
||||
transfer_assets
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_limited_teleport_assets_to_other_system_teyrchains_works() {
|
||||
let amount = PEZKUWICHAIN_ED * 100;
|
||||
let native_asset: Assets = (Parent, amount).into();
|
||||
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
test_teyrchain_is_trusted_teleporter!(
|
||||
PeoplePezkuwichain, // Origin
|
||||
vec![AssetHubPezkuwichain], // Destinations
|
||||
(native_asset, amount),
|
||||
fee_asset_id,
|
||||
limited_teleport_assets
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_transfer_assets_to_other_system_teyrchains_works() {
|
||||
let amount = PEZKUWICHAIN_ED * 100;
|
||||
let native_asset: Assets = (Parent, amount).into();
|
||||
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
test_teyrchain_is_trusted_teleporter!(
|
||||
PeoplePezkuwichain, // Origin
|
||||
vec![AssetHubPezkuwichain], // Destinations
|
||||
(native_asset, amount),
|
||||
fee_asset_id,
|
||||
transfer_assets
|
||||
);
|
||||
}
|
||||
|
||||
fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) {
|
||||
Pezkuwichain::assert_ump_queue_processed(false, Some(PeoplePezkuwichain::para_id()), None);
|
||||
}
|
||||
|
||||
fn para_origin_assertions(t: SystemParaToRelayTest) {
|
||||
type RuntimeEvent = <PeoplePezkuwichain as Chain>::RuntimeEvent;
|
||||
|
||||
PeoplePezkuwichain::assert_xcm_pallet_attempted_complete(None);
|
||||
|
||||
PeoplePezkuwichain::assert_teyrchain_system_ump_sent();
|
||||
|
||||
assert_expected_events!(
|
||||
PeoplePezkuwichain,
|
||||
vec![
|
||||
// Amount is withdrawn from Sender's account
|
||||
RuntimeEvent::Balances(pezpallet_balances::Event::Burned { who, amount }) => {
|
||||
who: *who == t.sender.account_id,
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<PeoplePezkuwichain as PeoplePezkuwichainPallet>::PezkuwiXcm::limited_teleport_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
bx!(t.args.fee_asset_id.into()),
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
/// Limited Teleport of native asset from System Teyrchain to Relay Chain
|
||||
/// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount`
|
||||
#[test]
|
||||
fn limited_teleport_native_assets_from_system_para_to_relay_fails() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = PEZKUWICHAIN_ED * 1000;
|
||||
let destination = PeoplePezkuwichain::parent_location();
|
||||
let beneficiary_id = PezkuwichainReceiver::get();
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
|
||||
// Fund a sender
|
||||
PeoplePezkuwichain::fund_accounts(vec![(
|
||||
PeoplePezkuwichainSender::get(),
|
||||
PEZKUWICHAIN_ED * 2_000u128,
|
||||
)]);
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: PeoplePezkuwichainSender::get(),
|
||||
receiver: PezkuwichainReceiver::get(),
|
||||
args: TestArgs::new_para(
|
||||
destination,
|
||||
beneficiary_id,
|
||||
amount_to_send,
|
||||
assets,
|
||||
None,
|
||||
fee_asset_id,
|
||||
),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<PeoplePezkuwichain>(para_origin_assertions);
|
||||
test.set_assertion::<Pezkuwichain>(relay_dest_assertions_fail);
|
||||
test.set_dispatchable::<PeoplePezkuwichain>(system_para_limited_teleport_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
let delivery_fees = PeoplePezkuwichain::execute_with(|| {
|
||||
xcm_helpers::teleport_assets_delivery_fees::<
|
||||
<PeoplePezkuwichainXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(
|
||||
test.args.assets.clone(),
|
||||
test.args.fee_asset_id,
|
||||
test.args.weight_limit,
|
||||
test.args.beneficiary,
|
||||
test.args.dest,
|
||||
)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
// Receiver's balance does not change
|
||||
assert_eq!(receiver_balance_after, receiver_balance_before);
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
[package]
|
||||
name = "people-zagros-integration-tests"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "People Zagros runtime integration tests with xcm-emulator"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codec = { workspace = true }
|
||||
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezpallet-balances = { workspace = true }
|
||||
pezpallet-identity = { workspace = true }
|
||||
pezpallet-message-queue = { workspace = true }
|
||||
pezpallet-xcm = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
xcm = { workspace = true }
|
||||
xcm-executor = { workspace = true }
|
||||
zagros-runtime = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
emulated-integration-tests-common = { workspace = true }
|
||||
teyrchains-common = { workspace = true, default-features = true }
|
||||
zagros-system-emulated-network = { workspace = true }
|
||||
|
||||
[features]
|
||||
runtime-benchmarks = [
|
||||
"emulated-integration-tests-common/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezpallet-balances/runtime-benchmarks",
|
||||
"pezpallet-identity/runtime-benchmarks",
|
||||
"pezpallet-message-queue/runtime-benchmarks",
|
||||
"pezpallet-xcm/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"teyrchains-common/runtime-benchmarks",
|
||||
"xcm-executor/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
"zagros-runtime/runtime-benchmarks",
|
||||
"zagros-system-emulated-network/runtime-benchmarks",
|
||||
]
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// 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.
|
||||
|
||||
#[cfg(test)]
|
||||
mod imports {
|
||||
// Bizinikiwi
|
||||
pub(crate) use pezframe_support::assert_ok;
|
||||
|
||||
// Pezkuwi
|
||||
pub(crate) use xcm::{latest::ZAGROS_GENESIS_HASH, prelude::*};
|
||||
|
||||
// Pezcumulus
|
||||
pub(crate) use emulated_integration_tests_common::xcm_emulator::{
|
||||
assert_expected_events, bx, Chain, TestExt, Teyrchain as Para,
|
||||
};
|
||||
pub(crate) use zagros_system_emulated_network::{
|
||||
self,
|
||||
asset_hub_zagros_emulated_chain::AssetHubZagrosParaPallet as AssetHubZagrosPallet,
|
||||
bridge_hub_zagros_emulated_chain::BridgeHubZagrosParaPallet as BridgeHubZagrosPallet,
|
||||
collectives_zagros_emulated_chain::CollectivesZagrosParaPallet as CollectivesZagrosPallet,
|
||||
coretime_zagros_emulated_chain::CoretimeZagrosParaPallet as CoretimeZagrosPallet,
|
||||
penpal_emulated_chain::{PenpalAssetOwner, PenpalBParaPallet as PenpalBPallet},
|
||||
people_zagros_emulated_chain::{
|
||||
people_zagros_runtime::{
|
||||
self, xcm_config::XcmConfig as PeopleZagrosXcmConfig,
|
||||
ExistentialDeposit as PeopleZagrosExistentialDeposit,
|
||||
},
|
||||
PeopleZagrosParaPallet as PeopleZagrosPallet,
|
||||
},
|
||||
zagros_emulated_chain::{genesis::ED as ZAGROS_ED, ZagrosRelayPallet as ZagrosPallet},
|
||||
AssetHubZagrosPara as AssetHubZagros, AssetHubZagrosParaReceiver as AssetHubZagrosReceiver,
|
||||
BridgeHubZagrosPara as BridgeHubZagros, CollectivesZagrosPara as CollectivesZagros,
|
||||
CoretimeZagrosPara as CoretimeZagros, PenpalBPara as PenpalB,
|
||||
PeopleZagrosPara as PeopleZagros, PeopleZagrosParaReceiver as PeopleZagrosReceiver,
|
||||
PeopleZagrosParaSender as PeopleZagrosSender, ZagrosRelay as Zagros,
|
||||
ZagrosRelayReceiver as ZagrosReceiver, ZagrosRelaySender as ZagrosSender,
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
// 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.
|
||||
|
||||
//! Tests related to XCM aliasing.
|
||||
|
||||
use crate::imports::*;
|
||||
use emulated_integration_tests_common::{macros::AccountId, test_cross_chain_alias};
|
||||
use pezframe_support::traits::ContainsPair;
|
||||
use xcm::latest::Junctions::*;
|
||||
|
||||
const ALLOWED: bool = true;
|
||||
const DENIED: bool = false;
|
||||
|
||||
const TELEPORT_FEES: bool = true;
|
||||
const RESERVE_TRANSFER_FEES: bool = false;
|
||||
|
||||
#[test]
|
||||
fn account_on_sibling_syschain_aliases_into_same_local_account() {
|
||||
// origin and target are the same account on different chains
|
||||
let origin: AccountId = [1; 32].into();
|
||||
let target = origin.clone();
|
||||
let fees = ZAGROS_ED * 10;
|
||||
|
||||
PenpalB::mint_foreign_asset(
|
||||
<PenpalB as Chain>::RuntimeOrigin::signed(PenpalAssetOwner::get()),
|
||||
Location::parent(),
|
||||
origin.clone(),
|
||||
fees * 10,
|
||||
);
|
||||
|
||||
// Aliasing same account on different chains
|
||||
test_cross_chain_alias!(
|
||||
vec![
|
||||
// between AH and People: allowed
|
||||
(AssetHubZagros, PeopleZagros, TELEPORT_FEES, ALLOWED),
|
||||
// between BH and People: allowed
|
||||
(BridgeHubZagros, PeopleZagros, TELEPORT_FEES, ALLOWED),
|
||||
// between Collectives and People: allowed
|
||||
(CollectivesZagros, PeopleZagros, TELEPORT_FEES, ALLOWED),
|
||||
// between Coretime and People: allowed
|
||||
(CoretimeZagros, PeopleZagros, TELEPORT_FEES, ALLOWED),
|
||||
// between Penpal and People: denied
|
||||
(PenpalB, PeopleZagros, RESERVE_TRANSFER_FEES, DENIED)
|
||||
],
|
||||
origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn account_on_sibling_syschain_cannot_alias_into_different_local_account() {
|
||||
// origin and target are different accounts on different chains
|
||||
let origin: AccountId = [1; 32].into();
|
||||
let target: AccountId = [2; 32].into();
|
||||
let fees = ZAGROS_ED * 10;
|
||||
|
||||
PenpalB::mint_foreign_asset(
|
||||
<PenpalB as Chain>::RuntimeOrigin::signed(PenpalAssetOwner::get()),
|
||||
Location::parent(),
|
||||
origin.clone(),
|
||||
fees * 10,
|
||||
);
|
||||
|
||||
// Aliasing different account on different chains
|
||||
test_cross_chain_alias!(
|
||||
vec![
|
||||
// between AH and People: denied
|
||||
(AssetHubZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between BH and People: denied
|
||||
(BridgeHubZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between Collectives and People: denied
|
||||
(CollectivesZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between Coretime and People: denied
|
||||
(CoretimeZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between Penpal and People: denied
|
||||
(PenpalB, PeopleZagros, RESERVE_TRANSFER_FEES, DENIED)
|
||||
],
|
||||
origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aliasing_child_locations() {
|
||||
use PeopleZagrosXcmConfig as XcmConfig;
|
||||
PeopleZagros::execute_with(|| {
|
||||
// Allows aliasing descendant of origin.
|
||||
let origin = Location::new(1, X1([PalletInstance(8)].into()));
|
||||
let target = Location::new(1, X2([PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(8)].into()));
|
||||
let target = Location::new(
|
||||
1,
|
||||
X2([Teyrchain(8), AccountId32 { network: None, id: [1u8; 32] }].into()),
|
||||
);
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(8)].into()));
|
||||
let target =
|
||||
Location::new(1, X3([Teyrchain(8), PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
|
||||
// Does not allow if not descendant.
|
||||
let origin = Location::new(1, X1([PalletInstance(8)].into()));
|
||||
let target = Location::new(0, X2([PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(8)].into()));
|
||||
let target = Location::new(
|
||||
0,
|
||||
X2([Teyrchain(8), AccountId32 { network: None, id: [1u8; 32] }].into()),
|
||||
);
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(8)].into()));
|
||||
let target = Location::new(0, X1([AccountId32 { network: None, id: [1u8; 32] }].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([AccountId32 { network: None, id: [1u8; 32] }].into()));
|
||||
let target = Location::new(0, X1([AccountId32 { network: None, id: [1u8; 32] }].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn asset_hub_root_aliases_anything() {
|
||||
use PeopleZagrosXcmConfig as XcmConfig;
|
||||
PeopleZagros::execute_with(|| {
|
||||
// Allows AH root to alias anything.
|
||||
let origin = Location::new(1, X1([Teyrchain(1000)].into()));
|
||||
|
||||
let target = Location::new(1, X1([Teyrchain(2000)].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(1, X1([AccountId32 { network: None, id: [1u8; 32] }].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(
|
||||
1,
|
||||
X2([Teyrchain(8), AccountId32 { network: None, id: [1u8; 32] }].into()),
|
||||
);
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target =
|
||||
Location::new(1, X3([Teyrchain(42), PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(2, X1([GlobalConsensus(Ethereum { chain_id: 1 })].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(2, X2([GlobalConsensus(Pezkuwi), Teyrchain(1000)].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(0, X2([PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
|
||||
// Other AH locations cannot alias anything.
|
||||
let origin = Location::new(1, X2([Teyrchain(1000), GeneralIndex(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X2([Teyrchain(1000), PalletInstance(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(
|
||||
1,
|
||||
X2([Teyrchain(1000), AccountId32 { network: None, id: [1u8; 32] }].into()),
|
||||
);
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
|
||||
// Other root locations cannot alias anything.
|
||||
let origin = Location::new(1, Here);
|
||||
let target = Location::new(2, X1([GlobalConsensus(Ethereum { chain_id: 1 })].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(2, X2([GlobalConsensus(Pezkuwi), Teyrchain(1000)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let target = Location::new(0, X2([PalletInstance(8), GeneralIndex(9)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
|
||||
let origin = Location::new(0, Here);
|
||||
let target = Location::new(1, X1([Teyrchain(2000)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(1001)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
let origin = Location::new(1, X1([Teyrchain(1002)].into()));
|
||||
assert!(!<XcmConfig as xcm_executor::Config>::Aliasers::contains(&origin, &target));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authorized_cross_chain_aliases() {
|
||||
// origin and target are different accounts on different chains
|
||||
let origin: AccountId = [100; 32].into();
|
||||
let bad_origin: AccountId = [150; 32].into();
|
||||
let target: AccountId = [200; 32].into();
|
||||
let fees = ZAGROS_ED * 10;
|
||||
|
||||
let pal_admin = <PenpalB as Chain>::RuntimeOrigin::signed(PenpalAssetOwner::get());
|
||||
PenpalB::mint_foreign_asset(pal_admin.clone(), Location::parent(), origin.clone(), fees * 10);
|
||||
PenpalB::mint_foreign_asset(pal_admin, Location::parent(), bad_origin.clone(), fees * 10);
|
||||
PeopleZagros::fund_accounts(vec![(target.clone(), fees * 10)]);
|
||||
|
||||
// let's authorize `origin` on Penpal to alias `target` on People
|
||||
PeopleZagros::execute_with(|| {
|
||||
let penpal_origin = Location::new(
|
||||
1,
|
||||
X2([
|
||||
Teyrchain(PenpalB::para_id().into()),
|
||||
AccountId32 {
|
||||
network: Some(ByGenesis(ZAGROS_GENESIS_HASH)),
|
||||
id: origin.clone().into(),
|
||||
},
|
||||
]
|
||||
.into()),
|
||||
);
|
||||
// `target` adds `penpal_origin` as authorized alias
|
||||
assert_ok!(<PeopleZagros as PeopleZagrosPallet>::PezkuwiXcm::add_authorized_alias(
|
||||
<PeopleZagros as Chain>::RuntimeOrigin::signed(target.clone()),
|
||||
Box::new(penpal_origin.into()),
|
||||
None
|
||||
));
|
||||
});
|
||||
// Verify that unauthorized `bad_origin` cannot alias into `target`, from any chain.
|
||||
test_cross_chain_alias!(
|
||||
vec![
|
||||
// between AH and People: denied
|
||||
(AssetHubZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between BH and People: denied
|
||||
(BridgeHubZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between Collectives and People: denied
|
||||
(CollectivesZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between Penpal and People: denied
|
||||
(PenpalB, PeopleZagros, RESERVE_TRANSFER_FEES, DENIED)
|
||||
],
|
||||
bad_origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
// Verify that only authorized `penpal::origin` can alias into `target`, while `origin` on other
|
||||
// chains cannot.
|
||||
test_cross_chain_alias!(
|
||||
vec![
|
||||
// between AH and People: denied
|
||||
(AssetHubZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between BH and People: denied
|
||||
(BridgeHubZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between Collectives and People: denied
|
||||
(CollectivesZagros, PeopleZagros, TELEPORT_FEES, DENIED),
|
||||
// between Penpal and People: allowed
|
||||
(PenpalB, PeopleZagros, RESERVE_TRANSFER_FEES, ALLOWED)
|
||||
],
|
||||
origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
// remove authorization for `origin` on Penpal to alias `target` on People
|
||||
PeopleZagros::execute_with(|| {
|
||||
// `target` removes all authorized aliases
|
||||
assert_ok!(
|
||||
<PeopleZagros as PeopleZagrosPallet>::PezkuwiXcm::remove_all_authorized_aliases(
|
||||
<PeopleZagros as Chain>::RuntimeOrigin::signed(target.clone())
|
||||
)
|
||||
);
|
||||
});
|
||||
// Verify `penpal::origin` can no longer alias into `target` on People.
|
||||
test_cross_chain_alias!(
|
||||
vec![(PenpalB, PeopleZagros, RESERVE_TRANSFER_FEES, DENIED)],
|
||||
origin,
|
||||
target,
|
||||
fees
|
||||
);
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
//! Tests related to claiming assets trapped during XCM execution.
|
||||
|
||||
use crate::imports::*;
|
||||
|
||||
use emulated_integration_tests_common::test_chain_can_claim_assets;
|
||||
|
||||
#[test]
|
||||
fn assets_can_be_claimed() {
|
||||
let amount = PeopleZagrosExistentialDeposit::get();
|
||||
let assets: Assets = (Parent, amount).into();
|
||||
|
||||
test_chain_can_claim_assets!(
|
||||
PeopleZagros,
|
||||
RuntimeCall,
|
||||
NetworkId::ByGenesis(ZAGROS_GENESIS_HASH),
|
||||
assets,
|
||||
amount
|
||||
);
|
||||
}
|
||||
+547
@@ -0,0 +1,547 @@
|
||||
// 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::imports::*;
|
||||
|
||||
use codec::Encode;
|
||||
use pezframe_support::pezsp_runtime::traits::Dispatchable;
|
||||
use people_zagros_runtime::people::IdentityInfo;
|
||||
use teyrchains_common::AccountId;
|
||||
use zagros_runtime::{
|
||||
governance::pezpallet_custom_origins::Origin::GeneralAdmin as GeneralAdminOrigin, Dmp,
|
||||
};
|
||||
use zagros_system_emulated_network::people_zagros_emulated_chain::people_zagros_runtime;
|
||||
|
||||
use pezpallet_identity::Data;
|
||||
|
||||
use emulated_integration_tests_common::accounts::{ALICE, BOB};
|
||||
|
||||
#[test]
|
||||
fn relay_commands_add_registrar() {
|
||||
let (origin_kind, origin) = (OriginKind::Superuser, <Zagros as Chain>::RuntimeOrigin::root());
|
||||
|
||||
let registrar: AccountId = [1; 32].into();
|
||||
Zagros::execute_with(|| {
|
||||
type Runtime = <Zagros as Chain>::Runtime;
|
||||
type RuntimeCall = <Zagros as Chain>::RuntimeCall;
|
||||
type RuntimeEvent = <Zagros as Chain>::RuntimeEvent;
|
||||
type PeopleCall = <PeopleZagros as Chain>::RuntimeCall;
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
|
||||
Dmp::make_teyrchain_reachable(1004);
|
||||
|
||||
let add_registrar_call =
|
||||
PeopleCall::Identity(pezpallet_identity::Call::<PeopleRuntime>::add_registrar {
|
||||
account: registrar.into(),
|
||||
});
|
||||
|
||||
let xcm_message = RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::send {
|
||||
dest: bx!(VersionedLocation::from(Location::new(0, [Teyrchain(1004)]))),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind,
|
||||
call: add_registrar_call.encode().into(),
|
||||
fallback_max_weight: None
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
assert_ok!(xcm_message.dispatch(origin));
|
||||
|
||||
assert_expected_events!(
|
||||
Zagros,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
PeopleZagros::execute_with(|| {
|
||||
type RuntimeEvent = <PeopleZagros as Chain>::RuntimeEvent;
|
||||
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
RuntimeEvent::Identity(pezpallet_identity::Event::RegistrarAdded { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: true, .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relay_commands_add_registrar_wrong_origin() {
|
||||
let people_zagros_alice = PeopleZagros::account_id_of(ALICE);
|
||||
|
||||
let origins = vec![
|
||||
(
|
||||
OriginKind::SovereignAccount,
|
||||
<Zagros as Chain>::RuntimeOrigin::signed(people_zagros_alice),
|
||||
),
|
||||
(OriginKind::Xcm, GeneralAdminOrigin.into()),
|
||||
];
|
||||
|
||||
let mut signed_origin = true;
|
||||
|
||||
for (origin_kind, origin) in origins {
|
||||
let registrar: AccountId = [1; 32].into();
|
||||
Zagros::execute_with(|| {
|
||||
type Runtime = <Zagros as Chain>::Runtime;
|
||||
type RuntimeCall = <Zagros as Chain>::RuntimeCall;
|
||||
type RuntimeEvent = <Zagros as Chain>::RuntimeEvent;
|
||||
type PeopleCall = <PeopleZagros as Chain>::RuntimeCall;
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
|
||||
Dmp::make_teyrchain_reachable(1004);
|
||||
|
||||
let add_registrar_call =
|
||||
PeopleCall::Identity(pezpallet_identity::Call::<PeopleRuntime>::add_registrar {
|
||||
account: registrar.into(),
|
||||
});
|
||||
|
||||
let xcm_message = RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::send {
|
||||
dest: bx!(VersionedLocation::from(Location::new(0, [Teyrchain(1004)]))),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind,
|
||||
call: add_registrar_call.encode().into(),
|
||||
fallback_max_weight: None
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
assert_ok!(xcm_message.dispatch(origin));
|
||||
assert_expected_events!(
|
||||
Zagros,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
PeopleZagros::execute_with(|| {
|
||||
type RuntimeEvent = <PeopleZagros as Chain>::RuntimeEvent;
|
||||
|
||||
if signed_origin {
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: false, .. }) => {},
|
||||
]
|
||||
);
|
||||
} else {
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: true, .. }) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
signed_origin = false;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relay_commands_kill_identity() {
|
||||
// To kill an identity, first one must be set
|
||||
PeopleZagros::execute_with(|| {
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
type PeopleRuntimeEvent = <PeopleZagros as Chain>::RuntimeEvent;
|
||||
|
||||
let people_zagros_alice =
|
||||
<PeopleZagros as Chain>::RuntimeOrigin::signed(PeopleZagros::account_id_of(ALICE));
|
||||
|
||||
let identity_info = IdentityInfo {
|
||||
email: Data::Raw(b"test@test.io".to_vec().try_into().unwrap()),
|
||||
..Default::default()
|
||||
};
|
||||
let identity: Box<<PeopleRuntime as pezpallet_identity::Config>::IdentityInformation> =
|
||||
Box::new(identity_info);
|
||||
|
||||
assert_ok!(<PeopleZagros as PeopleZagrosPallet>::Identity::set_identity(
|
||||
people_zagros_alice,
|
||||
identity
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
PeopleRuntimeEvent::Identity(pezpallet_identity::Event::IdentitySet { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
let (origin_kind, origin) = (OriginKind::Superuser, <Zagros as Chain>::RuntimeOrigin::root());
|
||||
|
||||
Zagros::execute_with(|| {
|
||||
type Runtime = <Zagros as Chain>::Runtime;
|
||||
type RuntimeCall = <Zagros as Chain>::RuntimeCall;
|
||||
type PeopleCall = <PeopleZagros as Chain>::RuntimeCall;
|
||||
type RuntimeEvent = <Zagros as Chain>::RuntimeEvent;
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
|
||||
Dmp::make_teyrchain_reachable(1004);
|
||||
|
||||
let kill_identity_call =
|
||||
PeopleCall::Identity(pezpallet_identity::Call::<PeopleRuntime>::kill_identity {
|
||||
target: people_zagros_runtime::MultiAddress::Id(PeopleZagros::account_id_of(ALICE)),
|
||||
});
|
||||
|
||||
let xcm_message = RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::send {
|
||||
dest: bx!(VersionedLocation::from(Location::new(0, [Teyrchain(1004)]))),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind,
|
||||
call: kill_identity_call.encode().into(),
|
||||
fallback_max_weight: None
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
assert_ok!(xcm_message.dispatch(origin));
|
||||
|
||||
assert_expected_events!(
|
||||
Zagros,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
PeopleZagros::execute_with(|| {
|
||||
type RuntimeEvent = <PeopleZagros as Chain>::RuntimeEvent;
|
||||
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
RuntimeEvent::Identity(pezpallet_identity::Event::IdentityKilled { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: true, .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relay_commands_kill_identity_wrong_origin() {
|
||||
let people_zagros_alice = PeopleZagros::account_id_of(BOB);
|
||||
|
||||
let origins = vec![
|
||||
(
|
||||
OriginKind::SovereignAccount,
|
||||
<Zagros as Chain>::RuntimeOrigin::signed(people_zagros_alice),
|
||||
),
|
||||
(OriginKind::Xcm, GeneralAdminOrigin.into()),
|
||||
];
|
||||
|
||||
for (origin_kind, origin) in origins {
|
||||
Zagros::execute_with(|| {
|
||||
type Runtime = <Zagros as Chain>::Runtime;
|
||||
type RuntimeCall = <Zagros as Chain>::RuntimeCall;
|
||||
type PeopleCall = <PeopleZagros as Chain>::RuntimeCall;
|
||||
type RuntimeEvent = <Zagros as Chain>::RuntimeEvent;
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
|
||||
Dmp::make_teyrchain_reachable(1004);
|
||||
|
||||
let kill_identity_call =
|
||||
PeopleCall::Identity(pezpallet_identity::Call::<PeopleRuntime>::kill_identity {
|
||||
target: people_zagros_runtime::MultiAddress::Id(PeopleZagros::account_id_of(
|
||||
ALICE,
|
||||
)),
|
||||
});
|
||||
|
||||
let xcm_message = RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::send {
|
||||
dest: bx!(VersionedLocation::from(Location::new(0, [Teyrchain(1004)]))),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind,
|
||||
call: kill_identity_call.encode().into(),
|
||||
fallback_max_weight: None
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
assert_ok!(xcm_message.dispatch(origin));
|
||||
assert_expected_events!(
|
||||
Zagros,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
PeopleZagros::execute_with(|| {
|
||||
assert_expected_events!(PeopleZagros, vec![]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relay_commands_add_remove_username_authority() {
|
||||
let people_zagros_alice = PeopleZagros::account_id_of(ALICE);
|
||||
let people_zagros_bob = PeopleZagros::account_id_of(BOB);
|
||||
|
||||
let (origin_kind, origin, usr) =
|
||||
(OriginKind::Superuser, <Zagros as Chain>::RuntimeOrigin::root(), "rootusername");
|
||||
|
||||
// First, add a username authority.
|
||||
Zagros::execute_with(|| {
|
||||
type Runtime = <Zagros as Chain>::Runtime;
|
||||
type RuntimeCall = <Zagros as Chain>::RuntimeCall;
|
||||
type RuntimeEvent = <Zagros as Chain>::RuntimeEvent;
|
||||
type PeopleCall = <PeopleZagros as Chain>::RuntimeCall;
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
|
||||
Dmp::make_teyrchain_reachable(1004);
|
||||
|
||||
let add_username_authority =
|
||||
PeopleCall::Identity(pezpallet_identity::Call::<PeopleRuntime>::add_username_authority {
|
||||
authority: people_zagros_runtime::MultiAddress::Id(people_zagros_alice.clone()),
|
||||
suffix: b"suffix1".into(),
|
||||
allocation: 10,
|
||||
});
|
||||
|
||||
let add_authority_xcm_msg = RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::send {
|
||||
dest: bx!(VersionedLocation::from(Location::new(0, [Teyrchain(1004)]))),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind,
|
||||
call: add_username_authority.encode().into(),
|
||||
fallback_max_weight: None
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
assert_ok!(add_authority_xcm_msg.dispatch(origin.clone()));
|
||||
|
||||
assert_expected_events!(
|
||||
Zagros,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Check events system-teyrchain-side
|
||||
PeopleZagros::execute_with(|| {
|
||||
type RuntimeEvent = <PeopleZagros as Chain>::RuntimeEvent;
|
||||
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
RuntimeEvent::Identity(pezpallet_identity::Event::AuthorityAdded { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: true, .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Now, use the previously added username authority to concede a username to an account.
|
||||
PeopleZagros::execute_with(|| {
|
||||
type PeopleRuntimeEvent = <PeopleZagros as Chain>::RuntimeEvent;
|
||||
let full_username = [usr.to_owned(), ".suffix1".to_owned()].concat().into_bytes();
|
||||
|
||||
assert_ok!(<PeopleZagros as PeopleZagrosPallet>::Identity::set_username_for(
|
||||
<PeopleZagros as Chain>::RuntimeOrigin::signed(people_zagros_alice.clone()),
|
||||
people_zagros_runtime::MultiAddress::Id(people_zagros_bob.clone()),
|
||||
full_username,
|
||||
None,
|
||||
true
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
PeopleRuntimeEvent::Identity(pezpallet_identity::Event::UsernameQueued { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Accept the given username
|
||||
PeopleZagros::execute_with(|| {
|
||||
type PeopleRuntimeEvent = <PeopleZagros as Chain>::RuntimeEvent;
|
||||
let full_username = [usr.to_owned(), ".suffix1".to_owned()].concat().into_bytes();
|
||||
|
||||
assert_ok!(<PeopleZagros as PeopleZagrosPallet>::Identity::accept_username(
|
||||
<PeopleZagros as Chain>::RuntimeOrigin::signed(people_zagros_bob.clone()),
|
||||
full_username.try_into().unwrap(),
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
PeopleRuntimeEvent::Identity(pezpallet_identity::Event::UsernameSet { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Now, remove the username authority with another privileged XCM call.
|
||||
Zagros::execute_with(|| {
|
||||
type Runtime = <Zagros as Chain>::Runtime;
|
||||
type RuntimeCall = <Zagros as Chain>::RuntimeCall;
|
||||
type RuntimeEvent = <Zagros as Chain>::RuntimeEvent;
|
||||
type PeopleCall = <PeopleZagros as Chain>::RuntimeCall;
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
|
||||
Dmp::make_teyrchain_reachable(1004);
|
||||
|
||||
let remove_username_authority = PeopleCall::Identity(pezpallet_identity::Call::<
|
||||
PeopleRuntime,
|
||||
>::remove_username_authority {
|
||||
authority: people_zagros_runtime::MultiAddress::Id(people_zagros_alice.clone()),
|
||||
suffix: b"suffix1".into(),
|
||||
});
|
||||
|
||||
let remove_authority_xcm_msg = RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::send {
|
||||
dest: bx!(VersionedLocation::from(Location::new(0, [Teyrchain(1004)]))),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind,
|
||||
call: remove_username_authority.encode().into(),
|
||||
fallback_max_weight: None
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
assert_ok!(remove_authority_xcm_msg.dispatch(origin));
|
||||
|
||||
assert_expected_events!(
|
||||
Zagros,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Final event check.
|
||||
PeopleZagros::execute_with(|| {
|
||||
type RuntimeEvent = <PeopleZagros as Chain>::RuntimeEvent;
|
||||
|
||||
assert_expected_events!(
|
||||
PeopleZagros,
|
||||
vec![
|
||||
RuntimeEvent::Identity(pezpallet_identity::Event::AuthorityRemoved { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pezpallet_message_queue::Event::Processed { success: true, .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relay_commands_add_remove_username_authority_wrong_origin() {
|
||||
let people_zagros_alice = PeopleZagros::account_id_of(ALICE);
|
||||
|
||||
let origins = vec![
|
||||
(
|
||||
OriginKind::SovereignAccount,
|
||||
<Zagros as Chain>::RuntimeOrigin::signed(people_zagros_alice.clone()),
|
||||
),
|
||||
(OriginKind::Xcm, GeneralAdminOrigin.into()),
|
||||
];
|
||||
|
||||
for (origin_kind, origin) in origins {
|
||||
Zagros::execute_with(|| {
|
||||
type Runtime = <Zagros as Chain>::Runtime;
|
||||
type RuntimeCall = <Zagros as Chain>::RuntimeCall;
|
||||
type RuntimeEvent = <Zagros as Chain>::RuntimeEvent;
|
||||
type PeopleCall = <PeopleZagros as Chain>::RuntimeCall;
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
|
||||
Dmp::make_teyrchain_reachable(1004);
|
||||
|
||||
let add_username_authority = PeopleCall::Identity(pezpallet_identity::Call::<
|
||||
PeopleRuntime,
|
||||
>::add_username_authority {
|
||||
authority: people_zagros_runtime::MultiAddress::Id(people_zagros_alice.clone()),
|
||||
suffix: b"suffix1".into(),
|
||||
allocation: 10,
|
||||
});
|
||||
|
||||
let add_authority_xcm_msg = RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::send {
|
||||
dest: bx!(VersionedLocation::from(Location::new(0, [Teyrchain(1004)]))),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind,
|
||||
call: add_username_authority.encode().into(),
|
||||
fallback_max_weight: None
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
assert_ok!(add_authority_xcm_msg.dispatch(origin.clone()));
|
||||
assert_expected_events!(
|
||||
Zagros,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Check events system-teyrchain-side
|
||||
PeopleZagros::execute_with(|| {
|
||||
assert_expected_events!(PeopleZagros, vec![]);
|
||||
});
|
||||
|
||||
Zagros::execute_with(|| {
|
||||
type Runtime = <Zagros as Chain>::Runtime;
|
||||
type RuntimeCall = <Zagros as Chain>::RuntimeCall;
|
||||
type RuntimeEvent = <Zagros as Chain>::RuntimeEvent;
|
||||
type PeopleCall = <PeopleZagros as Chain>::RuntimeCall;
|
||||
type PeopleRuntime = <PeopleZagros as Chain>::Runtime;
|
||||
|
||||
let remove_username_authority = PeopleCall::Identity(pezpallet_identity::Call::<
|
||||
PeopleRuntime,
|
||||
>::remove_username_authority {
|
||||
authority: people_zagros_runtime::MultiAddress::Id(people_zagros_alice.clone()),
|
||||
suffix: b"suffix1".into(),
|
||||
});
|
||||
|
||||
Dmp::make_teyrchain_reachable(1004);
|
||||
|
||||
let remove_authority_xcm_msg =
|
||||
RuntimeCall::XcmPallet(pezpallet_xcm::Call::<Runtime>::send {
|
||||
dest: bx!(VersionedLocation::from(Location::new(0, [Teyrchain(1004)]))),
|
||||
message: bx!(VersionedXcm::from(Xcm(vec![
|
||||
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
|
||||
Transact {
|
||||
origin_kind: OriginKind::SovereignAccount,
|
||||
call: remove_username_authority.encode().into(),
|
||||
fallback_max_weight: None,
|
||||
}
|
||||
]))),
|
||||
});
|
||||
|
||||
assert_ok!(remove_authority_xcm_msg.dispatch(origin));
|
||||
assert_expected_events!(
|
||||
Zagros,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
PeopleZagros::execute_with(|| {
|
||||
assert_expected_events!(PeopleZagros, vec![]);
|
||||
});
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
// 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.
|
||||
|
||||
//! Tests related to cross-chain identity operations.
|
||||
|
||||
use crate::imports::*;
|
||||
use codec::Encode;
|
||||
use emulated_integration_tests_common::accounts::ALICE;
|
||||
use pezframe_support::BoundedVec;
|
||||
use pezpallet_identity::Data;
|
||||
use people_zagros_runtime::people::{IdentityField, IdentityInfo};
|
||||
use xcm::latest::AssetTransferFilter;
|
||||
|
||||
#[test]
|
||||
fn set_identity_cross_chain() {
|
||||
type Identity = <PeopleZagros as PeopleZagrosPallet>::Identity;
|
||||
|
||||
let asset_hub_zagros_alice = AssetHubZagros::account_id_of(ALICE);
|
||||
let people_zagros_alice = PeopleZagros::account_id_of(ALICE);
|
||||
AssetHubZagros::fund_accounts(vec![(asset_hub_zagros_alice.clone(), ZAGROS_ED * 10000)]);
|
||||
PeopleZagros::fund_accounts(vec![(people_zagros_alice.clone(), ZAGROS_ED * 10000)]);
|
||||
|
||||
PeopleZagros::execute_with(|| {
|
||||
// No identity for Alice
|
||||
assert!(!Identity::has_identity(&people_zagros_alice, IdentityField::Email as u64));
|
||||
});
|
||||
|
||||
let destination = AssetHubZagros::sibling_location_of(PeopleZagros::para_id());
|
||||
let total_fees: Asset = (Location::parent(), ZAGROS_ED * 1000).into();
|
||||
let fees: Asset = (Location::parent(), ZAGROS_ED * 500).into();
|
||||
AssetHubZagros::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubZagros as Chain>::RuntimeEvent;
|
||||
|
||||
let identity_info = IdentityInfo {
|
||||
email: Data::Raw(b"test@test.io".to_vec().try_into().unwrap()),
|
||||
..Default::default()
|
||||
};
|
||||
// Set Alice identity on People from Alice on AH
|
||||
let set_identity_call =
|
||||
<PeopleZagros as Chain>::RuntimeCall::Identity(pezpallet_identity::Call::<
|
||||
<PeopleZagros as Chain>::Runtime,
|
||||
>::set_identity {
|
||||
info: bx!(identity_info),
|
||||
});
|
||||
let xcm_message = Xcm::<()>(vec![
|
||||
WithdrawAsset(total_fees.into()),
|
||||
PayFees { asset: fees.clone() },
|
||||
InitiateTransfer {
|
||||
destination,
|
||||
remote_fees: Some(AssetTransferFilter::Teleport(fees.clone().into())),
|
||||
preserve_origin: true,
|
||||
assets: BoundedVec::new(),
|
||||
remote_xcm: Xcm(vec![
|
||||
// try to alias into `Alice` account local to People chain
|
||||
AliasOrigin(people_zagros_alice.clone().into()),
|
||||
// set identity for the local Alice account
|
||||
Transact {
|
||||
origin_kind: OriginKind::SovereignAccount,
|
||||
call: set_identity_call.encode().into(),
|
||||
fallback_max_weight: None,
|
||||
},
|
||||
RefundSurplus,
|
||||
DepositAsset {
|
||||
assets: Wild(AllCounted(1)),
|
||||
beneficiary: people_zagros_alice.clone().into(),
|
||||
},
|
||||
]),
|
||||
},
|
||||
ExpectTransactStatus(MaybeErrorCode::Success),
|
||||
RefundSurplus,
|
||||
DepositAsset {
|
||||
assets: Wild(AllCounted(1)),
|
||||
beneficiary: asset_hub_zagros_alice.clone().into(),
|
||||
},
|
||||
]);
|
||||
|
||||
let signed_origin =
|
||||
<AssetHubZagros as Chain>::RuntimeOrigin::signed(asset_hub_zagros_alice);
|
||||
assert_ok!(<AssetHubZagros as AssetHubZagrosPallet>::PezkuwiXcm::execute(
|
||||
signed_origin,
|
||||
bx!(xcm::VersionedXcm::from(xcm_message.into())),
|
||||
Weight::MAX
|
||||
));
|
||||
assert_expected_events!(
|
||||
AssetHubZagros,
|
||||
vec![
|
||||
RuntimeEvent::PezkuwiXcm(pezpallet_xcm::Event::Sent { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
PeopleZagros::execute_with(|| {
|
||||
// Verify Alice on People now has identity
|
||||
assert!(Identity::has_identity(&people_zagros_alice, IdentityField::Email as u64));
|
||||
});
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// 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.
|
||||
|
||||
mod aliases;
|
||||
mod claim_assets;
|
||||
mod governance;
|
||||
mod identity;
|
||||
mod teleport;
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
// 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::imports::*;
|
||||
use emulated_integration_tests_common::{
|
||||
test_relay_is_trusted_teleporter, test_teyrchain_is_trusted_teleporter,
|
||||
test_teyrchain_is_trusted_teleporter_for_relay,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn teleport_via_limited_teleport_assets_from_and_to_relay() {
|
||||
let amount = ZAGROS_ED * 100;
|
||||
|
||||
test_relay_is_trusted_teleporter!(Zagros, vec![PeopleZagros], amount, limited_teleport_assets);
|
||||
|
||||
test_teyrchain_is_trusted_teleporter_for_relay!(
|
||||
PeopleZagros,
|
||||
Zagros,
|
||||
amount,
|
||||
limited_teleport_assets
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_transfer_assets_from_and_to_relay() {
|
||||
let amount = ZAGROS_ED * 100;
|
||||
|
||||
test_relay_is_trusted_teleporter!(Zagros, vec![PeopleZagros], amount, transfer_assets);
|
||||
|
||||
test_teyrchain_is_trusted_teleporter_for_relay!(PeopleZagros, Zagros, amount, transfer_assets);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_limited_teleport_assets_to_other_system_teyrchains_works() {
|
||||
let amount = ZAGROS_ED * 100;
|
||||
let native_asset: Assets = (Parent, amount).into();
|
||||
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
test_teyrchain_is_trusted_teleporter!(
|
||||
PeopleZagros, // Origin
|
||||
vec![AssetHubZagros], // Destinations
|
||||
(native_asset, amount),
|
||||
fee_asset_id,
|
||||
limited_teleport_assets
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleport_via_transfer_assets_to_other_system_teyrchains_works() {
|
||||
let amount = ZAGROS_ED * 100;
|
||||
let native_asset: Assets = (Parent, amount).into();
|
||||
|
||||
let fee_asset_id: AssetId = Parent.into();
|
||||
test_teyrchain_is_trusted_teleporter!(
|
||||
PeopleZagros, // Origin
|
||||
vec![AssetHubZagros], // Destinations
|
||||
(native_asset, amount),
|
||||
fee_asset_id,
|
||||
transfer_assets
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user