1pub use paste;
17
18pub use frame_support::{pallet_prelude::Weight, weights::WeightToFee};
20pub use pallet_asset_conversion;
21pub use pallet_assets;
22pub use pallet_balances;
23pub use pallet_message_queue;
24pub use pallet_whitelist;
25pub use pallet_xcm;
26
27pub use frame_support::assert_ok;
28
29pub use polkadot_runtime_parachains::dmp::Pallet as Dmp;
31pub use xcm::{
32 latest::AssetTransferFilter,
33 prelude::{
34 AliasOrigin, All, AllCounted, Asset, AssetId, Assets, BuyExecution, DepositAsset,
35 ExpectTransactStatus, Fungible, GeneralIndex, Here, InitiateTransfer, Junction, Location,
36 MaybeErrorCode, OriginKind, Outcome, PalletInstance, Parachain, Parent, PayFees,
37 RefundSurplus, Transact, Unlimited, VersionedAssetId, VersionedAssets, VersionedLocation,
38 VersionedXcm, WeightLimit, Wild, WithdrawAsset, Xcm, XcmContext, XCM_VERSION,
39 },
40};
41
42pub use xcm_executor::traits::{DropAssets, TransferType};
43
44pub use asset_test_utils;
46pub use cumulus_pallet_xcmp_queue;
47pub use parachains_common::AccountId;
48pub use xcm_emulator::{
49 assert_expected_events, Chain, Parachain as Para, RelayChain, TestArgs, TestContext, TestExt,
50};
51
52pub use frame_support::{
53 dispatch::{GetDispatchInfo, RawOrigin},
54 BoundedVec,
55};
56pub use xcm_runtime_apis::{
57 dry_run::runtime_decl_for_dry_run_api::DryRunApiV2,
58 fees::{runtime_decl_for_xcm_payment_api::XcmPaymentApiV1, Error as XcmPaymentApiError},
59};
60
61pub use frame_support::traits::{fungible::Mutate, fungibles::Inspect, Currency};
62pub use sp_runtime::{traits::Dispatchable, AccountId32};
63
64pub use crate::{ASSETS_PALLET_ID, USDT_ID};
65
66#[macro_export]
67macro_rules! test_parachain_is_trusted_teleporter {
68 ( $sender_para:ty, vec![$( $receiver_para:ty ),+], ($assets:expr, $amount:expr), $xcm_call:ident ) => {
69 $crate::macros::paste::paste! {
70 let sender = [<$sender_para Sender>]::get();
72 let mut para_sender_balance_before =
73 <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
74 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
75 let fee_asset_item = 0;
76 let weight_limit = $crate::macros::WeightLimit::Unlimited;
77
78 $(
79 {
80 let receiver = [<$receiver_para Receiver>]::get();
82 let para_receiver_balance_before =
83 <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
84 let para_destination =
85 <$sender_para as $crate::macros::Para>::sibling_location_of(
86 <$receiver_para as $crate::macros::Para>::para_id());
87 let beneficiary: $crate::macros::Location =
88 $crate::macros::Junction::AccountId32 { network: None, id: receiver.clone().into() }.into();
89
90 let call = <$sender_para as $crate::macros::Chain>::RuntimeCall::PolkadotXcm(
92 $crate::macros::pallet_xcm::Call::$xcm_call {
93 dest: Box::new(para_destination.clone().into()),
94 beneficiary: Box::new(beneficiary.clone().into()),
95 assets: Box::new($assets.clone().into()),
96 fee_asset_item: fee_asset_item,
97 weight_limit: weight_limit.clone(),
98 });
99
100 let max_weight_with_margin_for_error = ($crate::macros::Weight::MAX.ref_time() / 100) * 90;
102 assert!(<_ as $crate::macros::GetDispatchInfo>::get_dispatch_info(&call)
103 .call_weight.ref_time() < max_weight_with_margin_for_error);
104
105 let mut delivery_fees_amount = 0;
106 let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm(Vec::new()));
107 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
108 type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
109 type OriginCaller = <$sender_para as $crate::macros::Chain>::OriginCaller;
110
111 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
112 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
113 $crate::macros::XCM_VERSION).unwrap();
114
115
116 let (destination_to_query, messages_to_query) = &result
118 .forwarded_xcms
119 .iter()
120 .find(|(destination, _)| {
121 *destination == $crate::macros::VersionedLocation::from($crate::macros::Location::new(1,
122 [$crate::macros::Parachain(<$receiver_para as $crate::macros::Para>::para_id().into())]))
123 })
124 .unwrap();
125 assert_eq!(messages_to_query.len(), 1);
126 remote_message = messages_to_query[0].clone();
127 let delivery_fees =
128 <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_delivery_fees(destination_to_query.clone(),
129 remote_message.clone()).unwrap();
130 let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
131 let $crate::macros::Fungible(inner_delivery_fees_amount) = latest_delivery_fees.inner()[0].fun else {
132 unreachable!("asset is non-fungible");
133 };
134 delivery_fees_amount = inner_delivery_fees_amount;
135 });
136
137 <$sender_para as $crate::macros::TestExt>::reset_ext();
139 <$receiver_para as $crate::macros::TestExt>::reset_ext();
140
141 <$sender_para as $crate::macros::TestExt>::execute_with(|| { });
145
146 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
148 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
149 $crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
150
151 type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
152
153 $crate::macros::assert_expected_events!(
154 $sender_para,
155 vec![
156 RuntimeEvent::PolkadotXcm(
157 $crate::macros::pallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
158 ) => {},
159 RuntimeEvent::XcmpQueue(
160 $crate::macros::cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }
161 ) => {},
162 RuntimeEvent::Balances(
163 $crate::macros::pallet_balances::Event::Burned { who: sender, amount }
164 ) => {},
165 ]
166 );
167 });
168
169 <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
171 type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
172
173 $crate::macros::assert_expected_events!(
174 $receiver_para,
175 vec![
176 RuntimeEvent::Balances(
177 $crate::macros::pallet_balances::Event::Minted { who: receiver, .. }
178 ) => {},
179 RuntimeEvent::MessageQueue(
180 $crate::macros::pallet_message_queue::Event::Processed { success: true, .. }
181 ) => {},
182 ]
183 );
184 });
185
186 let para_sender_balance_after =
188 <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
189 let para_receiver_balance_after =
190 <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
191
192 assert_eq!(para_sender_balance_before - $amount - delivery_fees_amount, para_sender_balance_after);
193 assert!(para_receiver_balance_after > para_receiver_balance_before);
194
195 para_sender_balance_before = <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
197 }
198 )+
199 }
200 };
201}
202
203#[macro_export]
204macro_rules! test_relay_is_trusted_teleporter {
205 ( $sender_relay:ty, vec![$( $receiver_para:ty ),+], ($assets:expr, $amount:expr), $xcm_call:ident ) => {
206 $crate::macros::paste::paste! {
207 let sender = [<$sender_relay Sender>]::get();
209 let mut relay_sender_balance_before =
210 <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free;
211 let fee_asset_item = 0;
212 let weight_limit = $crate::macros::WeightLimit::Unlimited;
213
214 $(
215 {
216 let receiver = [<$receiver_para Receiver>]::get();
218 let para_receiver_balance_before =
219 <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
220 let para_destination =
221 <$sender_relay as $crate::macros::RelayChain>::child_location_of(
222 <$receiver_para as $crate::macros::Para>::para_id());
223 let beneficiary: $crate::macros::Location =
224 $crate::macros::Junction::AccountId32 { network: None, id: receiver.clone().into() }.into();
225
226 let call = <$sender_relay as $crate::macros::Chain>::RuntimeCall::XcmPallet(
228 $crate::macros::pallet_xcm::Call::$xcm_call {
229 dest: Box::new(para_destination.clone().into()),
230 beneficiary: Box::new(beneficiary.clone().into()),
231 assets: Box::new($assets.clone().into()),
232 fee_asset_item: fee_asset_item,
233 weight_limit: weight_limit.clone(),
234 });
235
236 let max_weight_with_margin_for_error = ($crate::macros::Weight::MAX.ref_time() / 100) * 90;
239 assert!(<_ as $crate::macros::GetDispatchInfo>::get_dispatch_info(&call)
240 .call_weight.ref_time() < max_weight_with_margin_for_error);
241
242 let mut delivery_fees_amount = 0;
243 let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm(Vec::new()));
244 <$sender_relay as $crate::macros::TestExt>::execute_with(|| {
245 $crate::macros::Dmp::<<$sender_relay as $crate::macros::Chain>::Runtime>::make_parachain_reachable(
246 <$receiver_para as $crate::macros::Para>::para_id());
247 type Runtime = <$sender_relay as $crate::macros::Chain>::Runtime;
248 type OriginCaller = <$sender_relay as $crate::macros::Chain>::OriginCaller;
249
250 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
251 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
252 $crate::macros::XCM_VERSION).unwrap();
253 let (destination_to_query, messages_to_query) = &result
255 .forwarded_xcms
256 .iter()
257 .find(|(destination, _)| {
258 *destination == $crate::macros::VersionedLocation::from($crate::macros::Location::new(0,
259 [$crate::macros::Parachain(<$receiver_para as $crate::macros::Para>::para_id().into())]))
260 })
261 .unwrap();
262 assert_eq!(messages_to_query.len(), 1);
263 remote_message = messages_to_query[0].clone();
264 let delivery_fees =
265 <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_delivery_fees(destination_to_query.clone(),
266 remote_message.clone()).unwrap();
267 let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
268 let $crate::macros::Fungible(inner_delivery_fees_amount) = latest_delivery_fees.inner()[0].fun else {
269 unreachable!("asset is non-fungible");
270 };
271 delivery_fees_amount = inner_delivery_fees_amount;
272 });
273
274 <$sender_relay as $crate::macros::TestExt>::reset_ext();
276 <$receiver_para as $crate::macros::TestExt>::reset_ext();
277
278 <$sender_relay as $crate::macros::TestExt>::execute_with(|| {
280 $crate::macros::Dmp::<<$sender_relay as $crate::macros::Chain>::Runtime>::make_parachain_reachable(
281 <$receiver_para as $crate::macros::Para>::para_id());
282 let origin = <$sender_relay as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
283 $crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
284
285 type RuntimeEvent = <$sender_relay as $crate::macros::Chain>::RuntimeEvent;
286
287 $crate::macros::assert_expected_events!(
288 $sender_relay,
289 vec![
290 RuntimeEvent::XcmPallet(
291 $crate::macros::pallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
292 ) => {},
293 RuntimeEvent::Balances(
294 $crate::macros::pallet_balances::Event::Burned { who: sender, amount }
295 ) => {},
296 RuntimeEvent::XcmPallet(
297 $crate::macros::pallet_xcm::Event::Sent { .. }
298 ) => {},
299 ]
300 );
301 });
302
303 <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
305 type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
306
307 $crate::macros::assert_expected_events!(
308 $receiver_para,
309 vec![
310 RuntimeEvent::Balances(
311 $crate::macros::pallet_balances::Event::Minted { who: receiver, .. }
312 ) => {},
313 RuntimeEvent::MessageQueue(
314 $crate::macros::pallet_message_queue::Event::Processed { success: true, .. }
315 ) => {},
316 ]
317 );
318 });
319
320 let relay_sender_balance_after =
322 <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free;
323 let para_receiver_balance_after =
324 <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
325
326 assert_eq!(relay_sender_balance_before - $amount - delivery_fees_amount, relay_sender_balance_after);
327 assert!(para_receiver_balance_after > para_receiver_balance_before);
328
329 relay_sender_balance_before = <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free;
331 }
332 )+
333 }
334 };
335}
336
337#[macro_export]
338macro_rules! test_parachain_is_trusted_teleporter_for_relay {
339 ( $sender_para:ty, $receiver_relay:ty, $amount:expr, $xcm_call:ident ) => {
340 $crate::macros::paste::paste! {
341 let sender = [<$sender_para Sender>]::get();
343 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
345 $crate::macros::assert_ok!(<<$sender_para as [<$sender_para Pallet>]>::Balances
346 as $crate::macros::Mutate<_>>::mint_into(&sender, $amount + 10_000_000_000));
347
348 });
349 let mut para_sender_balance_before =
350 <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
351 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
352 let assets: $crate::macros::Assets = ($crate::macros::Parent, $amount).into();
353 let fee_asset_item = 0;
354 let weight_limit = $crate::macros::WeightLimit::Unlimited;
355
356 <$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
361 let check_account = <$receiver_relay as [<$receiver_relay Pallet>]>::XcmPallet::check_account();
362 $crate::macros::assert_ok!(<<$receiver_relay as [<$receiver_relay Pallet>]>::Balances
363 as $crate::macros::Mutate<_>>::mint_into(&check_account, $amount));
364 });
365
366 let receiver = [<$receiver_relay Receiver>]::get();
368 let relay_receiver_balance_before =
369 <$receiver_relay as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
370 let relay_destination: $crate::macros::Location = $crate::macros::Parent.into();
371 let beneficiary: $crate::macros::Location =
372 $crate::macros::Junction::AccountId32 { network: None, id: receiver.clone().into() }.into();
373
374 let call = <$sender_para as $crate::macros::Chain>::RuntimeCall::PolkadotXcm($crate::macros::pallet_xcm::Call::$xcm_call {
376 dest: Box::new(relay_destination.clone().into()),
377 beneficiary: Box::new(beneficiary.clone().into()),
378 assets: Box::new(assets.clone().into()),
379 fee_asset_item: fee_asset_item,
380 weight_limit: weight_limit.clone(),
381 });
382
383 let max_weight_with_margin_for_error = ($crate::macros::Weight::MAX.ref_time() / 100) * 90;
386 assert!(<_ as $crate::macros::GetDispatchInfo>::get_dispatch_info(&call)
387 .call_weight.ref_time() < max_weight_with_margin_for_error);
388
389 let mut delivery_fees_amount = 0;
391 let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm(Vec::new()));
392 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
393 type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
394 type OriginCaller = <$sender_para as $crate::macros::Chain>::OriginCaller;
395
396 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
397 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
398 $crate::macros::XCM_VERSION).unwrap();
399 let (destination_to_query, messages_to_query) = &result
401 .forwarded_xcms
402 .iter()
403 .find(|(destination, _)| {
404 *destination == $crate::macros::VersionedLocation::from($crate::macros::Location::parent())
405 })
406 .unwrap();
407 assert_eq!(messages_to_query.len(), 1);
408 remote_message = messages_to_query[0].clone();
409 let delivery_fees =
410 <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_delivery_fees(destination_to_query.clone(),
411 remote_message.clone()).unwrap();
412 let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
413 delivery_fees_amount = if let Some(first_asset) = latest_delivery_fees.inner().first() {
414 let $crate::macros::Fungible(inner_delivery_fees_amount) = first_asset.fun else {
415 unreachable!("asset is non-fungible");
416 };
417 inner_delivery_fees_amount
418 } else {
419 0
420 }
421 });
422
423 <$sender_para as $crate::macros::TestExt>::reset_ext();
425 <$receiver_relay as $crate::macros::TestExt>::reset_ext();
426 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
428 $crate::macros::assert_ok!(<<$sender_para as [<$sender_para Pallet>]>::Balances
429 as $crate::macros::Mutate<_>>::mint_into(&sender, $amount + 10_000_000_000));
430 });
431
432 <$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
434 let check_account = <$receiver_relay as [<$receiver_relay Pallet>]>::XcmPallet::check_account();
435 $crate::macros::assert_ok!(<<$receiver_relay as [<$receiver_relay Pallet>]>::Balances
436 as $crate::macros::Mutate<_>>::mint_into(&check_account, $amount));
437 });
438
439 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
441 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
442 $crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
443
444 type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
445
446 $crate::macros::assert_expected_events!(
447 $sender_para,
448 vec![
449 RuntimeEvent::PolkadotXcm(
450 $crate::macros::pallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
451 ) => {},
452 RuntimeEvent::Balances(
453 $crate::macros::pallet_balances::Event::Burned { who: sender, amount }
454 ) => {},
455 RuntimeEvent::PolkadotXcm(
456 $crate::macros::pallet_xcm::Event::Sent { .. }
457 ) => {},
458 ]
459 );
460 });
461
462 <$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
464 type RuntimeEvent = <$receiver_relay as $crate::macros::Chain>::RuntimeEvent;
465
466 $crate::macros::assert_expected_events!(
467 $receiver_relay,
468 vec![
469 RuntimeEvent::Balances(
470 $crate::macros::pallet_balances::Event::Minted { who: receiver, .. }
471 ) => {},
472 RuntimeEvent::MessageQueue(
473 $crate::macros::pallet_message_queue::Event::Processed { success: true, .. }
474 ) => {},
475 ]
476 );
477 });
478
479 let para_sender_balance_after =
481 <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
482 let relay_receiver_balance_after =
483 <$receiver_relay as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
484
485 assert_eq!(para_sender_balance_before - $amount - delivery_fees_amount, para_sender_balance_after);
486 assert!(relay_receiver_balance_after > relay_receiver_balance_before);
487
488 para_sender_balance_before = <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
490 }
491 };
492}
493
494#[macro_export]
495macro_rules! test_chain_can_claim_assets {
496 ( $sender_para:ty, $runtime_call:ty, $network_id:expr, $assets:expr, $amount:expr ) => {
497 $crate::macros::paste::paste! {
498 let sender = [<$sender_para Sender>]::get();
499 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
500 let beneficiary: $crate::macros::Location =
502 $crate::macros::Junction::AccountId32 { network: Some($network_id), id: sender.clone().into() }.into();
503 let versioned_assets: $crate::macros::VersionedAssets = $assets.clone().into();
504
505 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
506 <<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm as $crate::macros::DropAssets>::drop_assets(
509 &beneficiary,
510 $assets.clone().into(),
511 &$crate::macros::XcmContext { origin: None, message_id: [0u8; 32], topic: None },
512 );
513
514 type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
515 $crate::macros::assert_expected_events!(
516 $sender_para,
517 vec![
518 RuntimeEvent::PolkadotXcm(
519 $crate::macros::pallet_xcm::Event::AssetsTrapped { origin: beneficiary, assets: versioned_assets, .. }
520 ) => {},
521 ]
522 );
523
524 let balance_before = <<$sender_para as [<$sender_para Pallet>]>::Balances
525 as $crate::macros::Currency<_>>::free_balance(&sender);
526
527 let other_origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed([<$sender_para Receiver>]::get());
529 assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
530 other_origin,
531 Box::new(versioned_assets.clone().into()),
532 Box::new(beneficiary.clone().into()),
533 ).is_err());
534 let other_versioned_assets: $crate::macros::VersionedAssets = $crate::macros::Assets::new().into();
535 assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
536 origin.clone(),
537 Box::new(other_versioned_assets.into()),
538 Box::new(beneficiary.clone().into()),
539 ).is_err());
540
541 $crate::macros::assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
543 origin.clone(),
544 Box::new(versioned_assets.clone().into()),
545 Box::new(beneficiary.clone().into()),
546 ));
547
548 $crate::macros::assert_expected_events!(
549 $sender_para,
550 vec![
551 RuntimeEvent::PolkadotXcm(
552 $crate::macros::pallet_xcm::Event::AssetsClaimed { origin: beneficiary, assets: versioned_assets, .. }
553 ) => {},
554 ]
555 );
556
557 let balance_after = <<$sender_para as [<$sender_para Pallet>]>::Balances
559 as $crate::macros::Currency<_>>::free_balance(&sender);
560 assert_eq!(balance_after, balance_before + $amount);
561
562 assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
564 origin.clone(),
565 Box::new(versioned_assets.clone().into()),
566 Box::new(beneficiary.clone().into()),
567 ).is_err());
568
569 let balance = <<$sender_para as [<$sender_para Pallet>]>::Balances
570 as $crate::macros::Currency<_>>::free_balance(&sender);
571 assert_eq!(balance, balance_after);
572
573 <<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm as $crate::macros::DropAssets>::drop_assets(
575 &beneficiary,
576 $assets.clone().into(),
577 &$crate::macros::XcmContext { origin: None, message_id: [0u8; 32], topic: None },
578 );
579 let receiver = [<$sender_para Receiver>]::get();
580 let other_beneficiary: $crate::macros::Location =
581 $crate::macros::Junction::AccountId32 { network: Some($network_id), id: receiver.clone().into() }.into();
582 let balance_before = <<$sender_para as [<$sender_para Pallet>]>::Balances
583 as $crate::macros::Currency<_>>::free_balance(&receiver);
584 $crate::macros::assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
585 origin.clone(),
586 Box::new(versioned_assets.clone().into()),
587 Box::new(other_beneficiary.clone().into()),
588 ));
589 let balance_after = <<$sender_para as [<$sender_para Pallet>]>::Balances
590 as $crate::macros::Currency<_>>::free_balance(&receiver);
591 assert_eq!(balance_after, balance_before + $amount);
592 });
593 }
594 };
595}
596
597#[macro_export]
598macro_rules! test_can_estimate_and_pay_exact_fees {
599 ( $sender_para:ty, $asset_hub:ty, $receiver_para:ty, ($asset_id:expr, $amount:expr), $owner_prefix:ty ) => {
600 $crate::macros::paste::paste! {
601 fn get_call(
603 estimated_local_fees: impl Into<$crate::macros::Asset>,
604 estimated_intermediate_fees: impl Into<$crate::macros::Asset>,
605 estimated_remote_fees: impl Into<$crate::macros::Asset>,
606 ) -> <$sender_para as $crate::macros::Chain>::RuntimeCall {
607 type RuntimeCall = <$sender_para as $crate::macros::Chain>::RuntimeCall;
608
609 let beneficiary = [<$receiver_para Receiver>]::get();
610 let xcm_in_destination = $crate::macros::Xcm::<()>::builder_unsafe()
611 .pay_fees(estimated_remote_fees)
612 .deposit_asset($crate::macros::AllCounted(1), beneficiary)
613 .build();
614 let ah_to_receiver = <$asset_hub as $crate::macros::Para>::sibling_location_of(
615 <$receiver_para as $crate::macros::Para>::para_id());
616 let xcm_in_reserve = $crate::macros::Xcm::<()>::builder_unsafe()
617 .pay_fees(estimated_intermediate_fees)
618 .deposit_reserve_asset(
619 $crate::macros::AllCounted(1),
620 ah_to_receiver,
621 xcm_in_destination,
622 )
623 .build();
624 let sender_to_ah = <$sender_para as $crate::macros::Para>::sibling_location_of(
625 <$asset_hub as $crate::macros::Para>::para_id());
626 let local_xcm = $crate::macros::Xcm::<<$sender_para as $crate::macros::Chain>::RuntimeCall>::builder()
627 .withdraw_asset(($asset_id, $amount))
628 .pay_fees(estimated_local_fees)
629 .initiate_reserve_withdraw($crate::macros::AllCounted(1), sender_to_ah, xcm_in_reserve)
630 .build();
631
632 RuntimeCall::PolkadotXcm($crate::macros::pallet_xcm::Call::execute {
633 message: Box::new($crate::macros::VersionedXcm::from(local_xcm)),
634 max_weight: $crate::macros::Weight::from_parts(10_000_000_000, 500_000),
635 })
636 }
637
638 let destination = <$sender_para as $crate::macros::Para>::sibling_location_of(
639 <$receiver_para as $crate::macros::Para>::para_id());
640 let sender = [<$sender_para Sender>]::get();
641 let sender_as_seen_by_ah = <$asset_hub as $crate::macros::Para>::sibling_location_of(
642 <$sender_para as $crate::macros::Para>::para_id());
643 let sov_of_sender_on_ah = <$asset_hub as $crate::macros::Para>::sovereign_account_id_of(sender_as_seen_by_ah.clone());
644 let asset_owner = [<$owner_prefix AssetOwner>]::get();
645
646 $sender_para::mint_foreign_asset(
649 <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(asset_owner.clone()),
650 $asset_id.clone().into(),
651 sender.clone(),
652 $amount * 2,
653 );
654
655 $asset_hub::fund_accounts(vec![(sov_of_sender_on_ah.clone(), $amount * 2)]);
658
659 let beneficiary_id = [<$receiver_para Receiver>]::get();
660
661 let test_args = $crate::macros::TestContext {
662 sender: sender.clone(),
663 receiver: beneficiary_id.clone(),
664 args: $crate::macros::TestArgs::new_para(
665 destination,
666 beneficiary_id.clone(),
667 $amount,
668 ($asset_id, $amount).into(),
669 None,
670 0,
671 ),
672 };
673 let mut test = ParaToParaThroughAHTest::new(test_args);
674
675 let mut local_execution_fees = 0;
677 let mut local_delivery_fees = 0;
678 let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm::<()>(Vec::new()));
679 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
680 type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
681 type OriginCaller = <$sender_para as $crate::macros::Chain>::OriginCaller;
682
683 let call = get_call(
684 ($crate::macros::Parent, 100_000_000_000u128),
685 ($crate::macros::Parent, 100_000_000_000u128),
686 ($crate::macros::Parent, 100_000_000_000u128),
687 );
688 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
689 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
690 $crate::macros::XCM_VERSION).unwrap();
691 let local_xcm = result.local_xcm.unwrap().clone();
692 let local_xcm_weight = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_xcm_weight(local_xcm).unwrap();
693 local_execution_fees = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_weight_to_asset_fee(
694 local_xcm_weight,
695 $crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::parent())),
696 )
697 .unwrap();
698 let (destination_to_query, messages_to_query) = &result
700 .forwarded_xcms
701 .iter()
702 .find(|(destination, _)| {
703 *destination == $crate::macros::VersionedLocation::from(
704 $crate::macros::Location::new(1, [$crate::macros::Parachain(1000)]))
705 })
706 .unwrap();
707 assert_eq!(messages_to_query.len(), 1);
708 remote_message = messages_to_query[0].clone();
709 let delivery_fees =
710 <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_delivery_fees(destination_to_query.clone(),
711 remote_message.clone()).unwrap();
712 local_delivery_fees = $crate::xcm_helpers::get_amount_from_versioned_assets(delivery_fees);
713 });
714
715 let mut intermediate_execution_fees = 0;
717 let mut intermediate_delivery_fees = 0;
718 let mut intermediate_remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm::<()>(Vec::new()));
719 <$asset_hub as $crate::macros::TestExt>::execute_with(|| {
720 type Runtime = <$asset_hub as $crate::macros::Chain>::Runtime;
721 type RuntimeCall = <$asset_hub as $crate::macros::Chain>::RuntimeCall;
722
723 let weight = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_xcm_weight(remote_message.clone()).unwrap();
725 intermediate_execution_fees = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_weight_to_asset_fee(
726 weight,
727 $crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::new(1, []))),
728 )
729 .unwrap();
730
731 let xcm_program =
733 $crate::macros::VersionedXcm::from($crate::macros::Xcm::<RuntimeCall>::from(
734 remote_message.clone().try_into().unwrap()));
735
736 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_xcm(
738 sender_as_seen_by_ah.clone().into(), xcm_program).unwrap();
739 let (destination_to_query, messages_to_query) = &result
740 .forwarded_xcms
741 .iter()
742 .find(|(destination, _)| {
743 *destination == $crate::macros::VersionedLocation::from($crate::macros::Location::new(1,
744 [$crate::macros::Parachain(2001)]))
745 })
746 .unwrap();
747 intermediate_remote_message = messages_to_query[0].clone();
753 let delivery_fees = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_delivery_fees(
754 destination_to_query.clone(),
755 intermediate_remote_message.clone(),
756 )
757 .unwrap();
758 intermediate_delivery_fees = $crate::xcm_helpers::get_amount_from_versioned_assets(delivery_fees);
759 });
760
761 let mut final_execution_fees = 0;
763 <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
764 type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
765
766 let weight = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_xcm_weight(
767 intermediate_remote_message.clone()).unwrap();
768 final_execution_fees =
769 <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_weight_to_asset_fee(weight,
770 $crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::parent())))
771 .unwrap();
772 });
773
774 <$sender_para as $crate::macros::TestExt>::reset_ext();
776 <$asset_hub as $crate::macros::TestExt>::reset_ext();
777 <$receiver_para as $crate::macros::TestExt>::reset_ext();
778
779 $sender_para::mint_foreign_asset(
781 <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(asset_owner),
782 $asset_id.clone().into(),
783 sender.clone(),
784 $amount * 2,
785 );
786 $asset_hub::fund_accounts(vec![(sov_of_sender_on_ah, $amount * 2)]);
787
788 let sender_assets_before = <$sender_para as $crate::macros::TestExt>::execute_with(|| {
790 type ForeignAssets = <$sender_para as [<$sender_para Pallet>]>::ForeignAssets;
791 <ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &sender)
792 });
793 let receiver_assets_before = <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
794 type ForeignAssets = <$receiver_para as [<$receiver_para Pallet>]>::ForeignAssets;
795 <ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &beneficiary_id)
796 });
797
798 test.set_assertion::<$sender_para>(sender_assertions);
799 test.set_assertion::<$asset_hub>(hop_assertions);
800 test.set_assertion::<$receiver_para>(receiver_assertions);
801 let call = get_call(
802 ($crate::macros::Parent, local_execution_fees + local_delivery_fees),
803 ($crate::macros::Parent, intermediate_execution_fees + intermediate_delivery_fees),
804 ($crate::macros::Parent, final_execution_fees),
805 );
806 test.set_call(call);
807 test.assert();
808
809 let sender_assets_after = <$sender_para as $crate::macros::TestExt>::execute_with(|| {
810 type ForeignAssets = <$sender_para as [<$sender_para Pallet>]>::ForeignAssets;
811 <ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &sender)
812 });
813 let receiver_assets_after = <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
814 type ForeignAssets = <$receiver_para as [<$receiver_para Pallet>]>::ForeignAssets;
815 <ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.into(), &beneficiary_id)
816 });
817
818 assert_eq!(sender_assets_after, sender_assets_before - $amount);
820 assert_eq!(
821 receiver_assets_after,
822 receiver_assets_before + $amount -
823 local_execution_fees -
824 local_delivery_fees -
825 intermediate_execution_fees -
826 intermediate_delivery_fees -
827 final_execution_fees
828 );
829 }
830 };
831}
832
833#[macro_export]
834macro_rules! test_dry_run_transfer_across_pk_bridge {
835 ( $sender_asset_hub:ty, $sender_bridge_hub:ty, $destination:expr ) => {
836 $crate::macros::paste::paste! {
837
838 let who = $crate::macros::AccountId32::new([1u8; 32]);
839 let transfer_amount = 10_000_000_000_000u128;
840 let initial_balance = transfer_amount * 10;
841
842 $sender_asset_hub::force_xcm_version($destination, $crate::macros::XCM_VERSION);
844
845 <$sender_asset_hub as $crate::macros::TestExt>::execute_with(|| {
846 type Runtime = <$sender_asset_hub as $crate::macros::Chain>::Runtime;
847 type RuntimeCall = <$sender_asset_hub as $crate::macros::Chain>::RuntimeCall;
848 type OriginCaller = <$sender_asset_hub as $crate::macros::Chain>::OriginCaller;
849 type Balances = <$sender_asset_hub as [<$sender_asset_hub Pallet>]>::Balances;
850
851 <Balances as $crate::macros::Mutate<_>>::set_balance(&who, initial_balance);
853
854 let beneficiary: $crate::macros::Location = $crate::macros::Junction::AccountId32 {
855 id: who.clone().into(),
856 network: None,
857 }.into();
858
859 let call = RuntimeCall::PolkadotXcm($crate::macros::pallet_xcm::Call::transfer_assets_using_type_and_then {
860 dest: Box::new($crate::macros::VersionedLocation::from($destination)),
861 assets: Box::new($crate::macros::VersionedAssets::from(vec![
862 ($crate::macros::Parent, transfer_amount).into(),
863 ])),
864 assets_transfer_type: Box::new($crate::macros::TransferType::LocalReserve),
865 remote_fees_id: Box::new($crate::macros::VersionedAssetId::from($crate::macros::Parent)),
866 fees_transfer_type: Box::new($crate::macros::TransferType::LocalReserve),
867 custom_xcm_on_dest: Box::new($crate::macros::VersionedXcm::<()>::from($crate::macros::Xcm::<()>::builder_unsafe().deposit_asset(AllCounted(1), beneficiary).build())),
868 weight_limit: $crate::macros::Unlimited,
869 });
870 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(who));
871 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
872 $crate::macros::XCM_VERSION).unwrap();
873
874 assert!(result.execution_result.is_ok());
876 assert_eq!(result.forwarded_xcms.len(), 1);
877 assert_eq!(result.forwarded_xcms[0].0, $crate::macros::VersionedLocation::from(
878 $crate::macros::Location::new(1, [$crate::macros::Parachain(
879 <$sender_bridge_hub as $crate::macros::Para>::para_id().into())])));
880 });
881 }
882 };
883}
884
885#[macro_export]
886macro_rules! test_xcm_fee_querying_apis_work_for_asset_hub {
887 ( $asset_hub:ty ) => {
888 $crate::macros::paste::paste! {
889
890 <$asset_hub as $crate::macros::TestExt>::execute_with(|| {
891 type RuntimeOrigin = <$asset_hub as $crate::macros::Chain>::RuntimeOrigin;
893 type Assets = <$asset_hub as [<$asset_hub Pallet>]>::Assets;
894 type AssetConversion = <$asset_hub as [<$asset_hub Pallet>]>::AssetConversion;
895 let wnd = $crate::macros::Location::new(1, []);
896 let usdt = $crate::macros::Location::new(0, [$crate::macros::PalletInstance($crate::macros::ASSETS_PALLET_ID),
897 $crate::macros::GeneralIndex($crate::macros::USDT_ID.into())]);
898 let sender = [<$asset_hub Sender>]::get();
899 $crate::macros::assert_ok!(AssetConversion::create_pool(
900 RuntimeOrigin::signed(sender.clone()),
901 Box::new(wnd.clone()),
902 Box::new(usdt.clone()),
903 ));
904
905 type Runtime = <$asset_hub as $crate::macros::Chain>::Runtime;
906 let acceptable_payment_assets = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_acceptable_payment_assets(
907 $crate::macros::XCM_VERSION).unwrap();
908 assert_eq!(acceptable_payment_assets, vec![
909 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(wnd.clone())),
910 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt.clone())),
911 ]);
912
913 let program = $crate::macros::Xcm::<()>::builder()
914 .withdraw_asset(($crate::macros::Parent, 100u128))
915 .buy_execution(($crate::macros::Parent, 10u128), $crate::macros::Unlimited)
916 .deposit_asset($crate::macros::All, [0u8; 32])
917 .build();
918 let weight = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_xcm_weight(
919 $crate::macros::VersionedXcm::from(program)).unwrap();
920 let fee_in_wnd = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_weight_to_asset_fee(weight,
921 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(wnd.clone()))).unwrap();
922 assert!(<Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_weight_to_asset_fee(weight,
924 $crate::macros::VersionedAssetId::from(
925 $crate::macros::AssetId($crate::macros::Location::new(0,
926 [$crate::macros::PalletInstance($crate::macros::ASSETS_PALLET_ID),
927 $crate::macros::GeneralIndex(1)]
928 )
929 )
930 )
931 ).is_err());
932 let fee_in_usdt_fail = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_weight_to_asset_fee(weight,
933 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt.clone())));
934 assert_eq!(fee_in_usdt_fail, Err($crate::macros::XcmPaymentApiError::AssetNotFound));
937 $crate::macros::assert_ok!(Assets::mint(
939 RuntimeOrigin::signed(sender.clone()),
940 $crate::macros::USDT_ID.into(),
941 sender.clone().into(),
942 5_000_000_000_000
943 ));
944 $crate::macros::assert_ok!(AssetConversion::add_liquidity(
946 RuntimeOrigin::signed(sender.clone()),
947 Box::new(wnd),
948 Box::new(usdt.clone()),
949 1_000_000_000_000,
950 4_000_000_000_000,
951 0,
952 0,
953 sender.into()
954 ));
955 let fee_in_usdt = <Runtime as $crate::macros::XcmPaymentApiV1<_>>::query_weight_to_asset_fee(weight,
957 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt))
958 );
959 $crate::macros::assert_ok!(fee_in_usdt);
960 assert!(fee_in_usdt.unwrap() > fee_in_wnd);
961 });
962 }
963 };
964}
965
966#[macro_export]
967macro_rules! test_cross_chain_alias {
968 ( vec![$( ($sender_para:ty, $receiver_para:ty, $is_teleport:expr, $expected_success:expr) ),+], $origin:expr, $target:expr, $fees:expr ) => {
969 $crate::macros::paste::paste! {
970 $(
971 {
972 let para_destination = <$sender_para as $crate::macros::Para>::sibling_location_of(
973 <$receiver_para as $crate::macros::Para>::para_id());
974 let account: $crate::macros::AccountId = $origin.clone().into();
975 $sender_para::fund_accounts(vec![(account.clone(), $fees * 10)]);
976 let total_fees: $crate::macros::Asset = ($crate::macros::Location::parent(), $fees).into();
977 let fees: $crate::macros::Asset = ($crate::macros::Location::parent(), $fees / 2).into();
978
979 let remote_fees = if $is_teleport {
980 Some($crate::macros::AssetTransferFilter::Teleport(fees.clone().into()))
981 } else {
982 let source_para_sa = <$receiver_para as $crate::macros::Para>::sovereign_account_id_of(
983 <$receiver_para as $crate::macros::Para>::sibling_location_of(
984 <$sender_para as $crate::macros::Para>::para_id()),
985 );
986 $receiver_para::fund_accounts(vec![(source_para_sa, $fees * 10)]);
987 Some($crate::macros::AssetTransferFilter::ReserveWithdraw(fees.clone().into()))
988 };
989 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
990 type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
991 let xcm_message = $crate::macros::Xcm::<()>(vec![
992 $crate::macros::WithdrawAsset(total_fees.into()),
993 $crate::macros::PayFees { asset: fees.clone() },
994 $crate::macros::InitiateTransfer {
995 destination: para_destination,
996 remote_fees,
997 preserve_origin: true,
998 assets: $crate::macros::BoundedVec::new(),
999 remote_xcm: $crate::macros::Xcm(vec![
1000 $crate::macros::AliasOrigin($target.clone().into()),
1002 $crate::macros::RefundSurplus,
1003 $crate::macros::DepositAsset {
1004 assets: $crate::macros::Wild($crate::macros::AllCounted(1)),
1005 beneficiary: $target.clone().into(),
1006 },
1007 ]),
1008 },
1009 $crate::macros::RefundSurplus,
1010 $crate::macros::DepositAsset { assets: $crate::macros::Wild($crate::macros::AllCounted(1)),
1011 beneficiary: account.clone().into() },
1012 ]);
1013
1014 let signed_origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(account.into());
1015 $crate::macros::assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::execute(
1016 signed_origin,
1017 Box::new($crate::macros::VersionedXcm::from(xcm_message.into())),
1018 $crate::macros::Weight::MAX
1019 ));
1020 $crate::macros::assert_expected_events!(
1021 $sender_para,
1022 vec![
1023 RuntimeEvent::PolkadotXcm($crate::macros::pallet_xcm::Event::Sent { .. }) => {},
1024 ]
1025 );
1026 });
1027
1028 <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
1029 type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
1030 $crate::macros::assert_expected_events!(
1031 $receiver_para,
1032 vec![
1033 RuntimeEvent::MessageQueue($crate::macros::pallet_message_queue::Event::Processed {
1034 success, ..
1035 }) => { success: *success == $expected_success, },
1036 ]
1037 );
1038 });
1039 }
1040 )+
1041 }
1042 };
1043}
1044
1045#[macro_export]
1047macro_rules! create_pool_with_native_on {
1048 ( $chain:ident, $asset:expr, $is_foreign:expr, $asset_owner:expr ) => {
1049 $crate::create_pool_with_native_on!(
1050 $chain,
1051 $asset,
1052 $is_foreign,
1053 $asset_owner,
1054 1_000_000_000_000,
1055 2_000_000_000_000
1056 );
1057 };
1058
1059 ( $chain:ident, $asset:expr, $is_foreign:expr, $asset_owner:expr, $native_amount:expr, $asset_amount:expr ) => {
1060 $crate::macros::paste::paste! {
1061 <$chain as $crate::macros::TestExt>::execute_with(|| {
1062 type RuntimeEvent = <$chain as $crate::macros::Chain>::RuntimeEvent;
1063 let owner = $asset_owner;
1064 let signed_owner = <$chain as $crate::macros::Chain>::RuntimeOrigin::signed(owner.clone());
1065 let native_asset: $crate::macros::Location = $crate::macros::Parent.into();
1066
1067 if $is_foreign {
1068 $crate::macros::assert_ok!(<$chain as [<$chain Pallet>]>::ForeignAssets::mint(
1069 signed_owner.clone(),
1070 $asset.clone().into(),
1071 owner.clone().into(),
1072 10_000_000_000_000, ));
1074 } else {
1075 let asset_id = match $asset.interior.last() {
1076 Some($crate::macros::GeneralIndex(id)) => *id as u32,
1077 _ => unreachable!(),
1078 };
1079 $crate::macros::assert_ok!(<$chain as [<$chain Pallet>]>::Assets::mint(
1080 signed_owner.clone(),
1081 asset_id.into(),
1082 owner.clone().into(),
1083 10_000_000_000_000, ));
1085 }
1086
1087 $crate::macros::assert_ok!(<$chain as [<$chain Pallet>]>::AssetConversion::create_pool(
1088 signed_owner.clone(),
1089 Box::new(native_asset.clone()),
1090 Box::new($asset.clone()),
1091 ));
1092
1093 $crate::macros::assert_expected_events!(
1094 $chain,
1095 vec![
1096 RuntimeEvent::AssetConversion($crate::macros::pallet_asset_conversion::Event::PoolCreated { .. }) => {},
1097 ]
1098 );
1099
1100 $crate::macros::assert_ok!(<$chain as [<$chain Pallet>]>::AssetConversion::add_liquidity(
1101 signed_owner,
1102 Box::new(native_asset),
1103 Box::new($asset),
1104 $native_amount,
1105 $asset_amount,
1106 0,
1107 0,
1108 owner.into()
1109 ));
1110
1111 $crate::macros::assert_expected_events!(
1112 $chain,
1113 vec![
1114 RuntimeEvent::AssetConversion($crate::macros::pallet_asset_conversion::Event::LiquidityAdded { .. }) => {},
1115 ]
1116 );
1117 });
1118 }
1119 };
1120}
1121
1122#[macro_export]
1123macro_rules! assert_whitelisted {
1124 ($chain:ident, $expected_call_hash:expr) => {
1125 type RuntimeEvent = <$chain as $crate::macros::Chain>::RuntimeEvent;
1126 $crate::macros::assert_expected_events!(
1127 $chain,
1128 vec![
1129 RuntimeEvent::Whitelist($crate::macros::pallet_whitelist::Event::CallWhitelisted { call_hash }) => {
1130 call_hash: *call_hash == $expected_call_hash,
1131 },
1132 ]
1133 );
1134 };
1135}