From 47155f85a877e8c26b2249e31cdb4deb485b4067 Mon Sep 17 00:00:00 2001 From: "paritytech-cmd-bot-polkadot-sdk[bot]" <179002856+paritytech-cmd-bot-polkadot-sdk[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 22:29:22 +0200 Subject: [PATCH] [stable2407] Backport #5913 (#6004) Backport #5913 into `stable2407` from franciscoaguirre. See the [documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md) on how to use this bot. --------- Co-authored-by: Francisco Aguirre Co-authored-by: Egor_P --- Cargo.lock | 5 + .../modules/xcm-bridge-hub-router/src/lib.rs | 35 +- cumulus/pallets/parachain-system/src/lib.rs | 6 +- .../emulated/common/src/macros.rs | 320 ++++++++++++++++++ .../bridges/bridge-hub-rococo/Cargo.toml | 3 + .../bridges/bridge-hub-rococo/src/lib.rs | 2 +- .../src/tests/asset_transfers.rs | 9 + .../bridges/bridge-hub-westend/Cargo.toml | 3 + .../bridges/bridge-hub-westend/src/lib.rs | 2 +- .../src/tests/asset_transfers.rs | 9 + .../xcm/xcm-builder/src/universal_exports.rs | 10 +- prdoc/pr_6004.prdoc | 20 ++ 12 files changed, 388 insertions(+), 36 deletions(-) create mode 100644 prdoc/pr_6004.prdoc diff --git a/Cargo.lock b/Cargo.lock index 03993fa614c2..bd7a29278a3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1997,6 +1997,7 @@ dependencies = [ "pallet-bridge-messages", "pallet-message-queue", "pallet-xcm", + "pallet-xcm-bridge-hub", "parachains-common", "parity-scale-codec", "rococo-system-emulated-network", @@ -2012,6 +2013,7 @@ dependencies = [ "staging-xcm", "staging-xcm-executor", "testnet-parachains-constants", + "xcm-runtime-apis", ] [[package]] @@ -2179,11 +2181,14 @@ dependencies = [ "pallet-bridge-messages", "pallet-message-queue", "pallet-xcm", + "pallet-xcm-bridge-hub", "parachains-common", "rococo-westend-system-emulated-network", + "sp-core", "sp-runtime", "staging-xcm", "staging-xcm-executor", + "xcm-runtime-apis", ] [[package]] diff --git a/bridges/modules/xcm-bridge-hub-router/src/lib.rs b/bridges/modules/xcm-bridge-hub-router/src/lib.rs index 8b86029ab8ff..3c56f54a72bc 100644 --- a/bridges/modules/xcm-bridge-hub-router/src/lib.rs +++ b/bridges/modules/xcm-bridge-hub-router/src/lib.rs @@ -96,7 +96,7 @@ pub mod pallet { /// Origin of the sibling bridge hub that is allowed to report bridge status. type BridgeHubOrigin: EnsureOrigin; /// Actual message sender (`HRMP` or `DMP`) to the sibling bridge hub location. - type ToBridgeHubSender: SendXcm + InspectMessageQueues; + type ToBridgeHubSender: SendXcm; /// Underlying channel with the sibling bridge hub. It must match the channel, used /// by the `Self::ToBridgeHubSender`. type WithBridgeHubChannel: XcmChannelStatusProvider; @@ -398,12 +398,12 @@ impl, I: 'static> SendXcm for Pallet { } impl, I: 'static> InspectMessageQueues for Pallet { - fn clear_messages() { - ViaBridgeHubExporter::::clear_messages() - } + fn clear_messages() {} + /// This router needs to implement `InspectMessageQueues` but doesn't have to + /// return any messages, since it just reuses the `XcmpQueue` router. fn get_messages() -> Vec<(VersionedLocation, Vec>)> { - ViaBridgeHubExporter::::get_messages() + Vec::new() } } @@ -648,34 +648,13 @@ mod tests { } #[test] - fn get_messages_works() { + fn get_messages_does_not_return_anything() { run_test(|| { assert_ok!(send_xcm::( (Parent, Parent, GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)).into(), vec![ClearOrigin].into() )); - assert_eq!( - XcmBridgeHubRouter::get_messages(), - vec![( - VersionedLocation::V4((Parent, Parachain(1002)).into()), - vec![VersionedXcm::V4( - Xcm::builder() - .withdraw_asset((Parent, 1_002_000)) - .buy_execution((Parent, 1_002_000), Unlimited) - .set_appendix( - Xcm::builder_unsafe() - .deposit_asset(AllCounted(1), (Parent, Parachain(1000))) - .build() - ) - .export_message( - Kusama, - Parachain(1000), - Xcm::builder_unsafe().clear_origin().build() - ) - .build() - )], - ),], - ); + assert_eq!(XcmBridgeHubRouter::get_messages(), vec![]); }); } } diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index 7f0bfceff252..6f8adaa461c5 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -1623,7 +1623,11 @@ impl InspectMessageQueues for Pallet { .map(|encoded_message| VersionedXcm::<()>::decode(&mut &encoded_message[..]).unwrap()) .collect(); - vec![(VersionedLocation::V4(Parent.into()), messages)] + if messages.is_empty() { + vec![] + } else { + vec![(VersionedLocation::from(Location::parent()), messages)] + } } } diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index 6f6bbe41e01b..f12907de914a 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -130,3 +130,323 @@ macro_rules! test_parachain_is_trusted_teleporter { } }; } + +#[macro_export] +macro_rules! test_relay_is_trusted_teleporter { + ( $sender_relay:ty, $sender_xcm_config:ty, vec![$( $receiver_para:ty ),+], ($assets:expr, $amount:expr) ) => { + $crate::macros::paste::paste! { + // init Origin variables + let sender = [<$sender_relay Sender>]::get(); + let mut relay_sender_balance_before = + <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free; + let origin = <$sender_relay as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone()); + let fee_asset_item = 0; + let weight_limit = $crate::macros::WeightLimit::Unlimited; + + $( + { + // init Destination variables + let receiver = [<$receiver_para Receiver>]::get(); + let para_receiver_balance_before = + <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free; + let para_destination = + <$sender_relay>::child_location_of(<$receiver_para>::para_id()); + let beneficiary: Location = + $crate::macros::AccountId32 { network: None, id: receiver.clone().into() }.into(); + + // Send XCM message from Relay + <$sender_relay>::execute_with(|| { + assert_ok!(<$sender_relay as [<$sender_relay Pallet>]>::XcmPallet::limited_teleport_assets( + origin.clone(), + bx!(para_destination.clone().into()), + bx!(beneficiary.clone().into()), + bx!($assets.clone().into()), + fee_asset_item, + weight_limit.clone(), + )); + + type RuntimeEvent = <$sender_relay as $crate::macros::Chain>::RuntimeEvent; + + assert_expected_events!( + $sender_relay, + vec![ + RuntimeEvent::XcmPallet( + $crate::macros::pallet_xcm::Event::Attempted { outcome: Outcome::Complete { .. } } + ) => {}, + RuntimeEvent::Balances( + $crate::macros::pallet_balances::Event::Burned { who: sender, amount } + ) => {}, + RuntimeEvent::XcmPallet( + $crate::macros::pallet_xcm::Event::Sent { .. } + ) => {}, + ] + ); + }); + + // Receive XCM message in Destination Parachain + <$receiver_para>::execute_with(|| { + type RuntimeEvent = <$receiver_para as $crate::macros::Chain>::RuntimeEvent; + + assert_expected_events!( + $receiver_para, + vec![ + RuntimeEvent::Balances( + $crate::macros::pallet_balances::Event::Minted { who: receiver, .. } + ) => {}, + RuntimeEvent::MessageQueue( + $crate::macros::pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + ] + ); + }); + + // Check if balances are updated accordingly in Origin and Parachain + let relay_sender_balance_after = + <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free; + let para_receiver_balance_after = + <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free; + let delivery_fees = <$sender_relay>::execute_with(|| { + $crate::macros::asset_test_utils::xcm_helpers::teleport_assets_delivery_fees::< + <$sender_xcm_config as xcm_executor::Config>::XcmSender, + >($assets.clone(), fee_asset_item, weight_limit.clone(), beneficiary, para_destination) + }); + + assert_eq!(relay_sender_balance_before - $amount - delivery_fees, relay_sender_balance_after); + assert!(para_receiver_balance_after > para_receiver_balance_before); + + // Update sender balance + relay_sender_balance_before = <$sender_relay as $crate::macros::Chain>::account_data_of(sender.clone()).free; + } + )+ + } + }; +} + +#[macro_export] +macro_rules! test_parachain_is_trusted_teleporter_for_relay { + ( $sender_para:ty, $sender_xcm_config:ty, $receiver_relay:ty, $amount:expr ) => { + $crate::macros::paste::paste! { + // init Origin variables + let sender = [<$sender_para Sender>]::get(); + let para_sender_balance_before = + <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free; + let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone()); + let assets: Assets = (Parent, $amount).into(); + let fee_asset_item = 0; + let weight_limit = $crate::macros::WeightLimit::Unlimited; + + // init Destination variables + let receiver = [<$receiver_relay Receiver>]::get(); + let relay_receiver_balance_before = + <$receiver_relay as $crate::macros::Chain>::account_data_of(receiver.clone()).free; + let relay_destination: Location = Parent.into(); + let beneficiary: Location = + $crate::macros::AccountId32 { network: None, id: receiver.clone().into() }.into(); + + // Send XCM message from Parachain + <$sender_para>::execute_with(|| { + assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::limited_teleport_assets( + origin.clone(), + bx!(relay_destination.clone().into()), + bx!(beneficiary.clone().into()), + bx!(assets.clone().into()), + fee_asset_item, + weight_limit.clone(), + )); + + type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent; + + assert_expected_events!( + $sender_para, + vec![ + RuntimeEvent::PolkadotXcm( + $crate::macros::pallet_xcm::Event::Attempted { outcome: Outcome::Complete { .. } } + ) => {}, + RuntimeEvent::Balances( + $crate::macros::pallet_balances::Event::Burned { who: sender, amount } + ) => {}, + RuntimeEvent::PolkadotXcm( + $crate::macros::pallet_xcm::Event::Sent { .. } + ) => {}, + ] + ); + }); + + // Receive XCM message in Destination Parachain + <$receiver_relay>::execute_with(|| { + type RuntimeEvent = <$receiver_relay as $crate::macros::Chain>::RuntimeEvent; + + assert_expected_events!( + $receiver_relay, + vec![ + RuntimeEvent::Balances( + $crate::macros::pallet_balances::Event::Minted { who: receiver, .. } + ) => {}, + RuntimeEvent::MessageQueue( + $crate::macros::pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + ] + ); + }); + + // Check if balances are updated accordingly in Origin and Relay Chain + let para_sender_balance_after = + <$sender_para as $crate::macros::Chain>::account_data_of(sender.clone()).free; + let relay_receiver_balance_after = + <$receiver_relay as $crate::macros::Chain>::account_data_of(receiver.clone()).free; + let delivery_fees = <$sender_para>::execute_with(|| { + $crate::macros::asset_test_utils::xcm_helpers::teleport_assets_delivery_fees::< + <$sender_xcm_config as xcm_executor::Config>::XcmSender, + >(assets, fee_asset_item, weight_limit.clone(), beneficiary, relay_destination) + }); + + assert_eq!(para_sender_balance_before - $amount - delivery_fees, para_sender_balance_after); + assert!(relay_receiver_balance_after > relay_receiver_balance_before); + } + }; +} + +#[macro_export] +macro_rules! test_chain_can_claim_assets { + ( $sender_para:ty, $runtime_call:ty, $network_id:expr, $assets:expr, $amount:expr ) => { + $crate::macros::paste::paste! { + let sender = [<$sender_para Sender>]::get(); + let origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed(sender.clone()); + // Receiver is the same as sender + let beneficiary: Location = + $crate::macros::AccountId32 { network: Some($network_id), id: sender.clone().into() }.into(); + let versioned_assets: $crate::macros::VersionedAssets = $assets.clone().into(); + + <$sender_para>::execute_with(|| { + // Assets are trapped for whatever reason. + // The possible reasons for this might differ from runtime to runtime, so here we just drop them directly. + <$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::drop_assets( + &beneficiary, + $assets.clone().into(), + &XcmContext { origin: None, message_id: [0u8; 32], topic: None }, + ); + + type RuntimeEvent = <$sender_para as $crate::macros::Chain>::RuntimeEvent; + assert_expected_events!( + $sender_para, + vec![ + RuntimeEvent::PolkadotXcm( + $crate::macros::pallet_xcm::Event::AssetsTrapped { origin: beneficiary, assets: versioned_assets, .. } + ) => {}, + ] + ); + + let balance_before = <$sender_para as [<$sender_para Pallet>]>::Balances::free_balance(&sender); + + // Different origin or different assets won't work. + let other_origin = <$sender_para as $crate::macros::Chain>::RuntimeOrigin::signed([<$sender_para Receiver>]::get()); + assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets( + other_origin, + bx!(versioned_assets.clone().into()), + bx!(beneficiary.clone().into()), + ).is_err()); + let other_versioned_assets: $crate::macros::VersionedAssets = Assets::new().into(); + assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets( + origin.clone(), + bx!(other_versioned_assets.into()), + bx!(beneficiary.clone().into()), + ).is_err()); + + // Assets will be claimed to `beneficiary`, which is the same as `sender`. + assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets( + origin.clone(), + bx!(versioned_assets.clone().into()), + bx!(beneficiary.clone().into()), + )); + + assert_expected_events!( + $sender_para, + vec![ + RuntimeEvent::PolkadotXcm( + $crate::macros::pallet_xcm::Event::AssetsClaimed { origin: beneficiary, assets: versioned_assets, .. } + ) => {}, + ] + ); + + // After claiming the assets, the balance has increased. + let balance_after = <$sender_para as [<$sender_para Pallet>]>::Balances::free_balance(&sender); + assert_eq!(balance_after, balance_before + $amount); + + // Claiming the assets again doesn't work. + assert!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets( + origin.clone(), + bx!(versioned_assets.clone().into()), + bx!(beneficiary.clone().into()), + ).is_err()); + + let balance = <$sender_para as [<$sender_para Pallet>]>::Balances::free_balance(&sender); + assert_eq!(balance, balance_after); + + // You can also claim assets and send them to a different account. + <$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::drop_assets( + &beneficiary, + $assets.clone().into(), + &XcmContext { origin: None, message_id: [0u8; 32], topic: None }, + ); + let receiver = [<$sender_para Receiver>]::get(); + let other_beneficiary: Location = + $crate::macros::AccountId32 { network: Some($network_id), id: receiver.clone().into() }.into(); + let balance_before = <$sender_para as [<$sender_para Pallet>]>::Balances::free_balance(&receiver); + assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::claim_assets( + origin.clone(), + bx!(versioned_assets.clone().into()), + bx!(other_beneficiary.clone().into()), + )); + let balance_after = <$sender_para as [<$sender_para Pallet>]>::Balances::free_balance(&receiver); + assert_eq!(balance_after, balance_before + $amount); + }); + } + }; +} + +#[macro_export] +macro_rules! test_dry_run_transfer_across_pk_bridge { + ( $sender_asset_hub:ty, $sender_bridge_hub:ty, $destination:expr ) => { + $crate::macros::paste::paste! { + use frame_support::{dispatch::RawOrigin, traits::fungible}; + use sp_runtime::AccountId32; + use xcm::prelude::*; + use xcm_runtime_apis::dry_run::runtime_decl_for_dry_run_api::DryRunApiV1; + + let who = AccountId32::new([1u8; 32]); + let transfer_amount = 10_000_000_000_000u128; + let initial_balance = transfer_amount * 10; + + // Bridge setup. + $sender_asset_hub::force_xcm_version($destination, XCM_VERSION); + + <$sender_asset_hub as TestExt>::execute_with(|| { + type Runtime = <$sender_asset_hub as Chain>::Runtime; + type RuntimeCall = <$sender_asset_hub as Chain>::RuntimeCall; + type OriginCaller = <$sender_asset_hub as Chain>::OriginCaller; + type Balances = <$sender_asset_hub as [<$sender_asset_hub Pallet>]>::Balances; + + // Give some initial funds. + >::set_balance(&who, initial_balance); + + let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::transfer_assets { + dest: Box::new(VersionedLocation::from($destination)), + beneficiary: Box::new(VersionedLocation::from(Junction::AccountId32 { + id: who.clone().into(), + network: None, + })), + assets: Box::new(VersionedAssets::from(vec![ + (Parent, transfer_amount).into(), + ])), + fee_asset_item: 0, + weight_limit: Unlimited, + }); + let result = Runtime::dry_run_call(OriginCaller::system(RawOrigin::Signed(who)), call).unwrap(); + // We assert the dry run succeeds and sends only one message to the local bridge hub. + assert!(result.execution_result.is_ok()); + assert_eq!(result.forwarded_xcms.len(), 1); + assert_eq!(result.forwarded_xcms[0].0, VersionedLocation::from(Location::new(1, [Parachain($sender_bridge_hub::para_id().into())]))); + }); + } + }; +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml index 0eb99c64c801..9938ec3ab623 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml @@ -14,6 +14,7 @@ workspace = true codec = { workspace = true } scale-info = { features = ["derive"], workspace = true } hex-literal = { workspace = true, default-features = true } + sp-core.workspace = true frame-support.workspace = true pallet-assets.workspace = true @@ -25,7 +26,9 @@ sp-runtime.workspace = true xcm.workspace = true pallet-xcm.workspace = true xcm-executor.workspace = true +xcm-runtime-apis.workspace = true pallet-bridge-messages.workspace = true +pallet-xcm-bridge-hub.workspace = true cumulus-pallet-xcmp-queue.workspace = true emulated-integration-tests-common.workspace = true parachains-common.workspace = true diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs index 04466a611c71..ac6cdf9257e8 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs @@ -31,7 +31,7 @@ mod imports { pub use emulated_integration_tests_common::{ accounts::ALICE, impls::Inspect, - test_parachain_is_trusted_teleporter, + test_dry_run_transfer_across_pk_bridge, test_parachain_is_trusted_teleporter, xcm_emulator::{ assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt, }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs index 6053936487b2..91062b247134 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs @@ -517,3 +517,12 @@ fn send_back_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_weste assert!(receiver_wnds_after > receiver_wnds_before); assert!(receiver_wnds_after <= receiver_wnds_before + amount); } + +#[test] +fn dry_run_transfer_to_westend_sends_xcm_to_bridge_hub() { + test_dry_run_transfer_across_pk_bridge!( + AssetHubRococo, + BridgeHubRococo, + asset_hub_westend_location() + ); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml index 71559162f37e..e23247adad51 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml @@ -18,11 +18,14 @@ pallet-asset-conversion.workspace = true pallet-balances.workspace = true pallet-message-queue.workspace = true pallet-message-queue.default-features = true +sp-core.workspace = true sp-runtime.workspace = true xcm.workspace = true pallet-xcm.workspace = true xcm-executor.workspace = true +xcm-runtime-apis.workspace = true pallet-bridge-messages.workspace = true +pallet-xcm-bridge-hub.workspace = true cumulus-pallet-xcmp-queue.workspace = true emulated-integration-tests-common.workspace = true parachains-common.workspace = true diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs index 3b0fcea57a26..90e473dbdd6f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs @@ -32,7 +32,7 @@ mod imports { pub use emulated_integration_tests_common::{ accounts::ALICE, impls::Inspect, - test_parachain_is_trusted_teleporter, + test_dry_run_transfer_across_pk_bridge, test_parachain_is_trusted_teleporter, xcm_emulator::{ assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt, }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs index 0c0b04cd45a9..a2107275e6a2 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs @@ -543,3 +543,12 @@ fn send_back_rocs_from_penpal_westend_through_asset_hub_westend_to_asset_hub_roc assert!(receiver_rocs_after > receiver_rocs_before); assert!(receiver_rocs_after <= receiver_rocs_before + amount); } + +#[test] +fn dry_run_transfer_to_rococo_sends_xcm_to_bridge_hub() { + test_dry_run_transfer_across_pk_bridge!( + AssetHubWestend, + BridgeHubWestend, + asset_hub_rococo_location() + ); +} diff --git a/polkadot/xcm/xcm-builder/src/universal_exports.rs b/polkadot/xcm/xcm-builder/src/universal_exports.rs index 30e0b7c72b03..5c754f01ec0a 100644 --- a/polkadot/xcm/xcm-builder/src/universal_exports.rs +++ b/polkadot/xcm/xcm-builder/src/universal_exports.rs @@ -337,15 +337,15 @@ impl InspectMessageQueues +impl InspectMessageQueues for SovereignPaidRemoteExporter { - fn clear_messages() { - Router::clear_messages() - } + fn clear_messages() {} + /// This router needs to implement `InspectMessageQueues` but doesn't have to + /// return any messages, since it just reuses the `XcmpQueue` router. fn get_messages() -> Vec<(VersionedLocation, Vec>)> { - Router::get_messages() + Vec::new() } } diff --git a/prdoc/pr_6004.prdoc b/prdoc/pr_6004.prdoc new file mode 100644 index 000000000000..f50cd722c714 --- /dev/null +++ b/prdoc/pr_6004.prdoc @@ -0,0 +1,20 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Remove redundant XCMs from dry run's forwarded xcms + +doc: + - audience: Runtime User + description: | + The DryRunApi was returning the same message repeated multiple times in the + `forwarded_xcms` field. This is no longer the case. + +crates: + - name: pallet-xcm-bridge-hub-router + bump: patch + - name: cumulus-pallet-parachain-system + bump: patch + - name: staging-xcm-builder + bump: patch + - name: emulated-integration-tests-common + bump: minor