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::XcmPaymentApiV2, 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 asset_id_for_delivery_fees = VersionedAssetId::from(Location::new(1, []));
130 let delivery_fees =
131 <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
132 destination_to_query.clone(),
133 remote_message.clone(),
134 asset_id_for_delivery_fees
135 ).unwrap();
136 let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
137 let $crate::macros::Fungible(inner_delivery_fees_amount) = latest_delivery_fees.inner()[0].fun else {
138 unreachable!("asset is non-fungible");
139 };
140 delivery_fees_amount = inner_delivery_fees_amount;
141 });
142
143 <$sender_para as $crate::macros::TestExt>::reset_ext();
145 <$receiver_para as $crate::macros::TestExt>::reset_ext();
146
147 <$sender_para as $crate::macros::TestExt>::execute_with(|| { });
151
152 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
154 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
155 $crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
156
157 type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
158
159 $crate::macros::assert_expected_events!(
160 $sender_para,
161 vec![
162 RuntimeEvent::PolkadotXcm(
163 $crate::macros::pallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
164 ) => {},
165 RuntimeEvent::XcmpQueue(
166 $crate::macros::cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }
167 ) => {},
168 RuntimeEvent::Balances(
169 $crate::macros::pallet_balances::Event::Burned { who: sender, amount }
170 ) => {},
171 ]
172 );
173 });
174
175 <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
177 type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
178
179 $crate::macros::assert_expected_events!(
180 $receiver_para,
181 vec![
182 RuntimeEvent::Balances(
183 $crate::macros::pallet_balances::Event::Minted { who: receiver, .. }
184 ) => {},
185 RuntimeEvent::MessageQueue(
186 $crate::macros::pallet_message_queue::Event::Processed { success: true, .. }
187 ) => {},
188 ]
189 );
190 });
191
192 let para_sender_balance_after =
194 <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
195 let para_receiver_balance_after =
196 <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
197
198 assert_eq!(para_sender_balance_before - $amount - delivery_fees_amount, para_sender_balance_after);
199 assert!(para_receiver_balance_after > para_receiver_balance_before);
200
201 para_sender_balance_before = <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
203 }
204 )+
205 }
206 };
207}
208
209#[macro_export]
210macro_rules! test_relay_is_trusted_teleporter {
211 ( $sender_relay:ty, vec![$( $receiver_para:ty ),+], ($assets:expr, $amount:expr), $xcm_call:ident ) => {
212 $crate::macros::paste::paste! {
213 let sender = [<$sender_relay Sender>]::get();
215 let mut relay_sender_balance_before =
216 <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free;
217 let fee_asset_item = 0;
218 let weight_limit = $crate::macros::WeightLimit::Unlimited;
219
220 $(
221 {
222 let receiver = [<$receiver_para Receiver>]::get();
224 let para_receiver_balance_before =
225 <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
226 let para_destination =
227 <$sender_relay as $crate::macros::RelayChain>::child_location_of(
228 <$receiver_para as $crate::macros::Para>::para_id());
229 let beneficiary: $crate::macros::Location =
230 $crate::macros::Junction::AccountId32 { network: None, id: receiver.clone().into() }.into();
231
232 let call = <$sender_relay as $crate::macros::Chain>::RuntimeCall::XcmPallet(
234 $crate::macros::pallet_xcm::Call::$xcm_call {
235 dest: Box::new(para_destination.clone().into()),
236 beneficiary: Box::new(beneficiary.clone().into()),
237 assets: Box::new($assets.clone().into()),
238 fee_asset_item: fee_asset_item,
239 weight_limit: weight_limit.clone(),
240 });
241
242 let max_weight_with_margin_for_error = ($crate::macros::Weight::MAX.ref_time() / 100) * 90;
245 assert!(<_ as $crate::macros::GetDispatchInfo>::get_dispatch_info(&call)
246 .call_weight.ref_time() < max_weight_with_margin_for_error);
247
248 let mut delivery_fees_amount = 0;
249 let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm(Vec::new()));
250 <$sender_relay as $crate::macros::TestExt>::execute_with(|| {
251 $crate::macros::Dmp::<<$sender_relay as $crate::macros::Chain>::Runtime>::make_parachain_reachable(
252 <$receiver_para as $crate::macros::Para>::para_id());
253 type Runtime = <$sender_relay as $crate::macros::Chain>::Runtime;
254 type OriginCaller = <$sender_relay as $crate::macros::Chain>::OriginCaller;
255
256 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
257 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
258 $crate::macros::XCM_VERSION).unwrap();
259 let (destination_to_query, messages_to_query) = &result
261 .forwarded_xcms
262 .iter()
263 .find(|(destination, _)| {
264 *destination == $crate::macros::VersionedLocation::from($crate::macros::Location::new(0,
265 [$crate::macros::Parachain(<$receiver_para as $crate::macros::Para>::para_id().into())]))
266 })
267 .unwrap();
268 assert_eq!(messages_to_query.len(), 1);
269 remote_message = messages_to_query[0].clone();
270 let asset_id_for_delivery_fees = VersionedAssetId::from(Location::new(0, []));
273 let delivery_fees =
274 <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
275 destination_to_query.clone(),
276 remote_message.clone(),
277 asset_id_for_delivery_fees
278 ).unwrap();
279 let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
280 let $crate::macros::Fungible(inner_delivery_fees_amount) = latest_delivery_fees.inner()[0].fun else {
281 unreachable!("asset is non-fungible");
282 };
283 delivery_fees_amount = inner_delivery_fees_amount;
284 });
285
286 <$sender_relay as $crate::macros::TestExt>::reset_ext();
288 <$receiver_para as $crate::macros::TestExt>::reset_ext();
289
290 <$sender_relay as $crate::macros::TestExt>::execute_with(|| {
292 $crate::macros::Dmp::<<$sender_relay as $crate::macros::Chain>::Runtime>::make_parachain_reachable(
293 <$receiver_para as $crate::macros::Para>::para_id());
294 let origin = <$sender_relay as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
295 $crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
296
297 type RuntimeEvent = <$sender_relay as $crate::macros::Chain>::RuntimeEvent;
298
299 $crate::macros::assert_expected_events!(
300 $sender_relay,
301 vec![
302 RuntimeEvent::XcmPallet(
303 $crate::macros::pallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
304 ) => {},
305 RuntimeEvent::Balances(
306 $crate::macros::pallet_balances::Event::Burned { who: sender, amount }
307 ) => {},
308 RuntimeEvent::XcmPallet(
309 $crate::macros::pallet_xcm::Event::Sent { .. }
310 ) => {},
311 ]
312 );
313 });
314
315 <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
317 type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
318
319 $crate::macros::assert_expected_events!(
320 $receiver_para,
321 vec![
322 RuntimeEvent::Balances(
323 $crate::macros::pallet_balances::Event::Minted { who: receiver, .. }
324 ) => {},
325 RuntimeEvent::MessageQueue(
326 $crate::macros::pallet_message_queue::Event::Processed { success: true, .. }
327 ) => {},
328 ]
329 );
330 });
331
332 let relay_sender_balance_after =
334 <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free;
335 let para_receiver_balance_after =
336 <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
337
338 assert_eq!(relay_sender_balance_before - $amount - delivery_fees_amount, relay_sender_balance_after);
339 assert!(para_receiver_balance_after > para_receiver_balance_before);
340
341 relay_sender_balance_before = <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free;
343 }
344 )+
345 }
346 };
347}
348
349#[macro_export]
350macro_rules! test_parachain_is_trusted_teleporter_for_relay {
351 ( $sender_para:ty, $receiver_relay:ty, $amount:expr, $xcm_call:ident ) => {
352 $crate::macros::paste::paste! {
353 let sender = [<$sender_para Sender>]::get();
355 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
357 $crate::macros::assert_ok!(<<$sender_para as [<$sender_para Pallet>]>::Balances
358 as $crate::macros::Mutate<_>>::mint_into(&sender, $amount + 10_000_000_000));
359
360 });
361 let mut para_sender_balance_before =
362 <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
363 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
364 let assets: $crate::macros::Assets = ($crate::macros::Parent, $amount).into();
365 let fee_asset_item = 0;
366 let weight_limit = $crate::macros::WeightLimit::Unlimited;
367
368 <$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
373 let check_account = <$receiver_relay as [<$receiver_relay Pallet>]>::XcmPallet::check_account();
374 $crate::macros::assert_ok!(<<$receiver_relay as [<$receiver_relay Pallet>]>::Balances
375 as $crate::macros::Mutate<_>>::mint_into(&check_account, $amount));
376 });
377
378 let receiver = [<$receiver_relay Receiver>]::get();
380 let relay_receiver_balance_before =
381 <$receiver_relay as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
382 let relay_destination: $crate::macros::Location = $crate::macros::Parent.into();
383 let beneficiary: $crate::macros::Location =
384 $crate::macros::Junction::AccountId32 { network: None, id: receiver.clone().into() }.into();
385
386 let call = <$sender_para as $crate::macros::Chain>::RuntimeCall::PolkadotXcm($crate::macros::pallet_xcm::Call::$xcm_call {
388 dest: Box::new(relay_destination.clone().into()),
389 beneficiary: Box::new(beneficiary.clone().into()),
390 assets: Box::new(assets.clone().into()),
391 fee_asset_item: fee_asset_item,
392 weight_limit: weight_limit.clone(),
393 });
394
395 let max_weight_with_margin_for_error = ($crate::macros::Weight::MAX.ref_time() / 100) * 90;
398 assert!(<_ as $crate::macros::GetDispatchInfo>::get_dispatch_info(&call)
399 .call_weight.ref_time() < max_weight_with_margin_for_error);
400
401 let mut delivery_fees_amount = 0;
403 let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm(Vec::new()));
404 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
405 type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
406 type OriginCaller = <$sender_para as $crate::macros::Chain>::OriginCaller;
407
408 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
409 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
410 $crate::macros::XCM_VERSION).unwrap();
411 let (destination_to_query, messages_to_query) = &result
413 .forwarded_xcms
414 .iter()
415 .find(|(destination, _)| {
416 *destination == $crate::macros::VersionedLocation::from($crate::macros::Location::parent())
417 })
418 .unwrap();
419 assert_eq!(messages_to_query.len(), 1);
420 remote_message = messages_to_query[0].clone();
421 let asset_id_for_delivery_fees = VersionedAssetId::from(Location::parent());
424 let delivery_fees =
425 <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
426 destination_to_query.clone(),
427 remote_message.clone(),
428 asset_id_for_delivery_fees
429 ).unwrap();
430 let latest_delivery_fees: $crate::macros::Assets = delivery_fees.clone().try_into().unwrap();
431 delivery_fees_amount = if let Some(first_asset) = latest_delivery_fees.inner().first() {
432 let $crate::macros::Fungible(inner_delivery_fees_amount) = first_asset.fun else {
433 unreachable!("asset is non-fungible");
434 };
435 inner_delivery_fees_amount
436 } else {
437 0
438 }
439 });
440
441 <$sender_para as $crate::macros::TestExt>::reset_ext();
443 <$receiver_relay as $crate::macros::TestExt>::reset_ext();
444 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
446 $crate::macros::assert_ok!(<<$sender_para as [<$sender_para Pallet>]>::Balances
447 as $crate::macros::Mutate<_>>::mint_into(&sender, $amount + 10_000_000_000));
448 });
449
450 <$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
452 let check_account = <$receiver_relay as [<$receiver_relay Pallet>]>::XcmPallet::check_account();
453 $crate::macros::assert_ok!(<<$receiver_relay as [<$receiver_relay Pallet>]>::Balances
454 as $crate::macros::Mutate<_>>::mint_into(&check_account, $amount));
455 });
456
457 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
459 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
460 $crate::macros::assert_ok!(<_ as $crate::macros::Dispatchable>::dispatch(call, origin));
461
462 type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
463
464 $crate::macros::assert_expected_events!(
465 $sender_para,
466 vec![
467 RuntimeEvent::PolkadotXcm(
468 $crate::macros::pallet_xcm::Event::Attempted { outcome: $crate::macros::Outcome::Complete { .. } }
469 ) => {},
470 RuntimeEvent::Balances(
471 $crate::macros::pallet_balances::Event::Burned { who: sender, amount }
472 ) => {},
473 RuntimeEvent::PolkadotXcm(
474 $crate::macros::pallet_xcm::Event::Sent { .. }
475 ) => {},
476 ]
477 );
478 });
479
480 <$receiver_relay as $crate::macros::TestExt>::execute_with(|| {
482 type RuntimeEvent = <$receiver_relay as $crate::macros::Chain>::RuntimeEvent;
483
484 $crate::macros::assert_expected_events!(
485 $receiver_relay,
486 vec![
487 RuntimeEvent::Balances(
488 $crate::macros::pallet_balances::Event::Minted { who: receiver, .. }
489 ) => {},
490 RuntimeEvent::MessageQueue(
491 $crate::macros::pallet_message_queue::Event::Processed { success: true, .. }
492 ) => {},
493 ]
494 );
495 });
496
497 let para_sender_balance_after =
499 <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
500 let relay_receiver_balance_after =
501 <$receiver_relay as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
502
503 assert_eq!(para_sender_balance_before - $amount - delivery_fees_amount, para_sender_balance_after);
504 assert!(relay_receiver_balance_after > relay_receiver_balance_before);
505
506 para_sender_balance_before = <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free;
508 }
509 };
510}
511
512#[macro_export]
513macro_rules! test_chain_can_claim_assets {
514 ( $sender_para:ty, $runtime_call:ty, $network_id:expr, $assets:expr, $amount:expr ) => {
515 $crate::macros::paste::paste! {
516 let sender = [<$sender_para Sender>]::get();
517 let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone());
518 let beneficiary: $crate::macros::Location =
520 $crate::macros::Junction::AccountId32 { network: Some($network_id), id: sender.clone().into() }.into();
521 let versioned_assets: $crate::macros::VersionedAssets = $assets.clone().into();
522
523 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
524 <<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm as $crate::macros::DropAssets>::drop_assets(
527 &beneficiary,
528 $assets.clone().into(),
529 &$crate::macros::XcmContext { origin: None, message_id: [0u8; 32], topic: None },
530 );
531
532 type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
533 $crate::macros::assert_expected_events!(
534 $sender_para,
535 vec![
536 RuntimeEvent::PolkadotXcm(
537 $crate::macros::pallet_xcm::Event::AssetsTrapped { origin: beneficiary, assets: versioned_assets, .. }
538 ) => {},
539 ]
540 );
541
542 let balance_before = <<$sender_para as [<$sender_para Pallet>]>::Balances
543 as $crate::macros::Currency<_>>::free_balance(&sender);
544
545 let other_origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed([<$sender_para Receiver>]::get());
547 assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
548 other_origin,
549 Box::new(versioned_assets.clone().into()),
550 Box::new(beneficiary.clone().into()),
551 ).is_err());
552 let other_versioned_assets: $crate::macros::VersionedAssets = $crate::macros::Assets::new().into();
553 assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
554 origin.clone(),
555 Box::new(other_versioned_assets.into()),
556 Box::new(beneficiary.clone().into()),
557 ).is_err());
558
559 $crate::macros::assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
561 origin.clone(),
562 Box::new(versioned_assets.clone().into()),
563 Box::new(beneficiary.clone().into()),
564 ));
565
566 $crate::macros::assert_expected_events!(
567 $sender_para,
568 vec![
569 RuntimeEvent::PolkadotXcm(
570 $crate::macros::pallet_xcm::Event::AssetsClaimed { origin: beneficiary, assets: versioned_assets, .. }
571 ) => {},
572 ]
573 );
574
575 let balance_after = <<$sender_para as [<$sender_para Pallet>]>::Balances
577 as $crate::macros::Currency<_>>::free_balance(&sender);
578 assert_eq!(balance_after, balance_before + $amount);
579
580 assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
582 origin.clone(),
583 Box::new(versioned_assets.clone().into()),
584 Box::new(beneficiary.clone().into()),
585 ).is_err());
586
587 let balance = <<$sender_para as [<$sender_para Pallet>]>::Balances
588 as $crate::macros::Currency<_>>::free_balance(&sender);
589 assert_eq!(balance, balance_after);
590
591 <<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm as $crate::macros::DropAssets>::drop_assets(
593 &beneficiary,
594 $assets.clone().into(),
595 &$crate::macros::XcmContext { origin: None, message_id: [0u8; 32], topic: None },
596 );
597 let receiver = [<$sender_para Receiver>]::get();
598 let other_beneficiary: $crate::macros::Location =
599 $crate::macros::Junction::AccountId32 { network: Some($network_id), id: receiver.clone().into() }.into();
600 let balance_before = <<$sender_para as [<$sender_para Pallet>]>::Balances
601 as $crate::macros::Currency<_>>::free_balance(&receiver);
602 $crate::macros::assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets(
603 origin.clone(),
604 Box::new(versioned_assets.clone().into()),
605 Box::new(other_beneficiary.clone().into()),
606 ));
607 let balance_after = <<$sender_para as [<$sender_para Pallet>]>::Balances
608 as $crate::macros::Currency<_>>::free_balance(&receiver);
609 assert_eq!(balance_after, balance_before + $amount);
610 });
611 }
612 };
613}
614
615#[macro_export]
616macro_rules! test_can_estimate_and_pay_exact_fees {
617 ( $sender_para:ty, $asset_hub:ty, $receiver_para:ty, ($asset_id:expr, $amount:expr), $owner_prefix:ty ) => {
618 $crate::macros::paste::paste! {
619 fn get_call(
621 estimated_local_fees: impl Into<$crate::macros::Asset>,
622 estimated_intermediate_fees: impl Into<$crate::macros::Asset>,
623 estimated_remote_fees: impl Into<$crate::macros::Asset>,
624 ) -> <$sender_para as $crate::macros::Chain>::RuntimeCall {
625 type RuntimeCall = <$sender_para as $crate::macros::Chain>::RuntimeCall;
626
627 let beneficiary = [<$receiver_para Receiver>]::get();
628 let xcm_in_destination = $crate::macros::Xcm::<()>::builder_unsafe()
629 .pay_fees(estimated_remote_fees)
630 .deposit_asset($crate::macros::AllCounted(1), beneficiary)
631 .build();
632 let ah_to_receiver = <$asset_hub as $crate::macros::Para>::sibling_location_of(
633 <$receiver_para as $crate::macros::Para>::para_id());
634 let xcm_in_reserve = $crate::macros::Xcm::<()>::builder_unsafe()
635 .pay_fees(estimated_intermediate_fees)
636 .deposit_reserve_asset(
637 $crate::macros::AllCounted(1),
638 ah_to_receiver,
639 xcm_in_destination,
640 )
641 .build();
642 let sender_to_ah = <$sender_para as $crate::macros::Para>::sibling_location_of(
643 <$asset_hub as $crate::macros::Para>::para_id());
644 let local_xcm = $crate::macros::Xcm::<<$sender_para as $crate::macros::Chain>::RuntimeCall>::builder()
645 .withdraw_asset(($asset_id, $amount))
646 .pay_fees(estimated_local_fees)
647 .initiate_reserve_withdraw($crate::macros::AllCounted(1), sender_to_ah, xcm_in_reserve)
648 .build();
649
650 RuntimeCall::PolkadotXcm($crate::macros::pallet_xcm::Call::execute {
651 message: Box::new($crate::macros::VersionedXcm::from(local_xcm)),
652 max_weight: $crate::macros::Weight::from_parts(10_000_000_000, 500_000),
653 })
654 }
655
656 let destination = <$sender_para as $crate::macros::Para>::sibling_location_of(
657 <$receiver_para as $crate::macros::Para>::para_id());
658 let sender = [<$sender_para Sender>]::get();
659 let sender_as_seen_by_ah = <$asset_hub as $crate::macros::Para>::sibling_location_of(
660 <$sender_para as $crate::macros::Para>::para_id());
661 let sov_of_sender_on_ah = <$asset_hub as $crate::macros::Para>::sovereign_account_id_of(sender_as_seen_by_ah.clone());
662 let asset_owner = [<$owner_prefix AssetOwner>]::get();
663
664 $sender_para::mint_foreign_asset(
667 <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(asset_owner.clone()),
668 $asset_id.clone().into(),
669 sender.clone(),
670 $amount * 2,
671 );
672
673 $asset_hub::fund_accounts(vec![(sov_of_sender_on_ah.clone(), $amount * 2)]);
676
677 let beneficiary_id = [<$receiver_para Receiver>]::get();
678
679 let test_args = $crate::macros::TestContext {
680 sender: sender.clone(),
681 receiver: beneficiary_id.clone(),
682 args: $crate::macros::TestArgs::new_para(
683 destination,
684 beneficiary_id.clone(),
685 $amount,
686 ($asset_id, $amount).into(),
687 None,
688 0,
689 ),
690 };
691 let mut test = ParaToParaThroughAHTest::new(test_args);
692
693 let mut local_execution_fees = 0;
695 let mut local_delivery_fees = 0;
696 let mut remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm::<()>(Vec::new()));
697 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
698 type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
699 type OriginCaller = <$sender_para as $crate::macros::Chain>::OriginCaller;
700
701 let call = get_call(
702 ($crate::macros::Parent, 100_000_000_000u128),
703 ($crate::macros::Parent, 100_000_000_000u128),
704 ($crate::macros::Parent, 100_000_000_000u128),
705 );
706 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(sender.clone()));
707 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
708 $crate::macros::XCM_VERSION).unwrap();
709 let local_xcm = result.local_xcm.unwrap().clone();
710 let local_xcm_weight = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_xcm_weight(local_xcm).unwrap();
711 local_execution_fees = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(
712 local_xcm_weight,
713 $crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::parent())),
714 )
715 .unwrap();
716 let (destination_to_query, messages_to_query) = &result
718 .forwarded_xcms
719 .iter()
720 .find(|(destination, _)| {
721 *destination == $crate::macros::VersionedLocation::from(
722 $crate::macros::Location::new(1, [$crate::macros::Parachain(1000)]))
723 })
724 .unwrap();
725 assert_eq!(messages_to_query.len(), 1);
726 remote_message = messages_to_query[0].clone();
727 let asset_id_for_delivery_fees = VersionedAssetId::from(Location::parent());
728 let delivery_fees =
729 <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
730 destination_to_query.clone(),
731 remote_message.clone(),
732 asset_id_for_delivery_fees
733 ).unwrap();
734 local_delivery_fees = $crate::xcm_helpers::get_amount_from_versioned_assets(delivery_fees);
735 });
736
737 let mut intermediate_execution_fees = 0;
739 let mut intermediate_delivery_fees = 0;
740 let mut intermediate_remote_message = $crate::macros::VersionedXcm::from($crate::macros::Xcm::<()>(Vec::new()));
741 <$asset_hub as $crate::macros::TestExt>::execute_with(|| {
742 type Runtime = <$asset_hub as $crate::macros::Chain>::Runtime;
743 type RuntimeCall = <$asset_hub as $crate::macros::Chain>::RuntimeCall;
744
745 let weight = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_xcm_weight(remote_message.clone()).unwrap();
747 intermediate_execution_fees = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(
748 weight,
749 $crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::new(1, []))),
750 )
751 .unwrap();
752
753 let xcm_program =
755 $crate::macros::VersionedXcm::from($crate::macros::Xcm::<RuntimeCall>::from(
756 remote_message.clone().try_into().unwrap()));
757
758 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_xcm(
760 sender_as_seen_by_ah.clone().into(), xcm_program).unwrap();
761 let (destination_to_query, messages_to_query) = &result
762 .forwarded_xcms
763 .iter()
764 .find(|(destination, _)| {
765 *destination == $crate::macros::VersionedLocation::from($crate::macros::Location::new(1,
766 [$crate::macros::Parachain(2001)]))
767 })
768 .unwrap();
769 intermediate_remote_message = messages_to_query[0].clone();
775 let asset_id_for_delivery_fees = VersionedAssetId::from(Location::parent());
776 let delivery_fees = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_delivery_fees(
777 destination_to_query.clone(),
778 intermediate_remote_message.clone(),
779 asset_id_for_delivery_fees,
780 )
781 .unwrap();
782 intermediate_delivery_fees = $crate::xcm_helpers::get_amount_from_versioned_assets(delivery_fees);
783 });
784
785 let mut final_execution_fees = 0;
787 <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
788 type Runtime = <$sender_para as $crate::macros::Chain>::Runtime;
789
790 let weight = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_xcm_weight(
791 intermediate_remote_message.clone()).unwrap();
792 final_execution_fees =
793 <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
794 $crate::macros::VersionedAssetId::from($crate::macros::AssetId($crate::macros::Location::parent())))
795 .unwrap();
796 });
797
798 <$sender_para as $crate::macros::TestExt>::reset_ext();
800 <$asset_hub as $crate::macros::TestExt>::reset_ext();
801 <$receiver_para as $crate::macros::TestExt>::reset_ext();
802
803 $sender_para::mint_foreign_asset(
805 <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(asset_owner),
806 $asset_id.clone().into(),
807 sender.clone(),
808 $amount * 2,
809 );
810 $asset_hub::fund_accounts(vec![(sov_of_sender_on_ah, $amount * 2)]);
811
812 let sender_assets_before = <$sender_para as $crate::macros::TestExt>::execute_with(|| {
814 type ForeignAssets = <$sender_para as [<$sender_para Pallet>]>::ForeignAssets;
815 <ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &sender)
816 });
817 let receiver_assets_before = <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
818 type ForeignAssets = <$receiver_para as [<$receiver_para Pallet>]>::ForeignAssets;
819 <ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &beneficiary_id)
820 });
821
822 test.set_assertion::<$sender_para>(sender_assertions);
823 test.set_assertion::<$asset_hub>(hop_assertions);
824 test.set_assertion::<$receiver_para>(receiver_assertions);
825 let call = get_call(
826 ($crate::macros::Parent, local_execution_fees + local_delivery_fees),
827 ($crate::macros::Parent, intermediate_execution_fees + intermediate_delivery_fees),
828 ($crate::macros::Parent, final_execution_fees),
829 );
830 test.set_call(call);
831 test.assert();
832
833 let sender_assets_after = <$sender_para as $crate::macros::TestExt>::execute_with(|| {
834 type ForeignAssets = <$sender_para as [<$sender_para Pallet>]>::ForeignAssets;
835 <ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.clone().into(), &sender)
836 });
837 let receiver_assets_after = <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
838 type ForeignAssets = <$receiver_para as [<$receiver_para Pallet>]>::ForeignAssets;
839 <ForeignAssets as $crate::macros::Inspect<_>>::balance($asset_id.into(), &beneficiary_id)
840 });
841
842 assert_eq!(sender_assets_after, sender_assets_before - $amount);
844 assert_eq!(
845 receiver_assets_after,
846 receiver_assets_before + $amount -
847 local_execution_fees -
848 local_delivery_fees -
849 intermediate_execution_fees -
850 intermediate_delivery_fees -
851 final_execution_fees
852 );
853 }
854 };
855}
856
857#[macro_export]
858macro_rules! test_dry_run_transfer_across_pk_bridge {
859 ( $sender_asset_hub:ty, $sender_bridge_hub:ty, $destination:expr ) => {
860 $crate::macros::paste::paste! {
861
862 let who = $crate::macros::AccountId32::new([1u8; 32]);
863 let transfer_amount = 10_000_000_000_000u128;
864 let initial_balance = transfer_amount * 10;
865
866 $sender_asset_hub::force_xcm_version($destination, $crate::macros::XCM_VERSION);
868
869 <$sender_asset_hub as $crate::macros::TestExt>::execute_with(|| {
870 type Runtime = <$sender_asset_hub as $crate::macros::Chain>::Runtime;
871 type RuntimeCall = <$sender_asset_hub as $crate::macros::Chain>::RuntimeCall;
872 type OriginCaller = <$sender_asset_hub as $crate::macros::Chain>::OriginCaller;
873 type Balances = <$sender_asset_hub as [<$sender_asset_hub Pallet>]>::Balances;
874
875 <Balances as $crate::macros::Mutate<_>>::set_balance(&who, initial_balance);
877
878 let beneficiary: $crate::macros::Location = $crate::macros::Junction::AccountId32 {
879 id: who.clone().into(),
880 network: None,
881 }.into();
882
883 let call = RuntimeCall::PolkadotXcm($crate::macros::pallet_xcm::Call::transfer_assets_using_type_and_then {
884 dest: Box::new($crate::macros::VersionedLocation::from($destination)),
885 assets: Box::new($crate::macros::VersionedAssets::from(vec![
886 ($crate::macros::Parent, transfer_amount).into(),
887 ])),
888 assets_transfer_type: Box::new($crate::macros::TransferType::LocalReserve),
889 remote_fees_id: Box::new($crate::macros::VersionedAssetId::from($crate::macros::Parent)),
890 fees_transfer_type: Box::new($crate::macros::TransferType::LocalReserve),
891 custom_xcm_on_dest: Box::new($crate::macros::VersionedXcm::<()>::from($crate::macros::Xcm::<()>::builder_unsafe().deposit_asset(AllCounted(1), beneficiary).build())),
892 weight_limit: $crate::macros::Unlimited,
893 });
894 let origin = OriginCaller::system($crate::macros::RawOrigin::Signed(who));
895 let result = <Runtime as $crate::macros::DryRunApiV2<_,_,_,_>>::dry_run_call(origin, call.clone(),
896 $crate::macros::XCM_VERSION).unwrap();
897
898 assert!(result.execution_result.is_ok());
900 assert_eq!(result.forwarded_xcms.len(), 1);
901 assert_eq!(result.forwarded_xcms[0].0, $crate::macros::VersionedLocation::from(
902 $crate::macros::Location::new(1, [$crate::macros::Parachain(
903 <$sender_bridge_hub as $crate::macros::Para>::para_id().into())])));
904 });
905 }
906 };
907}
908
909#[macro_export]
910macro_rules! test_xcm_fee_querying_apis_work_for_asset_hub {
911 ( $asset_hub:ty ) => {
912 $crate::macros::paste::paste! {
913
914 <$asset_hub as $crate::macros::TestExt>::execute_with(|| {
915 type RuntimeOrigin = <$asset_hub as $crate::macros::Chain>::RuntimeOrigin;
917 type Assets = <$asset_hub as [<$asset_hub Pallet>]>::Assets;
918 type AssetConversion = <$asset_hub as [<$asset_hub Pallet>]>::AssetConversion;
919 let wnd = $crate::macros::Location::new(1, []);
920 let usdt = $crate::macros::Location::new(0, [$crate::macros::PalletInstance($crate::macros::ASSETS_PALLET_ID),
921 $crate::macros::GeneralIndex($crate::macros::USDT_ID.into())]);
922 let sender = [<$asset_hub Sender>]::get();
923 $crate::macros::assert_ok!(AssetConversion::create_pool(
924 RuntimeOrigin::signed(sender.clone()),
925 Box::new(wnd.clone()),
926 Box::new(usdt.clone()),
927 ));
928
929 type Runtime = <$asset_hub as $crate::macros::Chain>::Runtime;
930 let acceptable_payment_assets = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_acceptable_payment_assets(
931 $crate::macros::XCM_VERSION).unwrap();
932 assert_eq!(acceptable_payment_assets, vec![
933 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(wnd.clone())),
934 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt.clone())),
935 ]);
936
937 let program = $crate::macros::Xcm::<()>::builder()
938 .withdraw_asset(($crate::macros::Parent, 100u128))
939 .buy_execution(($crate::macros::Parent, 10u128), $crate::macros::Unlimited)
940 .deposit_asset($crate::macros::All, [0u8; 32])
941 .build();
942 let weight = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_xcm_weight(
943 $crate::macros::VersionedXcm::from(program)).unwrap();
944 let fee_in_wnd = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
945 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(wnd.clone()))).unwrap();
946 assert!(<Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
948 $crate::macros::VersionedAssetId::from(
949 $crate::macros::AssetId($crate::macros::Location::new(0,
950 [$crate::macros::PalletInstance($crate::macros::ASSETS_PALLET_ID),
951 $crate::macros::GeneralIndex(1)]
952 )
953 )
954 )
955 ).is_err());
956 let fee_in_usdt_fail = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
957 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt.clone())));
958 assert_eq!(fee_in_usdt_fail, Err($crate::macros::XcmPaymentApiError::AssetNotFound));
961 $crate::macros::assert_ok!(Assets::mint(
963 RuntimeOrigin::signed(sender.clone()),
964 $crate::macros::USDT_ID.into(),
965 sender.clone().into(),
966 5_000_000_000_000
967 ));
968 $crate::macros::assert_ok!(AssetConversion::add_liquidity(
970 RuntimeOrigin::signed(sender.clone()),
971 Box::new(wnd),
972 Box::new(usdt.clone()),
973 1_000_000_000_000,
974 4_000_000_000_000,
975 0,
976 0,
977 sender.into()
978 ));
979 let fee_in_usdt = <Runtime as $crate::macros::XcmPaymentApiV2<_>>::query_weight_to_asset_fee(weight,
981 $crate::macros::VersionedAssetId::from($crate::macros::AssetId(usdt))
982 );
983 $crate::macros::assert_ok!(fee_in_usdt);
984 assert!(fee_in_usdt.unwrap() > fee_in_wnd);
985 });
986 }
987 };
988}
989
990#[macro_export]
991macro_rules! test_cross_chain_alias {
992 ( vec![$( ($sender_para:ty, $receiver_para:ty, $is_teleport:expr, $expected_success:expr) ),+], $origin:expr, $target:expr, $fees:expr ) => {
993 $crate::macros::paste::paste! {
994 $(
995 {
996 let para_destination = <$sender_para as $crate::macros::Para>::sibling_location_of(
997 <$receiver_para as $crate::macros::Para>::para_id());
998 let account: $crate::macros::AccountId = $origin.clone().into();
999 $sender_para::fund_accounts(vec![(account.clone(), $fees * 10)]);
1000 let total_fees: $crate::macros::Asset = ($crate::macros::Location::parent(), $fees).into();
1001 let fees: $crate::macros::Asset = ($crate::macros::Location::parent(), $fees / 2).into();
1002
1003 let remote_fees = if $is_teleport {
1004 Some($crate::macros::AssetTransferFilter::Teleport(fees.clone().into()))
1005 } else {
1006 let source_para_sa = <$receiver_para as $crate::macros::Para>::sovereign_account_id_of(
1007 <$receiver_para as $crate::macros::Para>::sibling_location_of(
1008 <$sender_para as $crate::macros::Para>::para_id()),
1009 );
1010 $receiver_para::fund_accounts(vec![(source_para_sa, $fees * 10)]);
1011 Some($crate::macros::AssetTransferFilter::ReserveWithdraw(fees.clone().into()))
1012 };
1013 <$sender_para as $crate::macros::TestExt>::execute_with(|| {
1014 type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent;
1015 let xcm_message = $crate::macros::Xcm::<()>(vec![
1016 $crate::macros::WithdrawAsset(total_fees.into()),
1017 $crate::macros::PayFees { asset: fees.clone() },
1018 $crate::macros::InitiateTransfer {
1019 destination: para_destination,
1020 remote_fees,
1021 preserve_origin: true,
1022 assets: $crate::macros::BoundedVec::new(),
1023 remote_xcm: $crate::macros::Xcm(vec![
1024 $crate::macros::AliasOrigin($target.clone().into()),
1026 $crate::macros::RefundSurplus,
1027 $crate::macros::DepositAsset {
1028 assets: $crate::macros::Wild($crate::macros::AllCounted(1)),
1029 beneficiary: $target.clone().into(),
1030 },
1031 ]),
1032 },
1033 $crate::macros::RefundSurplus,
1034 $crate::macros::DepositAsset { assets: $crate::macros::Wild($crate::macros::AllCounted(1)),
1035 beneficiary: account.clone().into() },
1036 ]);
1037
1038 let signed_origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(account.into());
1039 $crate::macros::assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::execute(
1040 signed_origin,
1041 Box::new($crate::macros::VersionedXcm::from(xcm_message.into())),
1042 $crate::macros::Weight::MAX
1043 ));
1044 $crate::macros::assert_expected_events!(
1045 $sender_para,
1046 vec![
1047 RuntimeEvent::PolkadotXcm($crate::macros::pallet_xcm::Event::Sent { .. }) => {},
1048 ]
1049 );
1050 });
1051
1052 <$receiver_para as $crate::macros::TestExt>::execute_with(|| {
1053 type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent;
1054 $crate::macros::assert_expected_events!(
1055 $receiver_para,
1056 vec![
1057 RuntimeEvent::MessageQueue($crate::macros::pallet_message_queue::Event::Processed {
1058 success, ..
1059 }) => { success: *success == $expected_success, },
1060 ]
1061 );
1062 });
1063 }
1064 )+
1065 }
1066 };
1067}
1068
1069#[macro_export]
1071macro_rules! create_pool_with_native_on {
1072 ( $chain:ident, $asset:expr, $is_foreign:expr, $asset_owner:expr ) => {
1073 $crate::create_pool_with_native_on!(
1074 $chain,
1075 $asset,
1076 $is_foreign,
1077 $asset_owner,
1078 1_000_000_000_000,
1079 2_000_000_000_000
1080 );
1081 };
1082
1083 ( $chain:ident, $asset:expr, $is_foreign:expr, $asset_owner:expr, $native_amount:expr, $asset_amount:expr ) => {
1084 $crate::macros::paste::paste! {
1085 <$chain as $crate::macros::TestExt>::execute_with(|| {
1086 type RuntimeEvent = <$chain as $crate::macros::Chain>::RuntimeEvent;
1087 let owner = $asset_owner;
1088 let signed_owner = <$chain as $crate::macros::Chain>::RuntimeOrigin::signed(owner.clone());
1089 let native_asset: $crate::macros::Location = $crate::macros::Parent.into();
1090
1091 if $is_foreign {
1092 $crate::macros::assert_ok!(<$chain as [<$chain Pallet>]>::ForeignAssets::mint(
1093 signed_owner.clone(),
1094 $asset.clone().into(),
1095 owner.clone().into(),
1096 10_000_000_000_000, ));
1098 } else {
1099 let asset_id = match $asset.interior.last() {
1100 Some($crate::macros::GeneralIndex(id)) => *id as u32,
1101 _ => unreachable!(),
1102 };
1103 $crate::macros::assert_ok!(<$chain as [<$chain Pallet>]>::Assets::mint(
1104 signed_owner.clone(),
1105 asset_id.into(),
1106 owner.clone().into(),
1107 10_000_000_000_000, ));
1109 }
1110
1111 $crate::macros::assert_ok!(<$chain as [<$chain Pallet>]>::AssetConversion::create_pool(
1112 signed_owner.clone(),
1113 Box::new(native_asset.clone()),
1114 Box::new($asset.clone()),
1115 ));
1116
1117 $crate::macros::assert_expected_events!(
1118 $chain,
1119 vec![
1120 RuntimeEvent::AssetConversion($crate::macros::pallet_asset_conversion::Event::PoolCreated { .. }) => {},
1121 ]
1122 );
1123
1124 $crate::macros::assert_ok!(<$chain as [<$chain Pallet>]>::AssetConversion::add_liquidity(
1125 signed_owner,
1126 Box::new(native_asset),
1127 Box::new($asset),
1128 $native_amount,
1129 $asset_amount,
1130 0,
1131 0,
1132 owner.into()
1133 ));
1134
1135 $crate::macros::assert_expected_events!(
1136 $chain,
1137 vec![
1138 RuntimeEvent::AssetConversion($crate::macros::pallet_asset_conversion::Event::LiquidityAdded { .. }) => {},
1139 ]
1140 );
1141 });
1142 }
1143 };
1144}
1145
1146#[macro_export]
1147macro_rules! assert_whitelisted {
1148 ($chain:ident, $expected_call_hash:expr) => {
1149 type RuntimeEvent = <$chain as $crate::macros::Chain>::RuntimeEvent;
1150 $crate::macros::assert_expected_events!(
1151 $chain,
1152 vec![
1153 RuntimeEvent::Whitelist($crate::macros::pallet_whitelist::Event::CallWhitelisted { call_hash }) => {
1154 call_hash: *call_hash == $expected_call_hash,
1155 },
1156 ]
1157 );
1158 };
1159}