Files
pezkuwi-sdk/pezcumulus/teyrchains/integration-tests/emulated/common/src/macros.rs
T
pezkuwichain 90fd044766 fix: Complete snowbridge pezpallet rebrand and critical bug fixes
- snowbridge-pezpallet-* → pezsnowbridge-pezpallet-* (201 refs)
- pallet/ directories → pezpallet/ (4 locations)
- Fixed pezpallet.rs self-include recursion bug
- Fixed sc-chain-spec hardcoded crate name in derive macro
- Reverted .pezpallet_by_name() to .pallet_by_name() (subxt API)
- Added BizinikiwiConfig type alias for zombienet tests
- Deleted obsolete session state files

Verified: pezsnowbridge-pezpallet-*, pezpallet-staking,
pezpallet-staking-async, pezframe-benchmarking-cli all pass cargo check
2025-12-16 09:57:23 +03:00

1160 lines
50 KiB
Rust

// 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;
// Bizinikiwi
pub use pezframe_support::{pezpallet_prelude::Weight, weights::WeightToFee};
pub use pezpallet_asset_conversion;
pub use pezpallet_assets;
pub use pezpallet_balances;
pub use pezpallet_message_queue;
pub use pezpallet_whitelist;
pub use pezpallet_xcm;
pub use pezframe_support::assert_ok;
// Pezkuwi
pub use pezkuwi_runtime_teyrchains::dmp::Pezpallet as Dmp;
pub use xcm::{
latest::AssetTransferFilter,
prelude::{
AliasOrigin, All, AllCounted, Asset, AssetId, Assets, BuyExecution, DepositAsset,
ExpectTransactStatus, Fungible, GeneralIndex, Here, InitiateTransfer, Junction, Location,
MaybeErrorCode, OriginKind, Outcome, PalletInstance, Parent, PayFees, RefundSurplus,
Teyrchain, Transact, Unlimited, VersionedAssetId, VersionedAssets, VersionedLocation,
VersionedXcm, WeightLimit, Wild, WithdrawAsset, Xcm, XcmContext, XCM_VERSION,
},
};
pub use xcm_executor::traits::{DropAssets, TransferType};
// Pezcumulus
pub use asset_test_pezutils;
pub use pezcumulus_pezpallet_xcmp_queue;
pub use teyrchains_common::AccountId;
pub use xcm_pez_emulator::{
assert_expected_events, Chain, RelayChain, TestArgs, TestContext, TestExt, Teyrchain as Para,
};
pub use pezframe_support::{
dispatch::{GetDispatchInfo, RawOrigin},
BoundedVec,
};
pub use xcm_runtime_pezapis::{
dry_run::runtime_decl_for_dry_run_api::DryRunApiV2,
fees::{runtime_decl_for_xcm_payment_api::XcmPaymentApiV2, Error as XcmPaymentApiError},
};
pub use pezframe_support::traits::{fungible::Mutate, fungibles::Inspect, Currency};
pub use pezsp_runtime::{traits::Dispatchable, AccountId32};
pub use crate::{ASSETS_PALLET_ID, USDT_ID};
#[macro_export]
macro_rules! test_teyrchain_is_trusted_teleporter {
( $sender_para:ty, vec![$( $receiver_para:ty ),+], ($assets:expr, $amount:expr), $fee_asset_id:expr, $xcm_call:ident ) => {
$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 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 as $crate::macros::Para>::sibling_location_of(
<$receiver_para as $crate::macros::Para>::para_id());
let beneficiary: $crate::macros::Location =
$crate::macros::Junction::AccountId32 { network: None, id: receiver.clone().into() }.into();
// Dry-run first.
let call = <$sender_para as $crate::macros::Chain>::RuntimeCall::PezkuwiXcm(
$crate::macros::pezpallet_xcm::Call::$xcm_call {
dest: Box::new(para_destination.clone().into()),
beneficiary: Box::new(beneficiary.clone().into()),
assets: Box::new($assets.clone().into()),
fee_asset_id: Box::new($fee_asset_id.clone().into()),
weight_limit: weight_limit.clone(),
});
// assume up to 90% of max weight
let max_weight_with_margin_for_error = ($crate::macros::Weight::MAX.ref_time() / 100) * 90;
assert!(<_ as $crate::macros::GetDispatchInfo>::get_dispatch_info(&call)
.call_weight.ref_time() < max_weight_with_margin_for_error);
let mut delivery_fees_amount = 0;
let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm(Vec::new()));
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
type OriginCaller = <$sender_para as $crate::macros::Chain>::OriginCaller;
let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
$crate::macros::XCM_VERSION).unwrap();
// We filter the result to get only the messages we are interested in.
let (destination_to_query, messages_to_query) = &result
.forwarded_xcms
.iter()
.find(|(destination, _)| {
*destination == $crate::macros::VersionedLocation::from($crate::macros::Location::new(1,
[$crate::macros::Teyrchain(<$receiver_para as $crate::macros::Para>::para_id().into())]))
})
.unwrap();
assert_eq!(messages_to_query.len(), 1);
remote_message = messages_to_query[0].clone();
// The native asset of every system chain.
// We want to get the delivery fees in this asset.
let asset_id_for_delivery_fees = VersionedAssetId::from(Location::new(1, []));
let delivery_fees =
<Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
destination_to_query.clone(),
remote_message.clone(),
asset_id_for_delivery_fees
).unwrap();
let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
let $crate::macros::Fungible(inner_delivery_fees_amount) = latest_delivery_fees.inner()[0].fun else {
unreachable!("asset is non-fungible");
};
delivery_fees_amount = inner_delivery_fees_amount;
});
// Reset to send actual message.
<$sender_para as $crate::macros::TestExt>::reset_ext();
<$receiver_para as $crate::macros::TestExt>::reset_ext();
// TODO: The test fails without the line below, seems like no horizontal message passing is being done
// when also using dry_run_call above (it works if there is no dry_run_call)
// So this is just workaround, must be investigated
<$sender_para as $crate::macros::TestExt>::execute_with(|| { });
// Send XCM message from Origin Teyrchain
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
$crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$sender_para,
vec![
RuntimeEvent::PezkuwiXcm(
$crate::macros::pezpallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
) => {},
RuntimeEvent::XcmpQueue(
$crate::macros::pezcumulus_pezpallet_xcmp_queue::Event::XcmpMessageSent { .. }
) => {},
RuntimeEvent::Balances(
$crate::macros::pezpallet_balances::Event::Burned { who: sender, amount }
) => {},
]
);
});
// Receive XCM message in Destination Teyrchain
<$receiver_para as $crate::macros::TestExt>::execute_with(|| {
type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$receiver_para,
vec![
RuntimeEvent::Balances(
$crate::macros::pezpallet_balances::Event::Minted { who: receiver, .. }
) => {},
RuntimeEvent::MessageQueue(
$crate::macros::pezpallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});
// Check if balances are updated accordingly in Origin and Destination Teyrchains
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;
assert_eq!(para_sender_balance_before - $amount - delivery_fees_amount, 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;
}
)+
}
};
}
#[macro_export]
macro_rules! test_relay_is_trusted_teleporter {
( $sender_relay:ty, vec![$( $receiver_para:ty ),+], $amount:expr, $xcm_call:ident ) => {
$crate::macros::paste::paste! {
// init Origin variables
let sender = [<$sender_relay Sender>]::get();
let mut relay_sender_balance_before =
<$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free;
let assets: $crate::macros::Assets = ($crate::macros::Here, $amount).into();
let fee_asset_id: $crate::macros::AssetId = ($crate::macros::Here).into();
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_relay as $crate::macros::RelayChain>::child_location_of(
<$receiver_para as $crate::macros::Para>::para_id());
let beneficiary: $crate::macros::Location =
$crate::macros::Junction::AccountId32 { network: None, id: receiver.clone().into() }.into();
// Dry-run first.
let call = <$sender_relay as $crate::macros::Chain>::RuntimeCall::XcmPallet(
$crate::macros::pezpallet_xcm::Call::$xcm_call {
dest: Box::new(para_destination.clone().into()),
beneficiary: Box::new(beneficiary.clone().into()),
assets: Box::new(assets.clone().into()),
fee_asset_id: Box::new(fee_asset_id.clone().into()),
weight_limit: weight_limit.clone(),
});
// verify sane weight for a call
// assume up to 90% of max weight
let max_weight_with_margin_for_error = ($crate::macros::Weight::MAX.ref_time() / 100) * 90;
assert!(<_ as $crate::macros::GetDispatchInfo>::get_dispatch_info(&call)
.call_weight.ref_time() < max_weight_with_margin_for_error);
let mut delivery_fees_amount = 0;
let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm(Vec::new()));
<$sender_relay as $crate::macros::TestExt>::execute_with(|| {
$crate::macros::Dmp::<<$sender_relay as $crate::macros::Chain>::Runtime>::make_teyrchain_reachable(
<$receiver_para as $crate::macros::Para>::para_id());
type Runtime = <$sender_relay as $crate::macros::Chain>::Runtime;
type OriginCaller = <$sender_relay as $crate::macros::Chain>::OriginCaller;
let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
$crate::macros::XCM_VERSION).unwrap();
// We filter the result to get only the messages we are interested in.
let (destination_to_query, messages_to_query) = &result
.forwarded_xcms
.iter()
.find(|(destination, _)| {
*destination == $crate::macros::VersionedLocation::from($crate::macros::Location::new(0,
[$crate::macros::Teyrchain(<$receiver_para as $crate::macros::Para>::para_id().into())]))
})
.unwrap();
assert_eq!(messages_to_query.len(), 1);
remote_message = messages_to_query[0].clone();
// The native asset of every system chain.
// We want to get the delivery fees in this asset.
let asset_id_for_delivery_fees = VersionedAssetId::from(Location::new(0, []));
let delivery_fees =
<Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
destination_to_query.clone(),
remote_message.clone(),
asset_id_for_delivery_fees
).unwrap();
let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
let $crate::macros::Fungible(inner_delivery_fees_amount) = latest_delivery_fees.inner()[0].fun else {
unreachable!("asset is non-fungible");
};
delivery_fees_amount = inner_delivery_fees_amount;
});
// Reset to send actual message.
<$sender_relay as $crate::macros::TestExt>::reset_ext();
<$receiver_para as $crate::macros::TestExt>::reset_ext();
// Send XCM message from Relay.
<$sender_relay as $crate::macros::TestExt>::execute_with(|| {
$crate::macros::Dmp::<<$sender_relay as $crate::macros::Chain>::Runtime>::make_teyrchain_reachable(
<$receiver_para as $crate::macros::Para>::para_id());
let origin = <$sender_relay as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
$crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
type RuntimeEvent = <$sender_relay as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$sender_relay,
vec![
RuntimeEvent::XcmPallet(
$crate::macros::pezpallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
) => {},
RuntimeEvent::Balances(
$crate::macros::pezpallet_balances::Event::Burned { who: sender, amount }
) => {},
RuntimeEvent::XcmPallet(
$crate::macros::pezpallet_xcm::Event::Sent { .. }
) => {},
]
);
});
// Receive XCM message in Destination Teyrchain
<$receiver_para as $crate::macros::TestExt>::execute_with(|| {
type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$receiver_para,
vec![
RuntimeEvent::Balances(
$crate::macros::pezpallet_balances::Event::Minted { who: receiver, .. }
) => {},
RuntimeEvent::MessageQueue(
$crate::macros::pezpallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});
// Check if balances are updated accordingly in Origin and Teyrchain
let relay_sender_balance_after =
<$sender_relay 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;
assert_eq!(relay_sender_balance_before - $amount - delivery_fees_amount, relay_sender_balance_after);
assert!(para_receiver_balance_after > para_receiver_balance_before);
// Update sender balance
relay_sender_balance_before = <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free;
}
)+
}
};
}
#[macro_export]
macro_rules! test_teyrchain_is_trusted_teleporter_for_relay {
( $sender_para:ty, $receiver_relay:ty, $amount:expr, $xcm_call:ident ) => {
$crate::macros::paste::paste! {
// init Origin variables
let sender = [<$sender_para Sender>]::get();
// Mint assets to `$sender_para` to succeed with teleport.
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
$crate::macros::assert_ok!(<<$sender_para as [<$sender_para Pezpallet>]>::Balances
as $crate::macros::Mutate<_>>::mint_into(&sender, $amount + 10_000_000_000));
});
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 assets: $crate::macros::Assets = ($crate::macros::Parent, $amount).into();
let fee_asset_id: $crate::macros::AssetId = ($crate::macros::Parent).into();
let weight_limit = $crate::macros::WeightLimit::Unlimited;
// We need to mint funds into the checking account of `$receiver_relay`
// for it to accept a teleport from `$sender_para`.
// Else we'd get a `NotWithdrawable` error since it tries to reduce the check account balance, which
// would be 0.
<$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
let check_account = <$receiver_relay as [<$receiver_relay Pezpallet>]>::XcmPallet::check_account();
$crate::macros::assert_ok!(<<$receiver_relay as [<$receiver_relay Pezpallet>]>::Balances
as $crate::macros::Mutate<_>>::mint_into(&check_account, $amount));
});
// Init destination variables.
let receiver = [<$receiver_relay Receiver>]::get();
let relay_receiver_balance_before =
<$receiver_relay as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
let relay_destination: $crate::macros::Location = $crate::macros::Parent.into();
let beneficiary: $crate::macros::Location =
$crate::macros::Junction::AccountId32 { network: None, id: receiver.clone().into() }.into();
// Dry-run first.
let call = <$sender_para as $crate::macros::Chain>::RuntimeCall::PezkuwiXcm($crate::macros::pezpallet_xcm::Call::$xcm_call {
dest: Box::new(relay_destination.clone().into()),
beneficiary: Box::new(beneficiary.clone().into()),
assets: Box::new(assets.clone().into()),
fee_asset_id: Box::new(fee_asset_id.clone().into()),
weight_limit: weight_limit.clone(),
});
// verify sane weight for a call
// assume up to 90% of max weight
let max_weight_with_margin_for_error = ($crate::macros::Weight::MAX.ref_time() / 100) * 90;
assert!(<_ as $crate::macros::GetDispatchInfo>::get_dispatch_info(&call)
.call_weight.ref_time() < max_weight_with_margin_for_error);
// These will be filled in the closure.
let mut delivery_fees_amount = 0;
let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm(Vec::new()));
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
type OriginCaller = <$sender_para as $crate::macros::Chain>::OriginCaller;
let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
$crate::macros::XCM_VERSION).unwrap();
// We filter the result to get only the messages we are interested in.
let (destination_to_query, messages_to_query) = &result
.forwarded_xcms
.iter()
.find(|(destination, _)| {
*destination == $crate::macros::VersionedLocation::from($crate::macros::Location::parent())
})
.unwrap();
assert_eq!(messages_to_query.len(), 1);
remote_message = messages_to_query[0].clone();
// The native asset of every system chain.
// We want to get the delivery fees in this asset.
let asset_id_for_delivery_fees = VersionedAssetId::from(Location::parent());
let delivery_fees =
<Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
destination_to_query.clone(),
remote_message.clone(),
asset_id_for_delivery_fees
).unwrap();
let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
delivery_fees_amount = if let Some(first_asset) = latest_delivery_fees.inner().first() {
let $crate::macros::Fungible(inner_delivery_fees_amount) = first_asset.fun else {
unreachable!("asset is non-fungible");
};
inner_delivery_fees_amount
} else {
0
}
});
// Reset to send actual message.
<$sender_para as $crate::macros::TestExt>::reset_ext();
<$receiver_relay as $crate::macros::TestExt>::reset_ext();
// Mint assets to `$sender_para` to succeed with teleport.
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
$crate::macros::assert_ok!(<<$sender_para as [<$sender_para Pezpallet>]>::Balances
as $crate::macros::Mutate<_>>::mint_into(&sender, $amount + 10_000_000_000));
});
// Since we reset everything, we need to mint funds into the checking account again.
<$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
let check_account = <$receiver_relay as [<$receiver_relay Pezpallet>]>::XcmPallet::check_account();
$crate::macros::assert_ok!(<<$receiver_relay as [<$receiver_relay Pezpallet>]>::Balances
as $crate::macros::Mutate<_>>::mint_into(&check_account, $amount));
});
// Send XCM message from Teyrchain.
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
$crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$sender_para,
vec![
RuntimeEvent::PezkuwiXcm(
$crate::macros::pezpallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
) => {},
RuntimeEvent::Balances(
$crate::macros::pezpallet_balances::Event::Burned { who: sender, amount }
) => {},
RuntimeEvent::PezkuwiXcm(
$crate::macros::pezpallet_xcm::Event::Sent { .. }
) => {},
]
);
});
// Receive XCM message in Destination Teyrchain
<$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
type RuntimeEvent = <$receiver_relay as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$receiver_relay,
vec![
RuntimeEvent::Balances(
$crate::macros::pezpallet_balances::Event::Minted { who: receiver, .. }
) => {},
RuntimeEvent::MessageQueue(
$crate::macros::pezpallet_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::macros::Chain>::account_data_of(sender.clone()).free;
let relay_receiver_balance_after =
<$receiver_relay as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
assert_eq!(para_sender_balance_before - $amount - delivery_fees_amount, para_sender_balance_after);
assert!(relay_receiver_balance_after > relay_receiver_balance_before);
// Update sender balance
para_sender_balance_before = <$sender_para as $crate::macros::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 ) => {
$crate::macros::paste::paste! {
let sender = [<$sender_para Sender>]::get();
let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
// Receiver is the same as sender
let beneficiary: $crate::macros::Location =
$crate::macros::Junction::AccountId32 { network: Some($network_id), id: sender.clone().into() }.into();
let versioned_assets: $crate::macros::VersionedAssets = $assets.clone().into();
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
// Assets are trapped for whatever reason.
// The possible reasons for this might differ from runtime to runtime, so here we just drop them directly.
<<$sender_para as [<$sender_para Pezpallet>]>::PezkuwiXcm as $crate::macros::DropAssets>::drop_assets(
&beneficiary,
$assets.clone().into(),
&$crate::macros::XcmContext { origin: None, message_id: [0u8; 32], topic: None },
);
type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$sender_para,
vec![
RuntimeEvent::PezkuwiXcm(
$crate::macros::pezpallet_xcm::Event::AssetsTrapped { origin: beneficiary, assets: versioned_assets, .. }
) => {},
]
);
let balance_before = <<$sender_para as [<$sender_para Pezpallet>]>::Balances
as $crate::macros::Currency<_>>::free_balance(&sender);
// Different origin or different assets won't work.
let other_origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed([<$sender_para Receiver>]::get());
assert!(<$sender_para as [<$sender_para Pezpallet>]>::PezkuwiXcm::claim_assets(
other_origin,
Box::new(versioned_assets.clone().into()),
Box::new(beneficiary.clone().into()),
).is_err());
let other_versioned_assets: $crate::macros::VersionedAssets = $crate::macros::Assets::new().into();
assert!(<$sender_para as [<$sender_para Pezpallet>]>::PezkuwiXcm::claim_assets(
origin.clone(),
Box::new(other_versioned_assets.into()),
Box::new(beneficiary.clone().into()),
).is_err());
// Assets will be claimed to `beneficiary`, which is the same as `sender`.
$crate::macros::assert_ok!(<$sender_para as [<$sender_para Pezpallet>]>::PezkuwiXcm::claim_assets(
origin.clone(),
Box::new(versioned_assets.clone().into()),
Box::new(beneficiary.clone().into()),
));
$crate::macros::assert_expected_events!(
$sender_para,
vec![
RuntimeEvent::PezkuwiXcm(
$crate::macros::pezpallet_xcm::Event::AssetsClaimed { origin: beneficiary, assets: versioned_assets, .. }
) => {},
]
);
// After claiming the assets, the balance has increased.
let balance_after = <<$sender_para as [<$sender_para Pezpallet>]>::Balances
as $crate::macros::Currency<_>>::free_balance(&sender);
assert_eq!(balance_after, balance_before + $amount);
// Claiming the assets again doesn't work.
assert!(<$sender_para as [<$sender_para Pezpallet>]>::PezkuwiXcm::claim_assets(
origin.clone(),
Box::new(versioned_assets.clone().into()),
Box::new(beneficiary.clone().into()),
).is_err());
let balance = <<$sender_para as [<$sender_para Pezpallet>]>::Balances
as $crate::macros::Currency<_>>::free_balance(&sender);
assert_eq!(balance, balance_after);
// You can also claim assets and send them to a different account.
<<$sender_para as [<$sender_para Pezpallet>]>::PezkuwiXcm as $crate::macros::DropAssets>::drop_assets(
&beneficiary,
$assets.clone().into(),
&$crate::macros::XcmContext { origin: None, message_id: [0u8; 32], topic: None },
);
let receiver = [<$sender_para Receiver>]::get();
let other_beneficiary: $crate::macros::Location =
$crate::macros::Junction::AccountId32 { network: Some($network_id), id: receiver.clone().into() }.into();
let balance_before = <<$sender_para as [<$sender_para Pezpallet>]>::Balances
as $crate::macros::Currency<_>>::free_balance(&receiver);
$crate::macros::assert_ok!(<$sender_para as [<$sender_para Pezpallet>]>::PezkuwiXcm::claim_assets(
origin.clone(),
Box::new(versioned_assets.clone().into()),
Box::new(other_beneficiary.clone().into()),
));
let balance_after = <<$sender_para as [<$sender_para Pezpallet>]>::Balances
as $crate::macros::Currency<_>>::free_balance(&receiver);
assert_eq!(balance_after, balance_before + $amount);
});
}
};
}
#[macro_export]
macro_rules! test_can_estimate_and_pay_exact_fees {
( $sender_para:ty, $asset_hub:ty, $receiver_para:ty, ($asset_id:expr, $amount:expr), $owner_prefix:ty ) => {
$crate::macros::paste::paste! {
// We first define the call we'll use throughout the test.
fn get_call(
estimated_local_fees: impl Into<$crate::macros::Asset>,
estimated_intermediate_fees: impl Into<$crate::macros::Asset>,
estimated_remote_fees: impl Into<$crate::macros::Asset>,
) -> <$sender_para as $crate::macros::Chain>::RuntimeCall {
type RuntimeCall = <$sender_para as $crate::macros::Chain>::RuntimeCall;
let beneficiary = [<$receiver_para Receiver>]::get();
let xcm_in_destination = $crate::macros::Xcm::<()>::builder_unsafe()
.pay_fees(estimated_remote_fees)
.deposit_asset($crate::macros::AllCounted(1), beneficiary)
.build();
let ah_to_receiver = <$asset_hub as $crate::macros::Para>::sibling_location_of(
<$receiver_para as $crate::macros::Para>::para_id());
let xcm_in_reserve = $crate::macros::Xcm::<()>::builder_unsafe()
.pay_fees(estimated_intermediate_fees)
.deposit_reserve_asset(
$crate::macros::AllCounted(1),
ah_to_receiver,
xcm_in_destination,
)
.build();
let sender_to_ah = <$sender_para as $crate::macros::Para>::sibling_location_of(
<$asset_hub as $crate::macros::Para>::para_id());
let local_xcm = $crate::macros::Xcm::<<$sender_para as $crate::macros::Chain>::RuntimeCall>::builder()
.withdraw_asset(($asset_id, $amount))
.pay_fees(estimated_local_fees)
.initiate_reserve_withdraw($crate::macros::AllCounted(1), sender_to_ah, xcm_in_reserve)
.build();
RuntimeCall::PezkuwiXcm($crate::macros::pezpallet_xcm::Call::execute {
message: Box::new($crate::macros::VersionedXcm::from(local_xcm)),
max_weight: $crate::macros::Weight::from_parts(10_000_000_000, 500_000),
})
}
let destination = <$sender_para as $crate::macros::Para>::sibling_location_of(
<$receiver_para as $crate::macros::Para>::para_id());
let sender = [<$sender_para Sender>]::get();
let sender_as_seen_by_ah = <$asset_hub as $crate::macros::Para>::sibling_location_of(
<$sender_para as $crate::macros::Para>::para_id());
let sov_of_sender_on_ah = <$asset_hub as $crate::macros::Para>::sovereign_account_id_of(sender_as_seen_by_ah.clone());
let asset_owner = [<$owner_prefix AssetOwner>]::get();
// Fund teyrchain's sender account.
// TODO: consider mint_foreign_asset to be part of xcm_pez_emulator::Chain trait
$sender_para::mint_foreign_asset(
<$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(asset_owner.clone()),
$asset_id.clone().into(),
sender.clone(),
$amount * 2,
);
// Fund the teyrchain origin's SA on Asset Hub with the native tokens.
// TODO: consider fund_accounts to be part of xcm_pez_emulator::Chain trait
$asset_hub::fund_accounts(vec![(sov_of_sender_on_ah.clone(), $amount * 2)]);
let beneficiary_id = [<$receiver_para Receiver>]::get();
let test_args = $crate::macros::TestContext {
sender: sender.clone(),
receiver: beneficiary_id.clone(),
args: $crate::macros::TestArgs::new_para(
destination,
beneficiary_id.clone(),
$amount,
($asset_id, $amount).into(),
None,
($asset_id).into(),
),
};
let mut test = ParaToParaThroughAHTest::new(test_args);
// We get these from the closure.
let mut local_execution_fees = 0;
let mut local_delivery_fees = 0;
let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm::<()>(Vec::new()));
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
type OriginCaller = <$sender_para as $crate::macros::Chain>::OriginCaller;
let call = get_call(
($crate::macros::Parent, 100_000_000_000u128),
($crate::macros::Parent, 100_000_000_000u128),
($crate::macros::Parent, 100_000_000_000u128),
);
let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
$crate::macros::XCM_VERSION).unwrap();
let local_xcm = result.local_xcm.unwrap().clone();
let local_xcm_weight = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_xcm_weight(local_xcm).unwrap();
local_execution_fees = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(
local_xcm_weight,
$crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::parent())),
)
.unwrap();
// We filter the result to get only the messages we are interested in.
let (destination_to_query, messages_to_query) = &result
.forwarded_xcms
.iter()
.find(|(destination, _)| {
*destination == $crate::macros::VersionedLocation::from(
$crate::macros::Location::new(1, [$crate::macros::Teyrchain(1000)]))
})
.unwrap();
assert_eq!(messages_to_query.len(), 1);
remote_message = messages_to_query[0].clone();
let asset_id_for_delivery_fees = VersionedAssetId::from(Location::parent());
let delivery_fees =
<Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
destination_to_query.clone(),
remote_message.clone(),
asset_id_for_delivery_fees
).unwrap();
local_delivery_fees = $crate::xcm_helpers::get_amount_from_versioned_assets(delivery_fees);
});
// These are set in the AssetHub closure.
let mut intermediate_execution_fees = 0;
let mut intermediate_delivery_fees = 0;
let mut intermediate_remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm::<()>(Vec::new()));
<$asset_hub as $crate::macros::TestExt>::execute_with(|| {
type Runtime = <$asset_hub as $crate::macros::Chain>::Runtime;
type RuntimeCall = <$asset_hub as $crate::macros::Chain>::RuntimeCall;
// First we get the execution fees.
let weight = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_xcm_weight(remote_message.clone()).unwrap();
intermediate_execution_fees = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(
weight,
$crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::new(1, []))),
)
.unwrap();
// We have to do this to turn `VersionedXcm<()>` into `VersionedXcm<RuntimeCall>`.
let xcm_program =
$crate::macros::VersionedXcm::from($crate::macros::Xcm::<RuntimeCall>::from(
remote_message.clone().try_into().unwrap()));
// Now we get the delivery fees to the final destination.
let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_xcm(
sender_as_seen_by_ah.clone().into(), xcm_program).unwrap();
let (destination_to_query, messages_to_query) = &result
.forwarded_xcms
.iter()
.find(|(destination, _)| {
*destination == $crate::macros::VersionedLocation::from($crate::macros::Location::new(1,
[$crate::macros::Teyrchain(2001)]))
})
.unwrap();
// There's actually two messages here.
// One created when the message we sent from `$sender_para` arrived and was executed.
// The second one when we dry-run the xcm.
// We could've gotten the message from the queue without having to dry-run, but
// offchain applications would have to dry-run, so we do it here as well.
intermediate_remote_message = messages_to_query[0].clone();
let asset_id_for_delivery_fees = VersionedAssetId::from(Location::parent());
let delivery_fees = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
destination_to_query.clone(),
intermediate_remote_message.clone(),
asset_id_for_delivery_fees,
)
.unwrap();
intermediate_delivery_fees = $crate::xcm_helpers::get_amount_from_versioned_assets(delivery_fees);
});
// Get the final execution fees in the destination.
let mut final_execution_fees = 0;
<$receiver_para as $crate::macros::TestExt>::execute_with(|| {
type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
let weight = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_xcm_weight(
intermediate_remote_message.clone()).unwrap();
final_execution_fees =
<Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
$crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::parent())))
.unwrap();
});
// Dry-running is done.
<$sender_para as $crate::macros::TestExt>::reset_ext();
<$asset_hub as $crate::macros::TestExt>::reset_ext();
<$receiver_para as $crate::macros::TestExt>::reset_ext();
// Fund accounts again.
$sender_para::mint_foreign_asset(
<$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(asset_owner),
$asset_id.clone().into(),
sender.clone(),
$amount * 2,
);
$asset_hub::fund_accounts(vec![(sov_of_sender_on_ah, $amount * 2)]);
// Actually run the extrinsic.
let sender_assets_before = <$sender_para as $crate::macros::TestExt>::execute_with(|| {
type ForeignAssets = <$sender_para as [<$sender_para Pezpallet>]>::ForeignAssets;
<ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &sender)
});
let receiver_assets_before = <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
type ForeignAssets = <$receiver_para as [<$receiver_para Pezpallet>]>::ForeignAssets;
<ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &beneficiary_id)
});
test.set_assertion::<$sender_para>(sender_assertions);
test.set_assertion::<$asset_hub>(hop_assertions);
test.set_assertion::<$receiver_para>(receiver_assertions);
let call = get_call(
($crate::macros::Parent, local_execution_fees + local_delivery_fees),
($crate::macros::Parent, intermediate_execution_fees + intermediate_delivery_fees),
($crate::macros::Parent, final_execution_fees),
);
test.set_call(call);
test.assert();
let sender_assets_after = <$sender_para as $crate::macros::TestExt>::execute_with(|| {
type ForeignAssets = <$sender_para as [<$sender_para Pezpallet>]>::ForeignAssets;
<ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &sender)
});
let receiver_assets_after = <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
type ForeignAssets = <$receiver_para as [<$receiver_para Pezpallet>]>::ForeignAssets;
<ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.into(), &beneficiary_id)
});
// We know the exact fees on every hop.
assert_eq!(sender_assets_after, sender_assets_before - $amount);
assert_eq!(
receiver_assets_after,
receiver_assets_before + $amount -
local_execution_fees -
local_delivery_fees -
intermediate_execution_fees -
intermediate_delivery_fees -
final_execution_fees
);
}
};
}
#[macro_export]
macro_rules! test_dry_run_transfer_across_pk_bridge {
( $sender_asset_hub:ty, $sender_bridge_hub:ty, $destination:expr ) => {
$crate::macros::paste::paste! {
let who = $crate::macros::AccountId32::new([1u8; 32]);
let transfer_amount = 10_000_000_000_000u128;
let initial_balance = transfer_amount * 10;
// AssetHub setup.
$sender_asset_hub::force_xcm_version($destination, $crate::macros::XCM_VERSION);
<$sender_asset_hub as $crate::macros::TestExt>::execute_with(|| {
type Runtime = <$sender_asset_hub as $crate::macros::Chain>::Runtime;
type RuntimeCall = <$sender_asset_hub as $crate::macros::Chain>::RuntimeCall;
type OriginCaller = <$sender_asset_hub as $crate::macros::Chain>::OriginCaller;
type Balances = <$sender_asset_hub as [<$sender_asset_hub Pezpallet>]>::Balances;
// Give some initial funds.
<Balances as $crate::macros::Mutate<_>>::set_balance(&who, initial_balance);
let beneficiary: $crate::macros::Location = $crate::macros::Junction::AccountId32 {
id: who.clone().into(),
network: None,
}.into();
let call = RuntimeCall::PezkuwiXcm($crate::macros::pezpallet_xcm::Call::transfer_assets_using_type_and_then {
dest: Box::new($crate::macros::VersionedLocation::from($destination)),
assets: Box::new($crate::macros::VersionedAssets::from(vec![
($crate::macros::Parent, transfer_amount).into(),
])),
assets_transfer_type: Box::new($crate::macros::TransferType::LocalReserve),
remote_fees_id: Box::new($crate::macros::VersionedAssetId::from($crate::macros::Parent)),
fees_transfer_type: Box::new($crate::macros::TransferType::LocalReserve),
custom_xcm_on_dest: Box::new($crate::macros::VersionedXcm::<()>::from($crate::macros::Xcm::<()>::builder_unsafe().deposit_asset(AllCounted(1), beneficiary).build())),
weight_limit: $crate::macros::Unlimited,
});
let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(who));
let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
$crate::macros::XCM_VERSION).unwrap();
// We assert the dry run succeeds and sends only one message to the local bridge hub.
assert!(result.execution_result.is_ok());
assert_eq!(result.forwarded_xcms.len(), 1);
assert_eq!(result.forwarded_xcms[0].0, $crate::macros::VersionedLocation::from(
$crate::macros::Location::new(1, [$crate::macros::Teyrchain(
<$sender_bridge_hub as $crate::macros::Para>::para_id().into())])));
});
}
};
}
#[macro_export]
macro_rules! test_xcm_fee_querying_apis_work_for_asset_hub {
( $asset_hub:ty ) => {
$crate::macros::paste::paste! {
<$asset_hub as $crate::macros::TestExt>::execute_with(|| {
// Setup a pool between USDT and ZGR.
type RuntimeOrigin = <$asset_hub as $crate::macros::Chain>::RuntimeOrigin;
type Assets = <$asset_hub as [<$asset_hub Pezpallet>]>::Assets;
type AssetConversion = <$asset_hub as [<$asset_hub Pezpallet>]>::AssetConversion;
let wnd = $crate::macros::Location::new(1, []);
let usdt = $crate::macros::Location::new(0, [$crate::macros::PalletInstance($crate::macros::ASSETS_PALLET_ID),
$crate::macros::GeneralIndex($crate::macros::USDT_ID.into())]);
let sender = [<$asset_hub Sender>]::get();
$crate::macros::assert_ok!(AssetConversion::create_pool(
RuntimeOrigin::signed(sender.clone()),
Box::new(wnd.clone()),
Box::new(usdt.clone()),
));
type Runtime = <$asset_hub as $crate::macros::Chain>::Runtime;
let acceptable_payment_assets = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_acceptable_payment_assets(
$crate::macros::XCM_VERSION).unwrap();
assert_eq!(acceptable_payment_assets, vec![
$crate::macros::VersionedAssetId::from($crate::macros::AssetId(wnd.clone())),
$crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt.clone())),
]);
let program = $crate::macros::Xcm::<()>::builder()
.withdraw_asset(($crate::macros::Parent, 100u128))
.buy_execution(($crate::macros::Parent, 10u128), $crate::macros::Unlimited)
.deposit_asset($crate::macros::All, [0u8; 32])
.build();
let weight = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_xcm_weight(
$crate::macros::VersionedXcm::from(program)).unwrap();
let fee_in_wnd = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
$crate::macros::VersionedAssetId::from($crate::macros::AssetId(wnd.clone()))).unwrap();
// Assets not in a pool don't work.
assert!(<Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
$crate::macros::VersionedAssetId::from(
$crate::macros::AssetId($crate::macros::Location::new(0,
[$crate::macros::PalletInstance($crate::macros::ASSETS_PALLET_ID),
$crate::macros::GeneralIndex(1)]
)
)
)
).is_err());
let fee_in_usdt_fail = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
$crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt.clone())));
// Weight to asset fee fails because there's not enough asset in the pool.
// We just created it, there's none.
assert_eq!(fee_in_usdt_fail, Err($crate::macros::XcmPaymentApiError::AssetNotFound));
// We add some.
$crate::macros::assert_ok!(Assets::mint(
RuntimeOrigin::signed(sender.clone()),
$crate::macros::USDT_ID.into(),
sender.clone().into(),
5_000_000_000_000
));
// We make 1 ZGR = 4 USDT.
$crate::macros::assert_ok!(AssetConversion::add_liquidity(
RuntimeOrigin::signed(sender.clone()),
Box::new(wnd),
Box::new(usdt.clone()),
1_000_000_000_000,
4_000_000_000_000,
0,
0,
sender.into()
));
// Now it works.
let fee_in_usdt = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
$crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt))
);
$crate::macros::assert_ok!(fee_in_usdt);
assert!(fee_in_usdt.unwrap() > fee_in_wnd);
});
}
};
}
#[macro_export]
macro_rules! test_cross_chain_alias {
( vec![$( ($sender_para:ty, $receiver_para:ty, $is_teleport:expr, $expected_success:expr) ),+], $origin:expr, $target:expr, $fees:expr ) => {
$crate::macros::paste::paste! {
$(
{
let para_destination = <$sender_para as $crate::macros::Para>::sibling_location_of(
<$receiver_para as $crate::macros::Para>::para_id());
let account: $crate::macros::AccountId = $origin.clone().into();
$sender_para::fund_accounts(vec![(account.clone(), $fees * 10)]);
let total_fees: $crate::macros::Asset = ($crate::macros::Location::parent(), $fees).into();
let fees: $crate::macros::Asset = ($crate::macros::Location::parent(), $fees / 2).into();
let remote_fees = if $is_teleport {
Some($crate::macros::AssetTransferFilter::Teleport(fees.clone().into()))
} else {
let source_para_sa = <$receiver_para as $crate::macros::Para>::sovereign_account_id_of(
<$receiver_para as $crate::macros::Para>::sibling_location_of(
<$sender_para as $crate::macros::Para>::para_id()),
);
$receiver_para::fund_accounts(vec![(source_para_sa, $fees * 10)]);
Some($crate::macros::AssetTransferFilter::ReserveWithdraw(fees.clone().into()))
};
<$sender_para as $crate::macros::TestExt>::execute_with(|| {
type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
let xcm_message = $crate::macros::Xcm::<()>(vec![
$crate::macros::WithdrawAsset(total_fees.into()),
$crate::macros::PayFees { asset: fees.clone() },
$crate::macros::InitiateTransfer {
destination: para_destination,
remote_fees,
preserve_origin: true,
assets: $crate::macros::BoundedVec::new(),
remote_xcm: $crate::macros::Xcm(vec![
// try to alias into `account`
$crate::macros::AliasOrigin($target.clone().into()),
$crate::macros::RefundSurplus,
$crate::macros::DepositAsset {
assets: $crate::macros::Wild($crate::macros::AllCounted(1)),
beneficiary: $target.clone().into(),
},
]),
},
$crate::macros::RefundSurplus,
$crate::macros::DepositAsset { assets: $crate::macros::Wild($crate::macros::AllCounted(1)),
beneficiary: account.clone().into() },
]);
let signed_origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(account.into());
$crate::macros::assert_ok!(<$sender_para as [<$sender_para Pezpallet>]>::PezkuwiXcm::execute(
signed_origin,
Box::new($crate::macros::VersionedXcm::from(xcm_message.into())),
$crate::macros::Weight::MAX
));
$crate::macros::assert_expected_events!(
$sender_para,
vec![
RuntimeEvent::PezkuwiXcm($crate::macros::pezpallet_xcm::Event::Sent { .. }) => {},
]
);
});
<$receiver_para as $crate::macros::TestExt>::execute_with(|| {
type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$receiver_para,
vec![
RuntimeEvent::MessageQueue($crate::macros::pezpallet_message_queue::Event::Processed {
success, ..
}) => { success: *success == $expected_success, },
]
);
});
}
)+
}
};
}
/// note: $asset needs to be prefunded outside this function
#[macro_export]
macro_rules! create_pool_with_native_on {
( $chain:ident, $asset:expr, $is_foreign:expr, $asset_owner:expr ) => {
$crate::create_pool_with_native_on!(
$chain,
$asset,
$is_foreign,
$asset_owner,
1_000_000_000_000,
2_000_000_000_000
);
};
( $chain:ident, $asset:expr, $is_foreign:expr, $asset_owner:expr, $native_amount:expr, $asset_amount:expr ) => {
$crate::macros::paste::paste! {
<$chain as $crate::macros::TestExt>::execute_with(|| {
type RuntimeEvent = <$chain as $crate::macros::Chain>::RuntimeEvent;
let owner = $asset_owner;
let signed_owner = <$chain as $crate::macros::Chain>::RuntimeOrigin::signed(owner.clone());
let native_asset: $crate::macros::Location = $crate::macros::Parent.into();
if $is_foreign {
$crate::macros::assert_ok!(<$chain as [<$chain Pezpallet>]>::ForeignAssets::mint(
signed_owner.clone(),
$asset.clone().into(),
owner.clone().into(),
10_000_000_000_000, // For it to have more than enough.
));
} else {
let asset_id = match $asset.interior.last() {
Some($crate::macros::GeneralIndex(id)) => *id as u32,
_ => unreachable!(),
};
$crate::macros::assert_ok!(<$chain as [<$chain Pezpallet>]>::Assets::mint(
signed_owner.clone(),
asset_id.into(),
owner.clone().into(),
10_000_000_000_000, // For it to have more than enough.
));
}
$crate::macros::assert_ok!(<$chain as [<$chain Pezpallet>]>::AssetConversion::create_pool(
signed_owner.clone(),
Box::new(native_asset.clone()),
Box::new($asset.clone()),
));
$crate::macros::assert_expected_events!(
$chain,
vec![
RuntimeEvent::AssetConversion($crate::macros::pezpallet_asset_conversion::Event::PoolCreated { .. }) => {},
]
);
$crate::macros::assert_ok!(<$chain as [<$chain Pezpallet>]>::AssetConversion::add_liquidity(
signed_owner,
Box::new(native_asset),
Box::new($asset),
$native_amount,
$asset_amount,
0,
0,
owner.into()
));
$crate::macros::assert_expected_events!(
$chain,
vec![
RuntimeEvent::AssetConversion($crate::macros::pezpallet_asset_conversion::Event::LiquidityAdded { .. }) => {},
]
);
});
}
};
}
#[macro_export]
macro_rules! assert_whitelisted {
($chain:ident, $expected_call_hash:expr) => {
type RuntimeEvent = <$chain as $crate::macros::Chain>::RuntimeEvent;
$crate::macros::assert_expected_events!(
$chain,
vec![
RuntimeEvent::Whitelist($crate::macros::pezpallet_whitelist::Event::CallWhitelisted { call_hash }) => {
call_hash: *call_hash == $expected_call_hash,
},
]
);
};
}