1pub use codec::{Decode, Encode};
17pub use paste;
18
19pub use crate::{
20 xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
21 PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD,
22};
23
24pub use frame_support::{
26 assert_ok,
27 sp_runtime::AccountId32,
28 traits::fungibles::Inspect,
29 weights::{Weight, WeightMeter},
30};
31pub use pallet_assets;
32pub use pallet_message_queue;
33pub use pallet_xcm;
34pub use xcm;
35
36pub use polkadot_runtime_parachains::{
38 dmp, hrmp,
39 inclusion::{AggregateMessageOrigin, UmpQueueId},
40};
41pub use xcm::{
42 prelude::{
43 Asset, InteriorLocation, Location, OriginKind, Outcome, VersionedXcm, XcmError, XcmVersion,
44 },
45 DoubleEncoded,
46};
47
48pub use cumulus_pallet_parachain_system;
50pub use cumulus_pallet_xcmp_queue;
51pub use cumulus_primitives_core::{
52 relay_chain::HrmpChannelId, DmpMessageHandler, Junction, Junctions, NetworkId, ParaId,
53 XcmpMessageHandler,
54};
55pub use parachains_common::{AccountId, Balance};
56pub use xcm_emulator::{
57 assert_expected_events, bx, helpers::weight_within_threshold, BridgeLaneId, BridgeMessage,
58 BridgeMessageDispatchError, BridgeMessageHandler, Chain, Network, Parachain, RelayChain,
59 TestExt,
60};
61
62use bp_messages::{
64 target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
65 MessageKey, OutboundLaneData,
66};
67pub use bp_xcm_bridge_hub::XcmBridgeHubCall;
68use pallet_bridge_messages::{Config as BridgeMessagesConfig, LaneIdOf, OutboundLanes, Pallet};
69pub use pallet_bridge_messages::{
70 Instance1 as BridgeMessagesInstance1, Instance2 as BridgeMessagesInstance2,
71 Instance3 as BridgeMessagesInstance3,
72};
73use pallet_xcm_bridge_hub::XcmBlobMessageDispatchResult;
74
75pub struct BridgeHubMessageHandler<S, SI, T, TI> {
76 _marker: std::marker::PhantomData<(S, SI, T, TI)>,
77}
78
79struct LaneIdWrapper<LaneId>(LaneId);
80impl<LaneId: Encode> From<LaneIdWrapper<LaneId>> for BridgeLaneId {
81 fn from(lane_id: LaneIdWrapper<LaneId>) -> BridgeLaneId {
82 lane_id.0.encode()
83 }
84}
85impl<LaneId: Decode> From<BridgeLaneId> for LaneIdWrapper<LaneId> {
86 fn from(id: BridgeLaneId) -> LaneIdWrapper<LaneId> {
87 LaneIdWrapper(LaneId::decode(&mut &id[..]).expect("decodable"))
88 }
89}
90
91impl<S, SI, T, TI> BridgeMessageHandler for BridgeHubMessageHandler<S, SI, T, TI>
92where
93 S: BridgeMessagesConfig<SI>,
94 SI: 'static,
95 T: BridgeMessagesConfig<TI>,
96 TI: 'static,
97 <T as BridgeMessagesConfig<TI>>::InboundPayload: From<Vec<u8>>,
98 <T as BridgeMessagesConfig<TI>>::MessageDispatch:
99 MessageDispatch<DispatchLevelResult = XcmBlobMessageDispatchResult>,
100{
101 fn get_source_outbound_messages() -> Vec<BridgeMessage> {
102 let active_outbound_lanes = OutboundLanes::<S, SI>::iter_keys();
104
105 let mut messages: Vec<BridgeMessage> = Default::default();
106
107 for lane in active_outbound_lanes {
109 let latest_generated_nonce =
110 OutboundLanes::<S, SI>::get(lane).unwrap().latest_generated_nonce;
111 let latest_received_nonce =
112 OutboundLanes::<S, SI>::get(lane).unwrap().latest_received_nonce;
113
114 (latest_received_nonce + 1..=latest_generated_nonce).for_each(|nonce| {
115 let encoded_payload: Vec<u8> = Pallet::<S, SI>::outbound_message_data(lane, nonce)
116 .expect("Bridge message does not exist")
117 .into();
118 let payload = Vec::<u8>::decode(&mut &encoded_payload[..])
119 .expect("Decoding XCM message failed");
120 let message = BridgeMessage { lane_id: LaneIdWrapper(lane).into(), nonce, payload };
121
122 messages.push(message);
123 });
124 }
125 messages
126 }
127
128 fn dispatch_target_inbound_message(
129 message: BridgeMessage,
130 ) -> Result<(), BridgeMessageDispatchError> {
131 type TargetMessageDispatch<T, I> = <T as BridgeMessagesConfig<I>>::MessageDispatch;
132 type InboundPayload<T, I> = <T as BridgeMessagesConfig<I>>::InboundPayload;
133
134 let lane_id = LaneIdWrapper::from(message.lane_id).0;
135 let nonce = message.nonce;
136 let payload = Ok(From::from(message.payload));
137
138 let dispatch_result = TargetMessageDispatch::<T, TI>::dispatch(DispatchMessage {
141 key: MessageKey { lane_id, nonce },
142 data: DispatchMessageData::<InboundPayload<T, TI>> { payload },
143 });
144
145 let result = match dispatch_result.dispatch_level_result {
146 XcmBlobMessageDispatchResult::Dispatched => Ok(()),
147 XcmBlobMessageDispatchResult::InvalidPayload => Err(BridgeMessageDispatchError(
148 Box::new(XcmBlobMessageDispatchResult::InvalidPayload),
149 )),
150 XcmBlobMessageDispatchResult::NotDispatched(e) => Err(BridgeMessageDispatchError(
151 Box::new(XcmBlobMessageDispatchResult::NotDispatched(e)),
152 )),
153 };
154 result
155 }
156
157 fn notify_source_message_delivery(lane_id: BridgeLaneId) {
158 let lane_id: LaneIdOf<S, SI> = LaneIdWrapper::from(lane_id).0;
159 let data = OutboundLanes::<S, SI>::get(lane_id).unwrap();
160 let new_data = OutboundLaneData {
161 oldest_unpruned_nonce: data.oldest_unpruned_nonce + 1,
162 latest_received_nonce: data.latest_received_nonce + 1,
163 ..data
164 };
165
166 OutboundLanes::<S, SI>::insert(lane_id, new_data);
167 }
168}
169
170#[macro_export]
171macro_rules! impl_accounts_helpers_for_relay_chain {
172 ( $chain:ident ) => {
173 $crate::impls::paste::paste! {
174 impl<N: $crate::impls::Network> $chain<N> {
175 pub fn fund_accounts(accounts: Vec<($crate::impls::AccountId, $crate::impls::Balance)>) {
177 <Self as $crate::impls::TestExt>::execute_with(|| {
178 for account in accounts {
179 let who = account.0;
180 let actual = <Self as [<$chain RelayPallet>]>::Balances::free_balance(&who);
181 let actual = actual.saturating_add(<Self as [<$chain RelayPallet>]>::Balances::reserved_balance(&who));
182
183 $crate::impls::assert_ok!(<Self as [<$chain RelayPallet>]>::Balances::force_set_balance(
184 <Self as $crate::impls::Chain>::RuntimeOrigin::root(),
185 who.into(),
186 actual.saturating_add(account.1),
187 ));
188 }
189 });
190 }
191 pub fn fund_para_sovereign(amount: $crate::impls::Balance, para_id: $crate::impls::ParaId) -> $crate::impls::AccountId32 {
193 let sovereign_account = <Self as $crate::impls::RelayChain>::sovereign_account_id_of_child_para(para_id);
194 Self::fund_accounts(vec![(sovereign_account.clone(), amount)]);
195 sovereign_account
196 }
197 }
198 }
199 };
200}
201
202#[macro_export]
203macro_rules! impl_assert_events_helpers_for_relay_chain {
204 ( $chain:ident ) => {
205 $crate::impls::paste::paste! {
206 type [<$chain RuntimeEvent>]<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
207
208 impl<N: $crate::impls::Network> $chain<N> {
209 pub fn assert_xcm_pallet_attempted_complete(expected_weight: Option<$crate::impls::Weight>) {
211 $crate::impls::assert_expected_events!(
212 Self,
213 vec![
214 [<$chain RuntimeEvent>]::<N>::XcmPallet(
215 $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete { used: weight } }
216 ) => {
217 weight: $crate::impls::weight_within_threshold(
218 ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
219 expected_weight.unwrap_or(*weight),
220 *weight
221 ),
222 },
223 ]
224 );
225 }
226
227 pub fn assert_xcm_pallet_attempted_incomplete(
229 expected_weight: Option<$crate::impls::Weight>,
230 expected_error: Option<$crate::impls::XcmError>,
231 ) {
232 $crate::impls::assert_expected_events!(
233 Self,
234 vec![
235 [<$chain RuntimeEvent>]::<N>::XcmPallet(
237 $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error: $crate::impls::xcm::prelude::InstructionError { error, .. } } }
238 ) => {
239 weight: $crate::impls::weight_within_threshold(
240 ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
241 expected_weight.unwrap_or(*weight),
242 *weight
243 ),
244 error: *error == expected_error.unwrap_or((*error).into()).into(),
245 },
246 ]
247 );
248 }
249
250 pub fn assert_xcm_pallet_sent() {
252 $crate::impls::assert_expected_events!(
253 Self,
254 vec![
255 [<$chain RuntimeEvent>]::<N>::XcmPallet($crate::impls::pallet_xcm::Event::Sent { .. }) => {},
256 ]
257 );
258 }
259
260 pub fn assert_ump_queue_processed(
263 expected_success: bool,
264 expected_id: Option<$crate::impls::ParaId>,
265 expected_weight: Option<$crate::impls::Weight>,
266 ) {
267 $crate::impls::assert_expected_events!(
268 Self,
269 vec![
270 [<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pallet_message_queue::Event::Processed {
272 origin: $crate::impls::AggregateMessageOrigin::Ump($crate::impls::UmpQueueId::Para(id)),
273 weight_used,
274 success,
275 ..
276 }) => {
277 id: *id == expected_id.unwrap_or(*id),
278 weight_used: $crate::impls::weight_within_threshold(
279 ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
280 expected_weight.unwrap_or(*weight_used),
281 *weight_used
282 ),
283 success: *success == expected_success,
284 },
285 ]
286 );
287 }
288 }
289 }
290 };
291}
292
293#[macro_export]
294macro_rules! impl_hrmp_channels_helpers_for_relay_chain {
295 ( $chain:ident ) => {
296 $crate::impls::paste::paste! {
297 impl<N: $crate::impls::Network> $chain<N> {
298 pub fn init_open_channel_call(
300 recipient_para_id: $crate::impls::ParaId,
301 max_capacity: u32,
302 max_message_size: u32,
303 ) -> $crate::impls::DoubleEncoded<()> {
304 use $crate::impls::Encode;
305
306 <Self as $crate::impls::Chain>::RuntimeCall::Hrmp($crate::impls::hrmp::Call::<
307 <Self as $crate::impls::Chain>::Runtime,
308 >::hrmp_init_open_channel {
309 recipient: recipient_para_id,
310 proposed_max_capacity: max_capacity,
311 proposed_max_message_size: max_message_size,
312 })
313 .encode()
314 .into()
315 }
316 pub fn accept_open_channel_call(sender_para_id: $crate::impls::ParaId) -> $crate::impls::DoubleEncoded<()> {
318 use $crate::impls::Encode;
319
320 <Self as $crate::impls::Chain>::RuntimeCall::Hrmp($crate::impls::hrmp::Call::<
321 <Self as $crate::impls::Chain>::Runtime,
322 >::hrmp_accept_open_channel {
323 sender: sender_para_id,
324 })
325 .encode()
326 .into()
327 }
328
329 pub fn force_process_hrmp_open(sender: $crate::impls::ParaId, recipient: $crate::impls::ParaId) {
331 use $crate::impls::Chain;
332
333 <Self as $crate::impls::TestExt>::execute_with(|| {
334 let relay_root_origin = <Self as Chain>::RuntimeOrigin::root();
335
336 $crate::impls::assert_ok!(<Self as [<$chain RelayPallet>]>::Hrmp::force_process_hrmp_open(
338 relay_root_origin,
339 0
340 ));
341
342 let channel_id = $crate::impls::HrmpChannelId { sender, recipient };
343
344 let hrmp_channel_exist = $crate::impls::hrmp::HrmpChannels::<
345 <Self as Chain>::Runtime,
346 >::contains_key(&channel_id);
347
348 assert!(hrmp_channel_exist)
350 });
351 }
352 }
353 }
354 };
355}
356
357#[macro_export]
358macro_rules! impl_send_transact_helpers_for_relay_chain {
359 ( $chain:ident ) => {
360 $crate::impls::paste::paste! {
361 impl<N: $crate::impls::Network> $chain<N> {
362 pub fn send_unpaid_transact_to_parachain_as_root(
364 recipient: $crate::impls::ParaId,
365 call: $crate::impls::DoubleEncoded<()>
366 ) {
367 use $crate::impls::{bx, Chain, RelayChain};
368
369 <Self as $crate::impls::TestExt>::execute_with(|| {
370 let root_origin = <Self as Chain>::RuntimeOrigin::root();
371 let destination: $crate::impls::Location = <Self as RelayChain>::child_location_of(recipient);
372 let xcm = $crate::impls::xcm_transact_unpaid_execution(call, $crate::impls::OriginKind::Superuser);
373
374 $crate::impls::dmp::Pallet::<<Self as $crate::impls::Chain>::Runtime>::make_parachain_reachable(recipient);
375
376 $crate::impls::assert_ok!(<Self as [<$chain RelayPallet>]>::XcmPallet::send(
378 root_origin,
379 bx!(destination.into()),
380 bx!(xcm),
381 ));
382 Self::assert_xcm_pallet_sent();
383 });
384 }
385 }
386 }
387 };
388}
389
390#[macro_export]
391macro_rules! impl_accounts_helpers_for_parachain {
392 ( $chain:ident ) => {
393 $crate::impls::paste::paste! {
394 impl<N: $crate::impls::Network> $chain<N> {
395 pub fn fund_accounts(accounts: Vec<($crate::impls::AccountId, $crate::impls::Balance)>) {
397 <Self as $crate::impls::TestExt>::execute_with(|| {
398 for account in accounts {
399 let who = account.0;
400 let actual = <Self as [<$chain ParaPallet>]>::Balances::free_balance(&who);
401 let actual = actual.saturating_add(<Self as [<$chain ParaPallet>]>::Balances::reserved_balance(&who));
402
403 $crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::Balances::force_set_balance(
404 <Self as $crate::impls::Chain>::RuntimeOrigin::root(),
405 who.into(),
406 actual.saturating_add(account.1),
407 ));
408 }
409 });
410 }
411
412 pub fn fund_para_sovereign(sibling_para_id: $crate::impls::ParaId, balance: $crate::impls::Balance) {
414 let sibling_location = Self::sibling_location_of(sibling_para_id);
415 let sovereign_account = Self::sovereign_account_id_of(sibling_location);
416 Self::fund_accounts(vec![(sovereign_account.into(), balance)])
417 }
418
419 pub fn sovereign_account_of_parachain_on_other_global_consensus(
421 network_id: $crate::impls::NetworkId,
422 para_id: $crate::impls::ParaId,
423 ) -> $crate::impls::AccountId {
424 let remote_location = $crate::impls::Location::new(
425 2,
426 [
427 $crate::impls::Junction::GlobalConsensus(network_id),
428 $crate::impls::Junction::Parachain(para_id.into()),
429 ],
430 );
431 <Self as $crate::impls::TestExt>::execute_with(|| {
432 Self::sovereign_account_id_of(remote_location)
433 })
434 }
435 }
436 }
437 };
438}
439
440#[macro_export]
441macro_rules! impl_assert_events_helpers_for_parachain {
442 ( $chain:ident ) => {
443 $crate::impls::paste::paste! {
444 type [<$chain RuntimeEvent>]<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
445
446 impl<N: $crate::impls::Network> $chain<N> {
447 pub fn assert_xcm_pallet_attempted_complete(expected_weight: Option<$crate::impls::Weight>) {
449 $crate::impls::assert_expected_events!(
450 Self,
451 vec![
452 [<$chain RuntimeEvent>]::<N>::PolkadotXcm(
453 $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete { used: weight } }
454 ) => {
455 weight: $crate::impls::weight_within_threshold(
456 ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
457 expected_weight.unwrap_or(*weight),
458 *weight
459 ),
460 },
461 ]
462 );
463 }
464
465 pub fn assert_xcm_pallet_attempted_incomplete(
467 expected_weight: Option<$crate::impls::Weight>,
468 expected_error: Option<$crate::impls::XcmError>,
469 ) {
470 $crate::impls::assert_expected_events!(
471 Self,
472 vec![
473 [<$chain RuntimeEvent>]::<N>::PolkadotXcm(
475 $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error: $crate::impls::xcm::prelude::InstructionError { error, .. } } }
476 ) => {
477 weight: $crate::impls::weight_within_threshold(
478 ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
479 expected_weight.unwrap_or(*weight),
480 *weight
481 ),
482 error: *error == expected_error.unwrap_or((*error).into()).into(),
483 },
484 ]
485 );
486 }
487
488 pub fn assert_xcm_pallet_attempted_error(expected_error: Option<$crate::impls::XcmError>) {
490 $crate::impls::assert_expected_events!(
491 Self,
492 vec![
493 [<$chain RuntimeEvent>]::<N>::PolkadotXcm(
495 $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Error($crate::impls::xcm::prelude::InstructionError { error, .. }) }
496 ) => {
497 error: *error == expected_error.unwrap_or((*error).into()).into(),
498 },
499 ]
500 );
501 }
502
503 pub fn assert_xcm_pallet_sent() {
505 $crate::impls::assert_expected_events!(
506 Self,
507 vec![
508 [<$chain RuntimeEvent>]::<N>::PolkadotXcm($crate::impls::pallet_xcm::Event::Sent { .. }) => {},
509 ]
510 );
511 }
512
513 pub fn assert_parachain_system_ump_sent() {
515 $crate::impls::assert_expected_events!(
516 Self,
517 vec![
518 [<$chain RuntimeEvent>]::<N>::ParachainSystem(
519 $crate::impls::cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
520 ) => {},
521 ]
522 );
523 }
524
525 pub fn assert_dmp_queue_complete(expected_weight: Option<$crate::impls::Weight>) {
527 $crate::impls::assert_expected_events!(
528 Self,
529 vec![
530 [<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pallet_message_queue::Event::Processed {
531 success: true, weight_used: weight, ..
532 }) => {
533 weight: $crate::impls::weight_within_threshold(
534 ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
535 expected_weight.unwrap_or(*weight),
536 *weight
537 ),
538 },
539 ]
540 );
541 }
542
543 pub fn assert_dmp_queue_incomplete(
545 expected_weight: Option<$crate::impls::Weight>,
546 ) {
547 $crate::impls::assert_expected_events!(
548 Self,
549 vec![
550 [<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pallet_message_queue::Event::Processed {
551 success: false, weight_used: weight, ..
552 }) => {
553 weight: $crate::impls::weight_within_threshold(
554 ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
555 expected_weight.unwrap_or(*weight),
556 *weight
557 ),
558 },
559 ]
560 );
561 }
562
563 pub fn assert_dmp_queue_error() {
565 $crate::impls::assert_expected_events!(
566 Self,
567 vec![
568 [<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pallet_message_queue::Event::ProcessingFailed {
569 ..
570 }) => {
571
572 },
573 ]
574 );
575 }
576
577 pub fn assert_xcmp_queue_success(expected_weight: Option<$crate::impls::Weight>) {
579 $crate::impls::assert_expected_events!(
580 Self,
581 vec![
582 [<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pallet_message_queue::Event::Processed { success: true, weight_used: weight, .. }
583 ) => {
584 weight: $crate::impls::weight_within_threshold(
585 ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
586 expected_weight.unwrap_or(*weight),
587 *weight
588 ),
589 },
590 ]
591 );
592 }
593 }
594 }
595 };
596}
597
598#[macro_export]
599macro_rules! impl_assets_helpers_for_system_parachain {
600 ( $chain:ident, $relay_chain:ident ) => {
601 $crate::impls::paste::paste! {
602 impl<N: $crate::impls::Network> $chain<N> {
603 pub fn force_create_asset_call(
605 asset_id: u32,
606 owner: $crate::impls::AccountId,
607 is_sufficient: bool,
608 min_balance: $crate::impls::Balance,
609 ) -> $crate::impls::DoubleEncoded<()> {
610 use $crate::impls::{Chain, Encode};
611
612 <Self as Chain>::RuntimeCall::Assets($crate::impls::pallet_assets::Call::<
613 <Self as Chain>::Runtime,
614 $crate::impls::pallet_assets::Instance1,
615 >::force_create {
616 id: asset_id.into(),
617 owner: owner.into(),
618 is_sufficient,
619 min_balance,
620 })
621 .encode()
622 .into()
623 }
624
625 pub fn force_create_asset_xcm(
627 origin_kind: $crate::impls::OriginKind,
628 asset_id: u32,
629 owner: $crate::impls::AccountId,
630 is_sufficient: bool,
631 min_balance: $crate::impls::Balance,
632 ) -> $crate::impls::VersionedXcm<()> {
633 let call = Self::force_create_asset_call(asset_id, owner, is_sufficient, min_balance);
634 $crate::impls::xcm_transact_unpaid_execution(call, origin_kind)
635 }
636
637 pub fn force_create_and_mint_asset(
639 id: u32,
640 min_balance: u128,
641 is_sufficient: bool,
642 asset_owner: $crate::impls::AccountId,
643 dmp_weight_threshold: Option<$crate::impls::Weight>,
644 amount_to_mint: u128,
645 ) {
646 use $crate::impls::Chain;
647
648 Self::force_create_asset_from_relay_as_root(
650 id,
651 min_balance,
652 is_sufficient,
653 asset_owner.clone(),
654 dmp_weight_threshold
655 );
656
657 let signed_origin = <Self as Chain>::RuntimeOrigin::signed(asset_owner.clone());
659 Self::mint_asset(signed_origin, id, asset_owner, amount_to_mint);
660 }
661
662 pub fn force_create_asset_from_relay_as_root(
664 id: u32,
665 min_balance: u128,
666 is_sufficient: bool,
667 asset_owner: $crate::impls::AccountId,
668 dmp_weight_threshold: Option<$crate::impls::Weight>,
669 ) {
670 use $crate::impls::{Parachain, Inspect, TestExt};
671
672 <$relay_chain<N>>::send_unpaid_transact_to_parachain_as_root(
673 Self::para_id(),
674 Self::force_create_asset_call(id, asset_owner.clone(), is_sufficient, min_balance),
675 );
676
677 Self::execute_with(|| {
679 type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
680
681 Self::assert_dmp_queue_complete(dmp_weight_threshold);
682
683 $crate::impls::assert_expected_events!(
684 Self,
685 vec![
686 RuntimeEvent::<N>::Assets($crate::impls::pallet_assets::Event::ForceCreated { asset_id, owner }) => {
687 asset_id: *asset_id == id,
688 owner: *owner == asset_owner,
689 },
690 ]
691 );
692
693 assert!(<Self as [<$chain ParaPallet>]>::Assets::asset_exists(id.clone().into()));
694 });
695 }
696 }
697 }
698 };
699}
700
701#[macro_export]
702macro_rules! impl_assets_helpers_for_parachain {
703 ($chain:ident) => {
704 $crate::impls::paste::paste! {
705 impl<N: $crate::impls::Network> $chain<N> {
706 pub fn force_create_asset(
708 id: u32,
709 owner: $crate::impls::AccountId,
710 is_sufficient: bool,
711 min_balance: u128,
712 prefund_accounts: Vec<($crate::impls::AccountId, u128)>,
713 ) {
714 use $crate::impls::Inspect;
715 let sudo_origin = <$chain<N> as $crate::impls::Chain>::RuntimeOrigin::root();
716 <Self as $crate::impls::TestExt>::execute_with(|| {
717 $crate::impls::assert_ok!(
718 <Self as [<$chain ParaPallet>]>::Assets::force_create(
719 sudo_origin,
720 id.clone().into(),
721 owner.clone().into(),
722 is_sufficient,
723 min_balance,
724 )
725 );
726 assert!(<Self as [<$chain ParaPallet>]>::Assets::asset_exists(id.clone()));
727 type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
728 $crate::impls::assert_expected_events!(
729 Self,
730 vec![
731 RuntimeEvent::<N>::Assets(
732 $crate::impls::pallet_assets::Event::ForceCreated {
733 asset_id,
734 ..
735 }
736 ) => { asset_id: *asset_id == id, },
737 ]
738 );
739 });
740 for (beneficiary, amount) in prefund_accounts.into_iter() {
741 let signed_origin =
742 <$chain<N> as $crate::impls::Chain>::RuntimeOrigin::signed(owner.clone());
743 Self::mint_asset(signed_origin, id.clone(), beneficiary, amount);
744 }
745 }
746
747 pub fn mint_asset(
749 signed_origin: <Self as $crate::impls::Chain>::RuntimeOrigin,
750 id: u32,
751 beneficiary: $crate::impls::AccountId,
752 amount_to_mint: u128,
753 ) {
754 <Self as $crate::impls::TestExt>::execute_with(|| {
755 $crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::Assets::mint(
756 signed_origin,
757 id.clone().into(),
758 beneficiary.clone().into(),
759 amount_to_mint
760 ));
761
762 type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
763
764 $crate::impls::assert_expected_events!(
765 Self,
766 vec![
767 RuntimeEvent::<N>::Assets(
768 $crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount }
769 ) => {
770 asset_id: *asset_id == id,
771 owner: *owner == beneficiary.clone().into(),
772 amount: *amount == amount_to_mint,
773 },
774 ]
775 );
776 });
777 }
778
779 pub fn create_asset_call(
781 asset_id: u32,
782 min_balance: $crate::impls::Balance,
783 admin: $crate::impls::AccountId,
784 ) -> $crate::impls::DoubleEncoded<()> {
785 use $crate::impls::{Chain, Encode};
786
787 <Self as Chain>::RuntimeCall::Assets($crate::impls::pallet_assets::Call::<
788 <Self as Chain>::Runtime,
789 $crate::impls::pallet_assets::Instance1,
790 >::create {
791 id: asset_id.into(),
792 min_balance,
793 admin: admin.into(),
794 })
795 .encode()
796 .into()
797 }
798 }
799 }
800 };
801}
802
803#[macro_export]
804macro_rules! impl_foreign_assets_helpers_for_parachain {
805 ($chain:ident, $asset_id_type:ty) => {
806 $crate::impls::paste::paste! {
807 impl<N: $crate::impls::Network> $chain<N> {
808 pub fn force_create_foreign_asset(
810 id: $asset_id_type,
811 owner: $crate::impls::AccountId,
812 is_sufficient: bool,
813 min_balance: u128,
814 prefund_accounts: Vec<($crate::impls::AccountId, u128)>,
815 ) {
816 use $crate::impls::Inspect;
817 let sudo_origin = <$chain<N> as $crate::impls::Chain>::RuntimeOrigin::root();
818 <Self as $crate::impls::TestExt>::execute_with(|| {
819 $crate::impls::assert_ok!(
820 <Self as [<$chain ParaPallet>]>::ForeignAssets::force_create(
821 sudo_origin,
822 id.clone(),
823 owner.clone().into(),
824 is_sufficient,
825 min_balance,
826 )
827 );
828 assert!(<Self as [<$chain ParaPallet>]>::ForeignAssets::asset_exists(id.clone()));
829 type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
830 $crate::impls::assert_expected_events!(
831 Self,
832 vec![
833 RuntimeEvent::<N>::ForeignAssets(
834 $crate::impls::pallet_assets::Event::ForceCreated {
835 asset_id,
836 ..
837 }
838 ) => { asset_id: *asset_id == id, },
839 ]
840 );
841 });
842 for (beneficiary, amount) in prefund_accounts.into_iter() {
843 let signed_origin =
844 <$chain<N> as $crate::impls::Chain>::RuntimeOrigin::signed(owner.clone());
845 Self::mint_foreign_asset(signed_origin, id.clone(), beneficiary, amount);
846 }
847 }
848
849 pub fn mint_foreign_asset(
851 signed_origin: <Self as $crate::impls::Chain>::RuntimeOrigin,
852 id: $asset_id_type,
853 beneficiary: $crate::impls::AccountId,
854 amount_to_mint: u128,
855 ) {
856 <Self as $crate::impls::TestExt>::execute_with(|| {
857 $crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::ForeignAssets::mint(
858 signed_origin,
859 id.clone().into(),
860 beneficiary.clone().into(),
861 amount_to_mint
862 ));
863
864 type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
865
866 $crate::impls::assert_expected_events!(
867 Self,
868 vec![
869 RuntimeEvent::<N>::ForeignAssets(
870 $crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount }
871 ) => {
872 asset_id: *asset_id == id,
873 owner: *owner == beneficiary.clone().into(),
874 amount: *amount == amount_to_mint,
875 },
876 ]
877 );
878 });
879 }
880
881 pub fn create_foreign_asset_call(
883 asset_id: $asset_id_type,
884 min_balance: $crate::impls::Balance,
885 admin: $crate::impls::AccountId,
886 ) -> $crate::impls::DoubleEncoded<()> {
887 use $crate::impls::{Chain, Encode};
888
889 <Self as Chain>::RuntimeCall::ForeignAssets($crate::impls::pallet_assets::Call::<
890 <Self as Chain>::Runtime,
891 $crate::impls::pallet_assets::Instance2,
892 >::create {
893 id: asset_id.into(),
894 min_balance,
895 admin: admin.into(),
896 })
897 .encode()
898 .into()
899 }
900 }
901 }
902 };
903}
904
905#[macro_export]
906macro_rules! impl_xcm_helpers_for_parachain {
907 ( $chain:ident ) => {
908 $crate::impls::paste::paste! {
909 impl<N: $crate::impls::Network> $chain<N> {
910 pub fn force_xcm_version(dest: $crate::impls::Location, version: $crate::impls::XcmVersion) {
912 <Self as $crate::impls::TestExt>::execute_with(|| {
913 $crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::PolkadotXcm::force_xcm_version(
914 <Self as $crate::impls::Chain>::RuntimeOrigin::root(),
915 $crate::impls::bx!(dest),
916 version,
917 ));
918 });
919 }
920
921 pub fn force_default_xcm_version(version: Option<$crate::impls::XcmVersion>) {
923 <Self as $crate::impls::TestExt>::execute_with(|| {
924 $crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::PolkadotXcm::force_default_xcm_version(
925 <Self as $crate::impls::Chain>::RuntimeOrigin::root(),
926 version,
927 ));
928 });
929 }
930 }
931 }
932 }
933}
934
935#[macro_export]
936macro_rules! impl_bridge_helpers_for_chain {
937 ( $chain:ident, $pallet:ident, $pallet_xcm:ident, $runtime_call_wrapper:path ) => {
938 $crate::impls::paste::paste! {
939 impl<N: $crate::impls::Network> $chain<N> {
940 pub fn open_bridge(
942 bridge_location: $crate::impls::Location,
943 bridge_destination_universal_location: $crate::impls::InteriorLocation,
944 maybe_paid: Option<($crate::impls::Asset, $crate::impls::AccountId)>
945 ) {
946 <Self as $crate::impls::TestExt>::execute_with(|| {
947 use $crate::impls::{bx, Chain};
948 use $crate::impls::XcmBridgeHubCall;
949 use $crate::impls::Encode;
950
951 let root_origin = <Self as Chain>::RuntimeOrigin::root();
953
954 let call: $crate::impls::DoubleEncoded<()> = $runtime_call_wrapper(XcmBridgeHubCall::open_bridge {
956 bridge_destination_universal_location: bx!(
957 bridge_destination_universal_location.clone().into()
958 )
959 }).encode().into();
960
961 let xcm = if let Some((fee_asset, beneficiary)) = maybe_paid {
962 $crate::impls::xcm_transact_paid_execution(call, $crate::impls::OriginKind::Xcm, fee_asset, beneficiary)
963 } else {
964 $crate::impls::xcm_transact_unpaid_execution(call, $crate::impls::OriginKind::Xcm)
965 };
966
967 $crate::impls::assert_ok!(<Self as [<$chain $pallet>]>::$pallet_xcm::send(
969 root_origin,
970 bx!(bridge_location.into()),
971 bx!(xcm),
972 ));
973 Self::assert_xcm_pallet_sent();
974 });
975 }
976 }
977 }
978 }
979}