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::{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, TransactAsset, 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>(
319 collator_session_key: CollatorSessionKeys<Runtime>,
320 runtime_para_id: u32,
321 sibling_parachain_id: u32,
322 unwrap_pallet_bridge_messages_event: Box<
323 dyn Fn(Vec<u8>) -> Option<pallet_bridge_messages::Event<Runtime, MessagesPalletInstance>>,
324 >,
325 export_message_instruction: fn() -> Instruction<XcmConfig::RuntimeCall>,
326 existential_deposit: Option<Asset>,
327 maybe_paid_export_message: Option<Asset>,
328 prepare_configuration: impl Fn() -> LaneIdOf<Runtime, MessagesPalletInstance>,
329) where
330 Runtime: BasicParachainRuntime + BridgeMessagesConfig<MessagesPalletInstance>,
331 XcmConfig: xcm_executor::Config,
332 MessagesPalletInstance: 'static,
333{
334 assert_ne!(runtime_para_id, sibling_parachain_id);
335 let sibling_parachain_location = Location::new(1, [Parachain(sibling_parachain_id)]);
336
337 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
338 let expected_lane_id = prepare_configuration();
339
340 assert_eq!(
342 pallet_bridge_messages::OutboundLanes::<Runtime, MessagesPalletInstance>::try_get(
343 expected_lane_id
344 ),
345 Ok(OutboundLaneData {
346 state: LaneState::Opened,
347 oldest_unpruned_nonce: 1,
348 latest_received_nonce: 0,
349 latest_generated_nonce: 0
350 })
351 );
352
353 let xcm = if let Some(fee) = maybe_paid_export_message {
355 if let Some(ed) = existential_deposit {
357 XcmConfig::AssetTransactor::deposit_asset(
358 &ed,
359 &sibling_parachain_location,
360 Some(&XcmContext::with_message_id([0; 32])),
361 )
362 .expect("deposited ed");
363 }
364 XcmConfig::AssetTransactor::deposit_asset(
366 &fee,
367 &sibling_parachain_location,
368 Some(&XcmContext::with_message_id([0; 32])),
369 )
370 .expect("deposited fee");
371
372 Xcm(vec![
373 WithdrawAsset(Assets::from(vec![fee.clone()])),
374 BuyExecution { fees: fee, weight_limit: Unlimited },
375 export_message_instruction(),
376 ])
377 } else {
378 Xcm(vec![
379 UnpaidExecution { weight_limit: Unlimited, check_origin: None },
380 export_message_instruction(),
381 ])
382 };
383
384 let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
386 assert_ok!(XcmExecutor::<XcmConfig>::prepare_and_execute(
387 sibling_parachain_location,
388 xcm,
389 &mut hash,
390 RuntimeHelper::<Runtime>::xcm_max_weight(XcmReceivedFrom::Sibling),
391 Weight::zero(),
392 )
393 .ensure_complete());
394
395 assert_eq!(
397 pallet_bridge_messages::OutboundLanes::<Runtime, MessagesPalletInstance>::try_get(
398 expected_lane_id
399 ),
400 Ok(OutboundLaneData {
401 state: LaneState::Opened,
402 oldest_unpruned_nonce: 1,
403 latest_received_nonce: 0,
404 latest_generated_nonce: 1,
405 })
406 );
407
408 let mut events = <frame_system::Pallet<Runtime>>::events()
410 .into_iter()
411 .filter_map(|e| unwrap_pallet_bridge_messages_event(e.event.encode()));
412 assert!(events.any(|e| matches!(e, pallet_bridge_messages::Event::MessageAccepted { .. })));
413 })
414}
415
416pub fn message_dispatch_routing_works<
422 Runtime,
423 AllPalletsWithoutSystem,
424 XcmConfig,
425 HrmpChannelOpener,
426 MessagesPalletInstance,
427 RuntimeNetwork,
428 BridgedNetwork,
429 NetworkDistanceAsParentCount,
430>(
431 collator_session_key: CollatorSessionKeys<Runtime>,
432 slot_durations: SlotDurations,
433 runtime_para_id: u32,
434 sibling_parachain_id: u32,
435 unwrap_cumulus_pallet_parachain_system_event: Box<
436 dyn Fn(Vec<u8>) -> Option<cumulus_pallet_parachain_system::Event<Runtime>>,
437 >,
438 unwrap_cumulus_pallet_xcmp_queue_event: Box<
439 dyn Fn(Vec<u8>) -> Option<cumulus_pallet_xcmp_queue::Event<Runtime>>,
440 >,
441 prepare_configuration: impl Fn(),
442) where
443 Runtime: BasicParachainRuntime
444 + cumulus_pallet_xcmp_queue::Config
445 + BridgeMessagesConfig<MessagesPalletInstance, InboundPayload = test_data::XcmAsPlainPayload>,
446 AllPalletsWithoutSystem:
447 OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>,
448 AccountIdOf<Runtime>: From<AccountId32>
449 + Into<<<Runtime as frame_system::Config>::RuntimeOrigin as OriginTrait>::AccountId>,
450 XcmConfig: xcm_executor::Config,
451 MessagesPalletInstance: 'static,
452 HrmpChannelOpener: frame_support::inherent::ProvideInherent<
453 Call = cumulus_pallet_parachain_system::Call<Runtime>,
454 >,
455 RuntimeNetwork: Get<NetworkId>,
456 BridgedNetwork: Get<NetworkId>,
457 NetworkDistanceAsParentCount: Get<u8>,
458{
459 struct NetworkWithParentCount<N, C>(core::marker::PhantomData<(N, C)>);
460 impl<N: Get<NetworkId>, C: Get<u8>> Get<Location> for NetworkWithParentCount<N, C> {
461 fn get() -> Location {
462 Location::new(C::get(), [GlobalConsensus(N::get())])
463 }
464 }
465 assert_ne!(runtime_para_id, sibling_parachain_id);
466
467 #[derive(Debug)]
468 enum XcmBlobMessageDispatchResult {
469 Dispatched,
470 #[allow(dead_code)]
471 NotDispatched(Option<DispatchBlobError>),
472 }
473
474 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
475 prepare_configuration();
476
477 let dummy_lane_id = LaneIdOf::<Runtime, MessagesPalletInstance>::default();
478 let mut alice = [0u8; 32];
479 alice[0] = 1;
480
481 let included_head = RuntimeHelper::<Runtime, AllPalletsWithoutSystem>::run_to_block(
482 2,
483 AccountId::from(alice).into(),
484 );
485 let bridging_message = test_data::simulate_message_exporter_on_bridged_chain::<
488 BridgedNetwork,
489 NetworkWithParentCount<RuntimeNetwork, NetworkDistanceAsParentCount>,
490 AlwaysLatest,
491 >((RuntimeNetwork::get(), Here));
492 let result =
493 <<Runtime as BridgeMessagesConfig<MessagesPalletInstance>>::MessageDispatch>::dispatch(
494 test_data::dispatch_message(dummy_lane_id, 1, bridging_message),
495 );
496 assert_eq!(
497 format!("{:?}", result.dispatch_level_result),
498 format!("{:?}", XcmBlobMessageDispatchResult::Dispatched)
499 );
500
501 let mut events = <frame_system::Pallet<Runtime>>::events()
503 .into_iter()
504 .filter_map(|e| unwrap_cumulus_pallet_parachain_system_event(e.event.encode()));
505 assert!(events.any(|e| matches!(
506 e,
507 cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
508 )));
509
510 let bridging_message =
513 test_data::simulate_message_exporter_on_bridged_chain::<
514 BridgedNetwork,
515 NetworkWithParentCount<RuntimeNetwork, NetworkDistanceAsParentCount>,
516 AlwaysLatest,
517 >((RuntimeNetwork::get(), [Parachain(sibling_parachain_id)].into()));
518
519 let result =
521 <<Runtime as BridgeMessagesConfig<MessagesPalletInstance>>::MessageDispatch>::dispatch(
522 DispatchMessage {
523 key: MessageKey { lane_id: dummy_lane_id, nonce: 1 },
524 data: DispatchMessageData { payload: Ok(bridging_message.clone()) },
525 },
526 );
527 assert_eq!(
528 format!("{:?}", result.dispatch_level_result),
529 format!(
530 "{:?}",
531 XcmBlobMessageDispatchResult::NotDispatched(Some(DispatchBlobError::RoutingError))
532 )
533 );
534
535 assert_eq!(
537 <frame_system::Pallet<Runtime>>::events()
538 .into_iter()
539 .filter_map(|e| unwrap_cumulus_pallet_xcmp_queue_event(e.event.encode()))
540 .count(),
541 0
542 );
543
544 mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(
546 runtime_para_id.into(),
547 sibling_parachain_id.into(),
548 included_head,
549 &alice,
550 &slot_durations,
551 );
552 let result =
553 <<Runtime as BridgeMessagesConfig<MessagesPalletInstance>>::MessageDispatch>::dispatch(
554 DispatchMessage {
555 key: MessageKey { lane_id: dummy_lane_id, nonce: 1 },
556 data: DispatchMessageData { payload: Ok(bridging_message) },
557 },
558 );
559 assert_eq!(
560 format!("{:?}", result.dispatch_level_result),
561 format!("{:?}", XcmBlobMessageDispatchResult::Dispatched)
562 );
563
564 let mut events = <frame_system::Pallet<Runtime>>::events()
566 .into_iter()
567 .filter_map(|e| unwrap_cumulus_pallet_xcmp_queue_event(e.event.encode()));
568 assert!(
569 events.any(|e| matches!(e, cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }))
570 );
571 })
572}
573
574pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer<
576 Runtime,
577 XcmConfig,
578 WeightToFee,
579>() -> u128
580where
581 Runtime: frame_system::Config + pallet_balances::Config,
582 XcmConfig: xcm_executor::Config,
583 WeightToFee: frame_support::weights::WeightToFee<Balance = BalanceOf<Runtime>>,
584 <WeightToFee as frame_support::weights::WeightToFee>::Balance: From<u128> + Into<u128>,
585{
586 let mut xcm = Xcm(vec![
588 WithdrawAsset(Assets::from(vec![Asset {
589 id: AssetId(Location::new(1, [])),
590 fun: Fungible(34333299),
591 }])),
592 BuyExecution {
593 fees: Asset { id: AssetId(Location::new(1, [])), fun: Fungible(34333299) },
594 weight_limit: Unlimited,
595 },
596 SetAppendix(Xcm(vec![DepositAsset {
597 assets: Wild(AllCounted(1)),
598 beneficiary: Location::new(1, [Parachain(1000)]),
599 }])),
600 ExportMessage {
601 network: Polkadot,
602 destination: [Parachain(1000)].into(),
603 xcm: Xcm(vec![
604 ReserveAssetDeposited(Assets::from(vec![Asset {
605 id: AssetId(Location::new(2, [GlobalConsensus(Kusama)])),
606 fun: Fungible(1000000000000),
607 }])),
608 ClearOrigin,
609 BuyExecution {
610 fees: Asset {
611 id: AssetId(Location::new(2, [GlobalConsensus(Kusama)])),
612 fun: Fungible(1000000000000),
613 },
614 weight_limit: Unlimited,
615 },
616 DepositAsset {
617 assets: Wild(AllCounted(1)),
618 beneficiary: Location::new(
619 0,
620 [xcm::latest::prelude::AccountId32 {
621 network: None,
622 id: [
623 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159,
624 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165,
625 109, 162, 125,
626 ],
627 }],
628 ),
629 },
630 SetTopic([
631 116, 82, 194, 132, 171, 114, 217, 165, 23, 37, 161, 177, 165, 179, 247, 114,
632 137, 101, 147, 70, 28, 157, 168, 32, 154, 63, 74, 228, 152, 180, 5, 63,
633 ]),
634 ]),
635 },
636 SetTopic([
637 36, 224, 250, 165, 82, 195, 67, 110, 160, 170, 140, 87, 217, 62, 201, 164, 42, 98, 219,
638 157, 124, 105, 248, 25, 131, 218, 199, 36, 109, 173, 100, 122,
639 ]),
640 ]);
641
642 let weight = XcmConfig::Weigher::weight(&mut xcm, Weight::MAX);
644 assert_ok!(weight);
645 let weight = weight.unwrap();
646 let max_expected = Runtime::BlockWeights::get().max_block / 10;
648 assert!(
649 weight.all_lte(max_expected),
650 "calculated weight: {:?}, max_expected: {:?}",
651 weight,
652 max_expected
653 );
654
655 let estimated_fee = WeightToFee::weight_to_fee(&weight);
657 assert!(estimated_fee > BalanceOf::<Runtime>::zero());
658
659 estimated_fee.into()
660}
661
662pub(crate) mod for_pallet_xcm_bridge_hub {
663 use super::*;
664 use crate::test_cases::helpers::for_pallet_xcm_bridge_hub::{
665 close_bridge, ensure_opened_bridge, open_bridge_with_extrinsic,
666 };
667 pub(crate) use pallet_xcm_bridge_hub::{
668 Bridge, BridgeState, Call as BridgeXcmOverBridgeCall, Config as BridgeXcmOverBridgeConfig,
669 LanesManagerOf,
670 };
671
672 pub fn open_and_close_bridge_works<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>(
674 collator_session_key: CollatorSessionKeys<Runtime>,
675 runtime_para_id: u32,
676 expected_source: Location,
677 destination: InteriorLocation,
678 origin_with_origin_kind: (Location, OriginKind),
679 is_paid_xcm_execution: bool,
680 ) where
681 Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>,
682 XcmOverBridgePalletInstance: 'static,
683 <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>,
684 <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>,
685 <Runtime as pallet_balances::Config>::Balance: From<u128>,
686 <<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>,
687 LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>,
688 TokenLocation: Get<Location>,
689 {
690 run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || {
691 let locations = pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations(
693 expected_source.clone().into(),
694 destination.clone().into(),
695 ).expect("valid bridge locations");
696 let expected_lane_id =
697 locations.calculate_lane_id(xcm::latest::VERSION).expect("valid laneId");
698 let lanes_manager = LanesManagerOf::<Runtime, XcmOverBridgePalletInstance>::new();
699
700 let expected_deposit = if <Runtime as pallet_xcm_bridge_hub::Config<
701 XcmOverBridgePalletInstance,
702 >>::AllowWithoutBridgeDeposit::contains(
703 locations.bridge_origin_relative_location()
704 ) {
705 Zero::zero()
706 } else {
707 <Runtime as pallet_xcm_bridge_hub::Config<
708 XcmOverBridgePalletInstance,
709 >>::BridgeDeposit::get()
710 };
711
712 assert_eq!(
714 pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get(
715 locations.bridge_id()
716 ),
717 None
718 );
719 assert_eq!(
720 lanes_manager.active_inbound_lane(expected_lane_id).map(drop),
721 Err(LanesManagerError::UnknownInboundLane)
722 );
723 assert_eq!(
724 lanes_manager.active_outbound_lane(expected_lane_id).map(drop),
725 Err(LanesManagerError::UnknownOutboundLane)
726 );
727
728 assert_eq!(
730 ensure_opened_bridge::<
731 Runtime,
732 XcmOverBridgePalletInstance,
733 LocationToAccountId,
734 TokenLocation,
735 >(
736 expected_source.clone(),
737 destination.clone(),
738 is_paid_xcm_execution,
739 |locations, maybe_paid_execution| open_bridge_with_extrinsic::<
740 Runtime,
741 XcmOverBridgePalletInstance,
742 >(
743 origin_with_origin_kind.clone(),
744 locations.bridge_destination_universal_location().clone(),
745 maybe_paid_execution
746 )
747 )
748 .0
749 .bridge_id(),
750 locations.bridge_id()
751 );
752
753 assert_eq!(
755 pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get(
756 locations.bridge_id()
757 ),
758 Some(Bridge {
759 bridge_origin_relative_location: Box::new(expected_source.clone().into()),
760 bridge_origin_universal_location: Box::new(
761 locations.bridge_origin_universal_location().clone().into()
762 ),
763 bridge_destination_universal_location: Box::new(
764 locations.bridge_destination_universal_location().clone().into()
765 ),
766 state: BridgeState::Opened,
767 bridge_owner_account: LocationToAccountId::convert_location(&expected_source)
768 .expect("valid location")
769 .into(),
770 deposit: expected_deposit,
771 lane_id: expected_lane_id,
772 })
773 );
774 assert_eq!(
775 lanes_manager.active_inbound_lane(expected_lane_id).map(|lane| lane.state()),
776 Ok(LaneState::Opened)
777 );
778 assert_eq!(
779 lanes_manager.active_outbound_lane(expected_lane_id).map(|lane| lane.state()),
780 Ok(LaneState::Opened)
781 );
782
783 close_bridge::<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>(
785 expected_source,
786 destination,
787 origin_with_origin_kind,
788 is_paid_xcm_execution,
789 );
790
791 assert_eq!(
793 pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get(
794 locations.bridge_id()
795 ),
796 None
797 );
798 assert_eq!(
799 lanes_manager.active_inbound_lane(expected_lane_id).map(drop),
800 Err(LanesManagerError::UnknownInboundLane)
801 );
802 assert_eq!(
803 lanes_manager.active_outbound_lane(expected_lane_id).map(drop),
804 Err(LanesManagerError::UnknownOutboundLane)
805 );
806 });
807 }
808}