// 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. pub use paste; // Substrate pub use pallet_balances; pub use pallet_message_queue; pub use pallet_xcm; // Polkadot pub use xcm::prelude::{AccountId32, WeightLimit}; // Cumulus pub use asset_test_utils; pub use cumulus_pallet_xcmp_queue; pub use xcm_emulator::Chain; #[macro_export] macro_rules! test_parachain_is_trusted_teleporter { ( $sender_para:ty, $sender_xcm_config:ty, vec![$( $receiver_para:ty ),+], ($assets:expr, $amount:expr) ) => { $crate::macros::paste::paste! { // init Origin variables let sender = [<$sender_para Sender>]::get(); let mut para_sender_balance_before = <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free; let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone()); let fee_asset_item = 0; let weight_limit = $crate::macros::WeightLimit::Unlimited; $( { // init Destination variables let receiver = [<$receiver_para Receiver>]::get(); let para_receiver_balance_before = <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free; let para_destination = <$sender_para>::sibling_location_of(<$receiver_para>::para_id()); let beneficiary: MultiLocation = $crate::macros::AccountId32 { network: None, id: receiver.clone().into() }.into(); // Send XCM message from Origin Parachain // We are only testing the limited teleport version, which should be ok since success will // depend only on a proper `XcmConfig` at destination. <$sender_para>::execute_with(|| { assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::limited_teleport_assets( origin.clone(), bx!(para_destination.into()), bx!(beneficiary.into()), bx!($assets.clone().into()), fee_asset_item, weight_limit.clone(), )); type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent; assert_expected_events!( $sender_para, vec![ RuntimeEvent::PolkadotXcm( $crate::macros::pallet_xcm::Event::Attempted { outcome: Outcome::Complete { .. } } ) => {}, RuntimeEvent::XcmpQueue( $crate::macros::cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. } ) => {}, RuntimeEvent::Balances( $crate::macros::pallet_balances::Event::Withdraw { who: sender, amount } ) => {}, ] ); }); // Receive XCM message in Destination Parachain <$receiver_para>::execute_with(|| { type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent; assert_expected_events!( $receiver_para, vec![ RuntimeEvent::Balances( $crate::macros::pallet_balances::Event::Deposit { who: receiver, .. } ) => {}, RuntimeEvent::MessageQueue( $crate::macros::pallet_message_queue::Event::Processed { success: true, .. } ) => {}, ] ); }); // Check if balances are updated accordingly in Origin and Destination Parachains let para_sender_balance_after = <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free; let para_receiver_balance_after = <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free; let delivery_fees = <$sender_para>::execute_with(|| { $crate::macros::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!(para_sender_balance_before - $amount - delivery_fees, para_sender_balance_after); assert!(para_receiver_balance_after > para_receiver_balance_before); // Update sender balance para_sender_balance_before = <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free; } )+ } }; }