Skip to content

Commit

Permalink
Collectives tests: Teleports and Whitelist Call (#251)
Browse files Browse the repository at this point in the history
Introduce teleport and whitelist call tests for Polkadot Collectives.

Based on #233

- [x] Does not require a CHANGELOG entry

---------

Co-authored-by: joe petrowski <[email protected]>
Co-authored-by: Branislav Kontur <[email protected]>
  • Loading branch information
3 people authored May 17, 2024
1 parent 67af9b9 commit c2886b9
Show file tree
Hide file tree
Showing 16 changed files with 348 additions and 15 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

180 changes: 179 additions & 1 deletion integration-tests/emulated/helpers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub use xcm_emulator::Chain;
/// TODO: when bumping to polkadot-sdk v1.8.0,
/// remove this crate altogether and get the macros from `emulated-integration-tests-common`.
#[macro_export]
macro_rules! test_parachain_is_trusted_teleporter {
macro_rules! test_sibling_is_trusted_teleporter {
( $sender_para:ty, $sender_xcm_config:ty, vec![$( $receiver_para:ty ),+], ($assets:expr, $amount:expr) ) => {
$crate::paste::paste! {
// init Origin variables
Expand Down Expand Up @@ -123,6 +123,184 @@ macro_rules! test_parachain_is_trusted_teleporter {
};
}

#[macro_export]
macro_rules! test_relay_is_trusted_teleporter {
( $sender_relay:ty, $sender_xcm_config:ty, vec![$( $receiver_para:ty ),+], ($assets:expr, $amount:expr) ) => {
$crate::paste::paste! {
// init Origin variables
let sender = [<$sender_relay Sender>]::get();
let mut relay_sender_balance_before =
<$sender_relay as $crate::Chain>::account_data_of(sender.clone()).free;
let origin = <$sender_relay as $crate::Chain>::RuntimeOrigin::signed(sender.clone());
let fee_asset_item = 0;
let weight_limit = $crate::WeightLimit::Unlimited;

$(
{
// init Destination variables
let receiver = [<$receiver_para Receiver>]::get();
let para_receiver_balance_before =
<$receiver_para as $crate::Chain>::account_data_of(receiver.clone()).free;
let para_destination =
<$sender_relay>::child_location_of(<$receiver_para>::para_id());
let beneficiary: Location =
$crate::AccountId32 { network: None, id: receiver.clone().into() }.into();

// Send XCM message from Relay
<$sender_relay>::execute_with(|| {
assert_ok!(<$sender_relay as [<$sender_relay Pallet>]>::XcmPallet::limited_teleport_assets(
origin.clone(),
bx!(para_destination.clone().into()),
bx!(beneficiary.clone().into()),
bx!($assets.clone().into()),
fee_asset_item,
weight_limit.clone(),
));

type RuntimeEvent = <$sender_relay as $crate::Chain>::RuntimeEvent;

assert_expected_events!(
$sender_relay,
vec![
RuntimeEvent::XcmPallet(
$crate::pallet_xcm::Event::Attempted { outcome: Outcome::Complete { .. } }
) => {},
RuntimeEvent::Balances(
$crate::pallet_balances::Event::Burned { who: sender, amount }
) => {},
RuntimeEvent::XcmPallet(
$crate::pallet_xcm::Event::Sent { .. }
) => {},
]
);
});

// Receive XCM message in Destination Parachain
<$receiver_para>::execute_with(|| {
type RuntimeEvent = <$receiver_para as $crate::Chain>::RuntimeEvent;

assert_expected_events!(
$receiver_para,
vec![
RuntimeEvent::Balances(
$crate::pallet_balances::Event::Minted { who: receiver, .. }
) => {},
RuntimeEvent::MessageQueue(
$crate::pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});

// Check if balances are updated accordingly in Origin and Parachain
let relay_sender_balance_after =
<$sender_relay as $crate::Chain>::account_data_of(sender.clone()).free;
let para_receiver_balance_after =
<$receiver_para as $crate::Chain>::account_data_of(receiver.clone()).free;
let delivery_fees = <$sender_relay>::execute_with(|| {
$crate::asset_test_utils::xcm_helpers::transfer_assets_delivery_fees::<
<$sender_xcm_config as xcm_executor::Config>::XcmSender,
>($assets.clone(), fee_asset_item, weight_limit.clone(), beneficiary, para_destination)
});

assert_eq!(relay_sender_balance_before - $amount - delivery_fees, relay_sender_balance_after);
assert!(para_receiver_balance_after > para_receiver_balance_before);

// Update sender balance
relay_sender_balance_before = <$sender_relay as $crate::Chain>::account_data_of(sender.clone()).free;
}
)+
}
};
}

#[macro_export]
macro_rules! test_parachain_is_trusted_teleporter {
( $sender_para:ty, $sender_xcm_config:ty, $receiver_relay:ty, $amount:expr ) => {
$crate::paste::paste! {
// init Origin variables
let sender = [<$sender_para Sender>]::get();
let mut para_sender_balance_before =
<$sender_para as $crate::Chain>::account_data_of(sender.clone()).free;
let origin = <$sender_para as $crate::Chain>::RuntimeOrigin::signed(sender.clone());
let assets: Assets = (Parent, $amount).into();
let fee_asset_item = 0;
let weight_limit = $crate::WeightLimit::Unlimited;

// init Destination variables
let receiver = [<$receiver_relay Receiver>]::get();
let relay_receiver_balance_before =
<$receiver_relay as $crate::Chain>::account_data_of(receiver.clone()).free;
let relay_destination: Location = Parent.into();
let beneficiary: Location =
$crate::AccountId32 { network: None, id: receiver.clone().into() }.into();

// Send XCM message from Parachain
<$sender_para>::execute_with(|| {
assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::limited_teleport_assets(
origin.clone(),
bx!(relay_destination.clone().into()),
bx!(beneficiary.clone().into()),
bx!(assets.clone().into()),
fee_asset_item,
weight_limit.clone(),
));

type RuntimeEvent = <$sender_para as $crate::Chain>::RuntimeEvent;

assert_expected_events!(
$sender_para,
vec![
RuntimeEvent::PolkadotXcm(
$crate::pallet_xcm::Event::Attempted { outcome: Outcome::Complete { .. } }
) => {},
RuntimeEvent::Balances(
$crate::pallet_balances::Event::Burned { who: sender, amount }
) => {},
RuntimeEvent::PolkadotXcm(
$crate::pallet_xcm::Event::Sent { .. }
) => {},
]
);
});

// Receive XCM message in Destination Parachain
<$receiver_relay>::execute_with(|| {
type RuntimeEvent = <$receiver_relay as $crate::Chain>::RuntimeEvent;

assert_expected_events!(
$receiver_relay,
vec![
RuntimeEvent::Balances(
$crate::pallet_balances::Event::Minted { who: receiver, .. }
) => {},
RuntimeEvent::MessageQueue(
$crate::pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});

// Check if balances are updated accordingly in Origin and Relay Chain
let para_sender_balance_after =
<$sender_para as $crate::Chain>::account_data_of(sender.clone()).free;
let relay_receiver_balance_after =
<$receiver_relay as $crate::Chain>::account_data_of(receiver.clone()).free;
let delivery_fees = <$sender_para>::execute_with(|| {
$crate::asset_test_utils::xcm_helpers::transfer_assets_delivery_fees::<
<$sender_xcm_config as xcm_executor::Config>::XcmSender,
>(assets, fee_asset_item, weight_limit.clone(), beneficiary, relay_destination)
});

assert_eq!(para_sender_balance_before - $amount - delivery_fees, para_sender_balance_after);
assert!(relay_receiver_balance_after > relay_receiver_balance_before);

// Update sender balance
para_sender_balance_before = <$sender_para as $crate::Chain>::account_data_of(sender.clone()).free;
}
};
}

#[macro_export]
macro_rules! test_chain_can_claim_assets {
( $sender_para:ty, $runtime_call:ty, $network_id:expr, $assets:expr, $amount:expr ) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub use emulated_integration_tests_common::{
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use integration_tests_helpers::test_parachain_is_trusted_teleporter;
pub use integration_tests_helpers::test_sibling_is_trusted_teleporter;
pub use kusama_system_emulated_network::{
asset_hub_kusama_emulated_chain::{
genesis::ED as ASSET_HUB_KUSAMA_ED, AssetHubKusamaParaPallet as AssetHubKusamaPallet,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ fn teleport_to_other_system_parachains_works() {
let amount = ASSET_HUB_KUSAMA_ED * 100;
let native_asset: Assets = (Parent, amount).into();

test_parachain_is_trusted_teleporter!(
test_sibling_is_trusted_teleporter!(
AssetHubKusama, // Origin
AssetHubKusamaXcmConfig, // XCM Configuration
vec![BridgeHubKusama], // Destinations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub use emulated_integration_tests_common::{
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use integration_tests_helpers::test_parachain_is_trusted_teleporter;
pub use integration_tests_helpers::test_sibling_is_trusted_teleporter;
pub use parachains_common::{AccountId, Balance};
pub use polkadot_system_emulated_network::{
asset_hub_polkadot_emulated_chain::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ fn teleport_to_other_system_parachains_works() {
let amount = ASSET_HUB_POLKADOT_ED * 100;
let native_asset: Assets = (Parent, amount).into();

test_parachain_is_trusted_teleporter!(
test_sibling_is_trusted_teleporter!(
AssetHubPolkadot, // Origin
AssetHubPolkadotXcmConfig, // XCM Configuration
vec![BridgeHubPolkadot], // Destinations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub use emulated_integration_tests_common::{
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use integration_tests_helpers::test_parachain_is_trusted_teleporter;
pub use integration_tests_helpers::test_sibling_is_trusted_teleporter;
pub use kusama_polkadot_system_emulated_network::{
asset_hub_kusama_emulated_chain::{
genesis::ED as ASSET_HUB_KUSAMA_ED, AssetHubKusamaParaPallet as AssetHubKusamaPallet,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn teleport_to_other_system_parachains_works() {
let amount = BRIDGE_HUB_KUSAMA_ED * 100;
let native_asset: Assets = (Parent, amount).into();

test_parachain_is_trusted_teleporter!(
test_sibling_is_trusted_teleporter!(
BridgeHubKusama, // Origin
XcmConfig, // XCM configuration
vec![AssetHubKusama], // Destinations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub use emulated_integration_tests_common::{
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use integration_tests_helpers::test_parachain_is_trusted_teleporter;
pub use integration_tests_helpers::test_sibling_is_trusted_teleporter;
pub use kusama_polkadot_system_emulated_network::{
asset_hub_kusama_emulated_chain::{
genesis::ED as ASSET_HUB_KUSAMA_ED, AssetHubKusamaParaPallet as AssetHubKusamaPallet,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn teleport_to_other_system_parachains_works() {
let amount = BRIDGE_HUB_POLKADOT_ED * 100;
let native_asset: Assets = (Parent, amount).into();

test_parachain_is_trusted_teleporter!(
test_sibling_is_trusted_teleporter!(
BridgeHubPolkadot, // Origin
XcmConfig, // XCM configuration
vec![AssetHubPolkadot], // Destinations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pallet-assets = { workspace = true, default-features = true }
pallet-treasury = { workspace = true, default-features = true }
pallet-message-queue = { workspace = true, default-features = true }
pallet-utility = { workspace = true, default-features = true }
pallet-whitelist = { workspace = true, default-features = true }

# Polkadot
polkadot-runtime-common = { workspace = true, default-features = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,21 @@ pub use emulated_integration_tests_common::{
xcm_emulator::{assert_expected_events, bx, Chain, Parachain, RelayChain as Relay, TestExt},
};
pub use polkadot_system_emulated_network::{
asset_hub_polkadot_emulated_chain::AssetHubPolkadotParaPallet as AssetHubPolkadotPallet,
collectives_polkadot_emulated_chain::CollectivesPolkadotParaPallet as CollectivesPolkadotPallet,
polkadot_emulated_chain::PolkadotRelayPallet as PolkadotPallet,
AssetHubPolkadotPara as AssetHubPolkadot, CollectivesPolkadotPara as CollectivesPolkadot,
PolkadotRelay as Polkadot,
asset_hub_polkadot_emulated_chain::{
genesis::ED as ASSET_HUB_POLKADOT_ED, AssetHubPolkadotParaPallet as AssetHubPolkadotPallet,
},
collectives_polkadot_emulated_chain::{
genesis::ED as COLLECTIVES_POLKADOT_ED,
CollectivesPolkadotParaPallet as CollectivesPolkadotPallet,
},
polkadot_emulated_chain::{genesis::ED as POLKADOT_ED, PolkadotRelayPallet as PolkadotPallet},
AssetHubPolkadotPara as AssetHubPolkadot,
AssetHubPolkadotParaReceiver as AssetHubPolkadotReceiver,
AssetHubPolkadotParaSender as AssetHubPolkadotSender,
CollectivesPolkadotPara as CollectivesPolkadot,
CollectivesPolkadotParaReceiver as CollectivesPolkadotReceiver,
CollectivesPolkadotParaSender as CollectivesPolkadotSender, PolkadotRelay as Polkadot,
PolkadotRelayReceiver as PolkadotReceiver, PolkadotRelaySender as PolkadotSender,
};

#[cfg(test)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// 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::*;
use codec::Encode;
use collectives_polkadot_runtime::fellowship::pallet_fellowship_origins::Origin::Fellows as FellowsOrigin;
use frame_support::{assert_ok, sp_runtime::traits::Dispatchable};

#[test]
fn fellows_whitelist_call() {
CollectivesPolkadot::execute_with(|| {
type RuntimeEvent = <CollectivesPolkadot as Chain>::RuntimeEvent;
type RuntimeCall = <CollectivesPolkadot as Chain>::RuntimeCall;
type RuntimeOrigin = <CollectivesPolkadot as Chain>::RuntimeOrigin;
type Runtime = <CollectivesPolkadot as Chain>::Runtime;
type PolkadotCall = <Polkadot as Chain>::RuntimeCall;
type PolkadotRuntime = <Polkadot as Chain>::Runtime;

let call_hash = [1u8; 32].into();

let whitelist_call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::<Runtime>::send {
dest: bx!(VersionedLocation::V4(Parent.into())),
message: bx!(VersionedXcm::V4(Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
Transact {
origin_kind: OriginKind::Xcm,
require_weight_at_most: Weight::from_parts(5_000_000_000, 500_000),
call: PolkadotCall::Whitelist(
pallet_whitelist::Call::<PolkadotRuntime>::whitelist_call { call_hash }
)
.encode()
.into(),
}
]))),
});

let fellows_origin: RuntimeOrigin = FellowsOrigin.into();

assert_ok!(whitelist_call.dispatch(fellows_origin));

assert_expected_events!(
CollectivesPolkadot,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
]
);
});

Polkadot::execute_with(|| {
type RuntimeEvent = <Polkadot as Chain>::RuntimeEvent;

assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::Whitelist(pallet_whitelist::Event::CallWhitelisted { .. }) => {},
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {},
]
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

mod fellowship;
mod fellowship_salary;
mod fellowship_treasury;
mod teleport;
Loading

0 comments on commit c2886b9

Please sign in to comment.