1pub mod from_grandpa_chain;
23pub mod from_parachain;
24
25pub(crate) mod helpers;
26
27use crate::{test_cases::bridges_prelude::*, test_data};
28
29use asset_test_utils::BasicParachainRuntime;
30use bp_messages::{
31 target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
32 LaneState, MessageKey, MessagesOperatingMode, OutboundLaneData,
33};
34use bp_runtime::BasicOperatingMode;
35use codec::Encode;
36use frame_support::{
37 assert_ok,
38 dispatch::GetDispatchInfo,
39 traits::{fungible::Mutate, Contains, Get, OnFinalize, OnInitialize, OriginTrait},
40};
41use frame_system::pallet_prelude::BlockNumberFor;
42use parachains_common::AccountId;
43use parachains_runtimes_test_utils::{
44 mock_open_hrmp_channel, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder,
45 GovernanceOrigin, RuntimeCallOf, RuntimeOriginOf, SlotDurations, XcmReceivedFrom,
46};
47use sp_runtime::{traits::Zero, AccountId32};
48use xcm::{latest::prelude::*, AlwaysLatest};
49use xcm_builder::DispatchBlobError;
50use xcm_executor::{
51 traits::{ConvertLocation, WeightBounds},
52 XcmExecutor,
53};
54
55pub(crate) mod bridges_prelude {
57 pub use bp_parachains::{RelayBlockHash, RelayBlockNumber};
58 pub use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig};
59 pub use pallet_bridge_messages::{
60 Call as BridgeMessagesCall, Config as BridgeMessagesConfig, LanesManagerError,
61 };
62 pub use pallet_bridge_parachains::{
63 Call as BridgeParachainsCall, Config as BridgeParachainsConfig,
64 };
65}
66
67pub use for_pallet_xcm_bridge_hub::open_and_close_bridge_works;
69
70pub use asset_test_utils::include_teleports_for_native_asset_works;
72use pallet_bridge_messages::LaneIdOf;
73
74pub type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
75 parachains_runtimes_test_utils::RuntimeHelper<Runtime, AllPalletsWithoutSystem>;
76
77pub use parachains_runtimes_test_utils::test_cases::{
79 change_storage_constant_by_governance_works, set_storage_keys_by_governance_works,
80};
81
82pub fn run_test<Runtime, T>(
84 collator_session_key: CollatorSessionKeys<Runtime>,
85 runtime_para_id: u32,
86 balances: Vec<(Runtime::AccountId, Runtime::Balance)>,
87 test: impl FnOnce() -> T,
88) -> T
89where
90 Runtime: BasicParachainRuntime,
91{
92 ExtBuilder::<Runtime>::default()
93 .with_collators(collator_session_key.collators())
94 .with_session_keys(collator_session_key.session_keys())
95 .with_safe_xcm_version(XCM_VERSION)
96 .with_para_id(runtime_para_id.into())
97 .with_balances(balances)
98 .with_tracing()
99 .build()
100 .execute_with(|| test())
101}
102
103pub fn initialize_bridge_by_governance_works<Runtime, GrandpaPalletInstance>(
105 collator_session_key: CollatorSessionKeys<Runtime>,
106 runtime_para_id: u32,
107 governance_origin: GovernanceOrigin<RuntimeOriginOf<Runtime>>,
108) where
109 Runtime: BasicParachainRuntime + BridgeGrandpaConfig<GrandpaPalletInstance>,
110 GrandpaPalletInstance: 'static,
111 RuntimeCallOf<Runtime>:
112 GetDispatchInfo + From<BridgeGrandpaCall<Runtime, GrandpaPalletInstance>>,
113{
114 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
115 assert_eq!(
117 pallet_bridge_grandpa::PalletOperatingMode::<Runtime, GrandpaPalletInstance>::try_get(),
118 Err(())
119 );
120
121 let initialize_call = RuntimeCallOf::<Runtime>::from(BridgeGrandpaCall::<
123 Runtime,
124 GrandpaPalletInstance,
125 >::initialize {
126 init_data: test_data::initialization_data::<Runtime, GrandpaPalletInstance>(12345),
127 });
128
129 assert_ok!(RuntimeHelper::<Runtime>::execute_as_governance_call(
131 initialize_call,
132 governance_origin
133 ));
134
135 assert_eq!(
137 pallet_bridge_grandpa::PalletOperatingMode::<Runtime, GrandpaPalletInstance>::try_get(),
138 Ok(BasicOperatingMode::Normal)
139 );
140 })
141}
142
143pub fn change_bridge_grandpa_pallet_mode_by_governance_works<Runtime, GrandpaPalletInstance>(
146 collator_session_key: CollatorSessionKeys<Runtime>,
147 runtime_para_id: u32,
148 governance_origin: GovernanceOrigin<RuntimeOriginOf<Runtime>>,
149) where
150 Runtime: BasicParachainRuntime + BridgeGrandpaConfig<GrandpaPalletInstance>,
151 GrandpaPalletInstance: 'static,
152 RuntimeCallOf<Runtime>:
153 GetDispatchInfo + From<BridgeGrandpaCall<Runtime, GrandpaPalletInstance>>,
154{
155 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
156 let dispatch_set_operating_mode_call = |old_mode, new_mode| {
157 assert_eq!(
159 pallet_bridge_grandpa::PalletOperatingMode::<Runtime, GrandpaPalletInstance>::get(),
160 old_mode,
161 );
162
163 let set_operating_mode_call = <Runtime as frame_system::Config>::RuntimeCall::from(
165 pallet_bridge_grandpa::Call::<Runtime, GrandpaPalletInstance>::set_operating_mode {
166 operating_mode: new_mode,
167 },
168 );
169
170 assert_ok!(RuntimeHelper::<Runtime>::execute_as_governance_call(
172 set_operating_mode_call,
173 governance_origin.clone()
174 ));
175
176 assert_eq!(
178 pallet_bridge_grandpa::PalletOperatingMode::<Runtime, GrandpaPalletInstance>::try_get(),
179 Ok(new_mode)
180 );
181 };
182
183 assert_eq!(
185 pallet_bridge_grandpa::PalletOperatingMode::<Runtime, GrandpaPalletInstance>::try_get(),
186 Err(())
187 );
188
189 dispatch_set_operating_mode_call(BasicOperatingMode::Normal, BasicOperatingMode::Halted);
190 dispatch_set_operating_mode_call(BasicOperatingMode::Halted, BasicOperatingMode::Normal);
191 });
192}
193
194pub fn change_bridge_parachains_pallet_mode_by_governance_works<Runtime, ParachainsPalletInstance>(
197 collator_session_key: CollatorSessionKeys<Runtime>,
198 runtime_para_id: u32,
199 governance_origin: GovernanceOrigin<RuntimeOriginOf<Runtime>>,
200) where
201 Runtime: BasicParachainRuntime + BridgeParachainsConfig<ParachainsPalletInstance>,
202 ParachainsPalletInstance: 'static,
203 RuntimeCallOf<Runtime>:
204 GetDispatchInfo + From<BridgeParachainsCall<Runtime, ParachainsPalletInstance>>,
205{
206 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
207 let dispatch_set_operating_mode_call = |old_mode, new_mode| {
208 assert_eq!(
210 pallet_bridge_parachains::PalletOperatingMode::<Runtime, ParachainsPalletInstance>::get(),
211 old_mode,
212 );
213
214 let set_operating_mode_call =
216 RuntimeCallOf::<Runtime>::from(pallet_bridge_parachains::Call::<
217 Runtime,
218 ParachainsPalletInstance,
219 >::set_operating_mode {
220 operating_mode: new_mode,
221 });
222
223 assert_ok!(RuntimeHelper::<Runtime>::execute_as_governance_call(
225 set_operating_mode_call,
226 governance_origin.clone()
227 ));
228
229 assert_eq!(
231 pallet_bridge_parachains::PalletOperatingMode::<Runtime, ParachainsPalletInstance>::try_get(),
232 Ok(new_mode)
233 );
234 };
235
236 assert_eq!(
238 pallet_bridge_parachains::PalletOperatingMode::<Runtime, ParachainsPalletInstance>::try_get(),
239 Err(())
240 );
241
242 dispatch_set_operating_mode_call(BasicOperatingMode::Normal, BasicOperatingMode::Halted);
243 dispatch_set_operating_mode_call(BasicOperatingMode::Halted, BasicOperatingMode::Normal);
244 });
245}
246
247pub fn change_bridge_messages_pallet_mode_by_governance_works<Runtime, MessagesPalletInstance>(
250 collator_session_key: CollatorSessionKeys<Runtime>,
251 runtime_para_id: u32,
252 governance_origin: GovernanceOrigin<RuntimeOriginOf<Runtime>>,
253) where
254 Runtime: BasicParachainRuntime + BridgeMessagesConfig<MessagesPalletInstance>,
255 MessagesPalletInstance: 'static,
256 RuntimeCallOf<Runtime>:
257 GetDispatchInfo + From<BridgeMessagesCall<Runtime, MessagesPalletInstance>>,
258{
259 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
260 let dispatch_set_operating_mode_call = |old_mode, new_mode| {
261 assert_eq!(
263 pallet_bridge_messages::PalletOperatingMode::<Runtime, MessagesPalletInstance>::get(
264 ),
265 old_mode,
266 );
267
268 let set_operating_mode_call = RuntimeCallOf::<Runtime>::from(BridgeMessagesCall::<
270 Runtime,
271 MessagesPalletInstance,
272 >::set_operating_mode {
273 operating_mode: new_mode,
274 });
275
276 assert_ok!(RuntimeHelper::<Runtime>::execute_as_governance_call(
278 set_operating_mode_call,
279 governance_origin.clone()
280 ));
281
282 assert_eq!(
284 pallet_bridge_messages::PalletOperatingMode::<Runtime, MessagesPalletInstance>::try_get(),
285 Ok(new_mode)
286 );
287 };
288
289 assert_eq!(
291 pallet_bridge_messages::PalletOperatingMode::<Runtime, MessagesPalletInstance>::try_get(
292 ),
293 Err(())
294 );
295
296 dispatch_set_operating_mode_call(
297 MessagesOperatingMode::Basic(BasicOperatingMode::Normal),
298 MessagesOperatingMode::RejectingOutboundMessages,
299 );
300 dispatch_set_operating_mode_call(
301 MessagesOperatingMode::RejectingOutboundMessages,
302 MessagesOperatingMode::Basic(BasicOperatingMode::Halted),
303 );
304 dispatch_set_operating_mode_call(
305 MessagesOperatingMode::Basic(BasicOperatingMode::Halted),
306 MessagesOperatingMode::Basic(BasicOperatingMode::Normal),
307 );
308 });
309}
310
311pub fn handle_export_message_from_system_parachain_to_outbound_queue_works<
315 Runtime,
316 XcmConfig,
317 MessagesPalletInstance,
318 LocationToAccountId,
319>(
320 collator_session_key: CollatorSessionKeys<Runtime>,
321 runtime_para_id: u32,
322 sibling_parachain_id: u32,
323 unwrap_pallet_bridge_messages_event: Box<
324 dyn Fn(Vec<u8>) -> Option<pallet_bridge_messages::Event<Runtime, MessagesPalletInstance>>,
325 >,
326 export_message_instruction: fn() -> Instruction<XcmConfig::RuntimeCall>,
327 _existential_deposit: Option<Asset>,
328 maybe_paid_export_message: Option<Asset>,
329 prepare_configuration: impl Fn() -> LaneIdOf<Runtime, MessagesPalletInstance>,
330) where
331 Runtime: BasicParachainRuntime + BridgeMessagesConfig<MessagesPalletInstance>,
332 XcmConfig: xcm_executor::Config,
333 MessagesPalletInstance: 'static,
334 LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>,
335{
336 assert_ne!(runtime_para_id, sibling_parachain_id);
337 let sibling_parachain_location = Location::new(1, [Parachain(sibling_parachain_id)]);
338
339 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
340 let expected_lane_id = prepare_configuration();
341
342 assert_eq!(
344 pallet_bridge_messages::OutboundLanes::<Runtime, MessagesPalletInstance>::try_get(
345 expected_lane_id
346 ),
347 Ok(OutboundLaneData {
348 state: LaneState::Opened,
349 oldest_unpruned_nonce: 1,
350 latest_received_nonce: 0,
351 latest_generated_nonce: 0
352 })
353 );
354
355 let xcm = if let Some(fee) = maybe_paid_export_message {
357 let sibling_account =
360 LocationToAccountId::convert_location(&sibling_parachain_location)
361 .expect("valid location conversion");
362
363 let fee_amount = if let Fungibility::Fungible(amount) = fee.fun {
365 amount
366 } else {
367 panic!("Expected fungible asset for fee");
368 };
369
370 let balance_amount: BalanceOf<Runtime> = fee_amount
372 .try_into()
373 .unwrap_or_else(|_| panic!("Failed to convert fee amount to balance"));
374 <pallet_balances::Pallet<Runtime>>::mint_into(&sibling_account, balance_amount)
375 .expect("minting should succeed");
376
377 Xcm(vec![
378 WithdrawAsset(Assets::from(vec![fee.clone()])),
379 BuyExecution { fees: fee, weight_limit: Unlimited },
380 export_message_instruction(),
381 ])
382 } else {
383 Xcm(vec![
384 UnpaidExecution { weight_limit: Unlimited, check_origin: None },
385 export_message_instruction(),
386 ])
387 };
388
389 let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
391 assert_ok!(XcmExecutor::<XcmConfig>::prepare_and_execute(
392 sibling_parachain_location,
393 xcm,
394 &mut hash,
395 RuntimeHelper::<Runtime>::xcm_max_weight(XcmReceivedFrom::Sibling),
396 Weight::zero(),
397 )
398 .ensure_complete());
399
400 assert_eq!(
402 pallet_bridge_messages::OutboundLanes::<Runtime, MessagesPalletInstance>::try_get(
403 expected_lane_id
404 ),
405 Ok(OutboundLaneData {
406 state: LaneState::Opened,
407 oldest_unpruned_nonce: 1,
408 latest_received_nonce: 0,
409 latest_generated_nonce: 1,
410 })
411 );
412
413 let mut events = <frame_system::Pallet<Runtime>>::events()
415 .into_iter()
416 .filter_map(|e| unwrap_pallet_bridge_messages_event(e.event.encode()));
417 assert!(events.any(|e| matches!(e, pallet_bridge_messages::Event::MessageAccepted { .. })));
418 })
419}
420
421pub fn message_dispatch_routing_works<
427 Runtime,
428 AllPalletsWithoutSystem,
429 XcmConfig,
430 HrmpChannelOpener,
431 MessagesPalletInstance,
432 RuntimeNetwork,
433 BridgedNetwork,
434 NetworkDistanceAsParentCount,
435>(
436 collator_session_key: CollatorSessionKeys<Runtime>,
437 slot_durations: SlotDurations,
438 runtime_para_id: u32,
439 sibling_parachain_id: u32,
440 unwrap_cumulus_pallet_parachain_system_event: Box<
441 dyn Fn(Vec<u8>) -> Option<cumulus_pallet_parachain_system::Event<Runtime>>,
442 >,
443 unwrap_cumulus_pallet_xcmp_queue_event: Box<
444 dyn Fn(Vec<u8>) -> Option<cumulus_pallet_xcmp_queue::Event<Runtime>>,
445 >,
446 prepare_configuration: impl Fn(),
447) where
448 Runtime: BasicParachainRuntime
449 + cumulus_pallet_xcmp_queue::Config
450 + BridgeMessagesConfig<MessagesPalletInstance, InboundPayload = test_data::XcmAsPlainPayload>,
451 AllPalletsWithoutSystem:
452 OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>,
453 AccountIdOf<Runtime>: From<AccountId32>
454 + Into<<<Runtime as frame_system::Config>::RuntimeOrigin as OriginTrait>::AccountId>,
455 XcmConfig: xcm_executor::Config,
456 MessagesPalletInstance: 'static,
457 HrmpChannelOpener: frame_support::inherent::ProvideInherent<
458 Call = cumulus_pallet_parachain_system::Call<Runtime>,
459 >,
460 RuntimeNetwork: Get<NetworkId>,
461 BridgedNetwork: Get<NetworkId>,
462 NetworkDistanceAsParentCount: Get<u8>,
463{
464 struct NetworkWithParentCount<N, C>(core::marker::PhantomData<(N, C)>);
465 impl<N: Get<NetworkId>, C: Get<u8>> Get<Location> for NetworkWithParentCount<N, C> {
466 fn get() -> Location {
467 Location::new(C::get(), [GlobalConsensus(N::get())])
468 }
469 }
470 assert_ne!(runtime_para_id, sibling_parachain_id);
471
472 #[derive(Debug)]
473 enum XcmBlobMessageDispatchResult {
474 Dispatched,
475 #[allow(dead_code)]
476 NotDispatched(Option<DispatchBlobError>),
477 }
478
479 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
480 prepare_configuration();
481
482 let dummy_lane_id = LaneIdOf::<Runtime, MessagesPalletInstance>::default();
483 let mut alice = [0u8; 32];
484 alice[0] = 1;
485
486 let included_head = RuntimeHelper::<Runtime, AllPalletsWithoutSystem>::run_to_block(
487 2,
488 AccountId::from(alice).into(),
489 );
490 let bridging_message = test_data::simulate_message_exporter_on_bridged_chain::<
493 BridgedNetwork,
494 NetworkWithParentCount<RuntimeNetwork, NetworkDistanceAsParentCount>,
495 AlwaysLatest,
496 >((RuntimeNetwork::get(), Here));
497 let result =
498 <<Runtime as BridgeMessagesConfig<MessagesPalletInstance>>::MessageDispatch>::dispatch(
499 test_data::dispatch_message(dummy_lane_id, 1, bridging_message),
500 );
501 assert_eq!(
502 format!("{:?}", result.dispatch_level_result),
503 format!("{:?}", XcmBlobMessageDispatchResult::Dispatched)
504 );
505
506 let mut events = <frame_system::Pallet<Runtime>>::events()
508 .into_iter()
509 .filter_map(|e| unwrap_cumulus_pallet_parachain_system_event(e.event.encode()));
510 assert!(events.any(|e| matches!(
511 e,
512 cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
513 )));
514
515 let bridging_message =
518 test_data::simulate_message_exporter_on_bridged_chain::<
519 BridgedNetwork,
520 NetworkWithParentCount<RuntimeNetwork, NetworkDistanceAsParentCount>,
521 AlwaysLatest,
522 >((RuntimeNetwork::get(), [Parachain(sibling_parachain_id)].into()));
523
524 let result =
526 <<Runtime as BridgeMessagesConfig<MessagesPalletInstance>>::MessageDispatch>::dispatch(
527 DispatchMessage {
528 key: MessageKey { lane_id: dummy_lane_id, nonce: 1 },
529 data: DispatchMessageData { payload: Ok(bridging_message.clone()) },
530 },
531 );
532 assert_eq!(
533 format!("{:?}", result.dispatch_level_result),
534 format!(
535 "{:?}",
536 XcmBlobMessageDispatchResult::NotDispatched(Some(DispatchBlobError::RoutingError))
537 )
538 );
539
540 assert_eq!(
542 <frame_system::Pallet<Runtime>>::events()
543 .into_iter()
544 .filter_map(|e| unwrap_cumulus_pallet_xcmp_queue_event(e.event.encode()))
545 .count(),
546 0
547 );
548
549 mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(
551 runtime_para_id.into(),
552 sibling_parachain_id.into(),
553 included_head,
554 &alice,
555 &slot_durations,
556 );
557 let result =
558 <<Runtime as BridgeMessagesConfig<MessagesPalletInstance>>::MessageDispatch>::dispatch(
559 DispatchMessage {
560 key: MessageKey { lane_id: dummy_lane_id, nonce: 1 },
561 data: DispatchMessageData { payload: Ok(bridging_message) },
562 },
563 );
564 assert_eq!(
565 format!("{:?}", result.dispatch_level_result),
566 format!("{:?}", XcmBlobMessageDispatchResult::Dispatched)
567 );
568
569 let mut events = <frame_system::Pallet<Runtime>>::events()
571 .into_iter()
572 .filter_map(|e| unwrap_cumulus_pallet_xcmp_queue_event(e.event.encode()));
573 assert!(
574 events.any(|e| matches!(e, cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }))
575 );
576 })
577}
578
579pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer<
581 Runtime,
582 XcmConfig,
583 WeightToFee,
584>() -> u128
585where
586 Runtime: frame_system::Config + pallet_balances::Config,
587 XcmConfig: xcm_executor::Config,
588 WeightToFee: frame_support::weights::WeightToFee<Balance = BalanceOf<Runtime>>,
589 <WeightToFee as frame_support::weights::WeightToFee>::Balance: From<u128> + Into<u128>,
590{
591 let mut xcm = Xcm(vec![
593 WithdrawAsset(Assets::from(vec![Asset {
594 id: AssetId(Location::new(1, [])),
595 fun: Fungible(34333299),
596 }])),
597 BuyExecution {
598 fees: Asset { id: AssetId(Location::new(1, [])), fun: Fungible(34333299) },
599 weight_limit: Unlimited,
600 },
601 SetAppendix(Xcm(vec![DepositAsset {
602 assets: Wild(AllCounted(1)),
603 beneficiary: Location::new(1, [Parachain(1000)]),
604 }])),
605 ExportMessage {
606 network: Polkadot,
607 destination: [Parachain(1000)].into(),
608 xcm: Xcm(vec![
609 ReserveAssetDeposited(Assets::from(vec![Asset {
610 id: AssetId(Location::new(2, [GlobalConsensus(Kusama)])),
611 fun: Fungible(1000000000000),
612 }])),
613 ClearOrigin,
614 BuyExecution {
615 fees: Asset {
616 id: AssetId(Location::new(2, [GlobalConsensus(Kusama)])),
617 fun: Fungible(1000000000000),
618 },
619 weight_limit: Unlimited,
620 },
621 DepositAsset {
622 assets: Wild(AllCounted(1)),
623 beneficiary: Location::new(
624 0,
625 [xcm::latest::prelude::AccountId32 {
626 network: None,
627 id: [
628 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159,
629 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165,
630 109, 162, 125,
631 ],
632 }],
633 ),
634 },
635 SetTopic([
636 116, 82, 194, 132, 171, 114, 217, 165, 23, 37, 161, 177, 165, 179, 247, 114,
637 137, 101, 147, 70, 28, 157, 168, 32, 154, 63, 74, 228, 152, 180, 5, 63,
638 ]),
639 ]),
640 },
641 SetTopic([
642 36, 224, 250, 165, 82, 195, 67, 110, 160, 170, 140, 87, 217, 62, 201, 164, 42, 98, 219,
643 157, 124, 105, 248, 25, 131, 218, 199, 36, 109, 173, 100, 122,
644 ]),
645 ]);
646
647 let weight = XcmConfig::Weigher::weight(&mut xcm, Weight::MAX);
649 assert_ok!(weight);
650 let weight = weight.unwrap();
651 let max_expected = Runtime::BlockWeights::get().max_block / 10;
653 assert!(
654 weight.all_lte(max_expected),
655 "calculated weight: {:?}, max_expected: {:?}",
656 weight,
657 max_expected
658 );
659
660 let estimated_fee = WeightToFee::weight_to_fee(&weight);
662 assert!(estimated_fee > BalanceOf::<Runtime>::zero());
663
664 estimated_fee.into()
665}
666
667pub(crate) mod for_pallet_xcm_bridge_hub {
668 use super::*;
669 use crate::test_cases::helpers::for_pallet_xcm_bridge_hub::{
670 close_bridge, ensure_opened_bridge, open_bridge_with_extrinsic,
671 };
672 pub(crate) use pallet_xcm_bridge_hub::{
673 Bridge, BridgeState, Call as BridgeXcmOverBridgeCall, Config as BridgeXcmOverBridgeConfig,
674 LanesManagerOf,
675 };
676
677 pub fn open_and_close_bridge_works<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>(
679 collator_session_key: CollatorSessionKeys<Runtime>,
680 runtime_para_id: u32,
681 expected_source: Location,
682 destination: InteriorLocation,
683 origin_with_origin_kind: (Location, OriginKind),
684 is_paid_xcm_execution: bool,
685 ) where
686 Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>,
687 XcmOverBridgePalletInstance: 'static,
688 <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>,
689 <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>,
690 <Runtime as pallet_balances::Config>::Balance: From<u128>,
691 <<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::AccountId: From<<Runtime as frame_system::Config>::AccountId>,
692 LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>,
693 TokenLocation: Get<Location>,
694 {
695 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
696 let locations = pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations(
698 expected_source.clone().into(),
699 destination.clone().into(),
700 ).expect("valid bridge locations");
701 let expected_lane_id =
702 locations.calculate_lane_id(xcm::latest::VERSION).expect("valid laneId");
703 let lanes_manager = LanesManagerOf::<Runtime, XcmOverBridgePalletInstance>::new();
704
705 let expected_deposit = if <Runtime as pallet_xcm_bridge_hub::Config<
706 XcmOverBridgePalletInstance,
707 >>::AllowWithoutBridgeDeposit::contains(
708 locations.bridge_origin_relative_location()
709 ) {
710 Zero::zero()
711 } else {
712 <Runtime as pallet_xcm_bridge_hub::Config<
713 XcmOverBridgePalletInstance,
714 >>::BridgeDeposit::get()
715 };
716
717 assert_eq!(
719 pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get(
720 locations.bridge_id()
721 ),
722 None
723 );
724 assert_eq!(
725 lanes_manager.active_inbound_lane(expected_lane_id).map(drop),
726 Err(LanesManagerError::UnknownInboundLane)
727 );
728 assert_eq!(
729 lanes_manager.active_outbound_lane(expected_lane_id).map(drop),
730 Err(LanesManagerError::UnknownOutboundLane)
731 );
732
733 assert_eq!(
735 ensure_opened_bridge::<
736 Runtime,
737 XcmOverBridgePalletInstance,
738 LocationToAccountId,
739 TokenLocation,
740 >(
741 expected_source.clone(),
742 destination.clone(),
743 is_paid_xcm_execution,
744 |locations, maybe_paid_execution| open_bridge_with_extrinsic::<
745 Runtime,
746 XcmOverBridgePalletInstance,
747 >(
748 origin_with_origin_kind.clone(),
749 locations.bridge_destination_universal_location().clone(),
750 maybe_paid_execution
751 )
752 )
753 .0
754 .bridge_id(),
755 locations.bridge_id()
756 );
757
758 assert_eq!(
760 pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get(
761 locations.bridge_id()
762 ),
763 Some(Bridge {
764 bridge_origin_relative_location: Box::new(expected_source.clone().into()),
765 bridge_origin_universal_location: Box::new(
766 locations.bridge_origin_universal_location().clone().into()
767 ),
768 bridge_destination_universal_location: Box::new(
769 locations.bridge_destination_universal_location().clone().into()
770 ),
771 state: BridgeState::Opened,
772 bridge_owner_account: LocationToAccountId::convert_location(&expected_source)
773 .expect("valid location")
774 .into(),
775 deposit: expected_deposit,
776 lane_id: expected_lane_id,
777 })
778 );
779 assert_eq!(
780 lanes_manager.active_inbound_lane(expected_lane_id).map(|lane| lane.state()),
781 Ok(LaneState::Opened)
782 );
783 assert_eq!(
784 lanes_manager.active_outbound_lane(expected_lane_id).map(|lane| lane.state()),
785 Ok(LaneState::Opened)
786 );
787
788 close_bridge::<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>(
790 expected_source,
791 destination,
792 origin_with_origin_kind,
793 is_paid_xcm_execution,
794 );
795
796 assert_eq!(
798 pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get(
799 locations.bridge_id()
800 ),
801 None
802 );
803 assert_eq!(
804 lanes_manager.active_inbound_lane(expected_lane_id).map(drop),
805 Err(LanesManagerError::UnknownInboundLane)
806 );
807 assert_eq!(
808 lanes_manager.active_outbound_lane(expected_lane_id).map(drop),
809 Err(LanesManagerError::UnknownOutboundLane)
810 );
811 });
812 }
813}