diff --git a/Cargo.lock b/Cargo.lock
index 9149c90fa5ab023f3276fecce13ba69e81a554b3..c122c982af190d2f3e298b33f5b867a75b42db7d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -24092,10 +24092,13 @@ name = "xcm-executor-integration-tests"
 version = "1.0.0"
 dependencies = [
  "frame-support",
+ "frame-system",
  "futures",
+ "pallet-sudo",
  "pallet-transaction-payment",
  "pallet-xcm",
  "parity-scale-codec",
+ "polkadot-runtime-parachains",
  "polkadot-test-client",
  "polkadot-test-runtime",
  "polkadot-test-service",
diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml
index def35c5cc2ad701dce94c990a14521b62bca366e..0dad302839f1f51fd6c10867e64a9965ca69d5c6 100644
--- a/bridges/bin/runtime-common/Cargo.toml
+++ b/bridges/bin/runtime-common/Cargo.toml
@@ -83,6 +83,7 @@ runtime-benchmarks = [
 	"pallet-utility/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"sp-trie",
+	"xcm/runtime-benchmarks",
 ]
 integrity-test = ["static_assertions"]
 test-helpers = ["bp-runtime/test-helpers", "sp-trie"]
diff --git a/bridges/modules/xcm-bridge-hub-router/Cargo.toml b/bridges/modules/xcm-bridge-hub-router/Cargo.toml
index db82ed93b83bbaa781dc5b14c7c1f30abfb81116..3d164f11eed146c02f2532ccad502f9acf478eda 100644
--- a/bridges/modules/xcm-bridge-hub-router/Cargo.toml
+++ b/bridges/modules/xcm-bridge-hub-router/Cargo.toml
@@ -50,6 +50,7 @@ runtime-benchmarks = [
 	"frame-system/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/bridges/modules/xcm-bridge-hub/Cargo.toml b/bridges/modules/xcm-bridge-hub/Cargo.toml
index f431e27cb494179f65d3c7e45e5d16747f0ba1c0..4066529011d731c536a8c13fbe7c8df62b187e8c 100644
--- a/bridges/modules/xcm-bridge-hub/Cargo.toml
+++ b/bridges/modules/xcm-bridge-hub/Cargo.toml
@@ -62,6 +62,7 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/bridges/snowbridge/pallets/inbound-queue/Cargo.toml b/bridges/snowbridge/pallets/inbound-queue/Cargo.toml
index 4d36ba4f3e2c11b77532c7b59a61d753be2a5e21..ef51a05cf3561968a91a91ce5eec34971521557d 100644
--- a/bridges/snowbridge/pallets/inbound-queue/Cargo.toml
+++ b/bridges/snowbridge/pallets/inbound-queue/Cargo.toml
@@ -79,6 +79,7 @@ runtime-benchmarks = [
 	"snowbridge-router-primitives/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/bridges/snowbridge/pallets/system/Cargo.toml b/bridges/snowbridge/pallets/system/Cargo.toml
index e069fb1924554081dcd8109767e198e0be548a39..0eb976bbf2edb1ff79c7d846f9c6fa1e2e24fa76 100644
--- a/bridges/snowbridge/pallets/system/Cargo.toml
+++ b/bridges/snowbridge/pallets/system/Cargo.toml
@@ -64,6 +64,7 @@ runtime-benchmarks = [
 	"snowbridge-core/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/bridges/snowbridge/primitives/core/Cargo.toml b/bridges/snowbridge/primitives/core/Cargo.toml
index a9e798b9a8a953144aeb771a6096f1fc85a5e3ae..bf501a2d4775e935f742e2d790129452ad6db1ae 100644
--- a/bridges/snowbridge/primitives/core/Cargo.toml
+++ b/bridges/snowbridge/primitives/core/Cargo.toml
@@ -60,4 +60,6 @@ runtime-benchmarks = [
 	"polkadot-parachain-primitives/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
+	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/bridges/snowbridge/primitives/router/Cargo.toml b/bridges/snowbridge/primitives/router/Cargo.toml
index e9a171cdff3feb3d6c0890d04591b9ebe0214369..3cd93ba9a9352876288f8d90a8f543a32ba27018 100644
--- a/bridges/snowbridge/primitives/router/Cargo.toml
+++ b/bridges/snowbridge/primitives/router/Cargo.toml
@@ -48,4 +48,5 @@ runtime-benchmarks = [
 	"snowbridge-core/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/bridges/snowbridge/runtime/runtime-common/Cargo.toml b/bridges/snowbridge/runtime/runtime-common/Cargo.toml
index ad10ecfb4eec4e196ec9ead78c6e6631182fdcaa..bcdb4e8f2d688bb16904e2bda3f68bf21510507e 100644
--- a/bridges/snowbridge/runtime/runtime-common/Cargo.toml
+++ b/bridges/snowbridge/runtime/runtime-common/Cargo.toml
@@ -42,4 +42,5 @@ runtime-benchmarks = [
 	"snowbridge-core/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/bridges/snowbridge/runtime/test-common/Cargo.toml b/bridges/snowbridge/runtime/test-common/Cargo.toml
index 22d6c3404551968080ae2cbb3dae0521729f9b82..ddd8c32ee334fda55e542545d86e7398b04eb56e 100644
--- a/bridges/snowbridge/runtime/test-common/Cargo.toml
+++ b/bridges/snowbridge/runtime/test-common/Cargo.toml
@@ -83,5 +83,6 @@ runtime-benchmarks = [
 	"snowbridge-pallet-system/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 fast-runtime = []
diff --git a/cumulus/pallets/dmp-queue/Cargo.toml b/cumulus/pallets/dmp-queue/Cargo.toml
index f8f0dabcce7d263ca1dd8485e8c8361275ffb47d..e7028abc80a2d425d5006ec0a9a72ce0b5d23cf8 100644
--- a/cumulus/pallets/dmp-queue/Cargo.toml
+++ b/cumulus/pallets/dmp-queue/Cargo.toml
@@ -51,6 +51,7 @@ runtime-benchmarks = [
 	"frame-support/runtime-benchmarks",
 	"frame-system/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/pallets/parachain-system/Cargo.toml b/cumulus/pallets/parachain-system/Cargo.toml
index c1d7b8bc493f2275dcf46b4cbb4a7a64ee8360fc..598dbc412eeeed5d4733281fa4773ede822bafdc 100644
--- a/cumulus/pallets/parachain-system/Cargo.toml
+++ b/cumulus/pallets/parachain-system/Cargo.toml
@@ -35,10 +35,12 @@ polkadot-runtime-parachains.workspace = true
 polkadot-runtime-common = { optional = true, workspace = true }
 xcm.workspace = true
 xcm-builder.workspace = true
-cumulus-pallet-parachain-system-proc-macro.workspace = true
-cumulus-primitives-core.workspace = true
-cumulus-primitives-parachain-inherent.workspace = true
-cumulus-primitives-proof-size-hostfunction.workspace = true
+
+# Cumulus
+cumulus-pallet-parachain-system-proc-macro = { workspace = true }
+cumulus-primitives-core = { workspace = true }
+cumulus-primitives-parachain-inherent = { workspace = true }
+cumulus-primitives-proof-size-hostfunction = { workspace = true }
 
 [dev-dependencies]
 assert_matches = { workspace = true }
@@ -77,7 +79,6 @@ std = [
 	"log/std",
 	"pallet-message-queue/std",
 	"polkadot-parachain-primitives/std",
-	"polkadot-runtime-common/std",
 	"polkadot-runtime-parachains/std",
 	"scale-info/std",
 	"sp-core/std",
@@ -100,17 +101,16 @@ runtime-benchmarks = [
 	"frame-system/runtime-benchmarks",
 	"pallet-message-queue/runtime-benchmarks",
 	"polkadot-parachain-primitives/runtime-benchmarks",
-	"polkadot-runtime-common/runtime-benchmarks",
 	"polkadot-runtime-parachains/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
 	"frame-support/try-runtime",
 	"frame-system/try-runtime",
 	"pallet-message-queue/try-runtime",
-	"polkadot-runtime-common?/try-runtime",
 	"polkadot-runtime-parachains/try-runtime",
 	"sp-runtime/try-runtime",
 ]
diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs
index 4163e440360821c2305f2a60dfad273ea963756b..18e72acf67b0ab052af9c85860806d93f8375b37 100644
--- a/cumulus/pallets/parachain-system/src/lib.rs
+++ b/cumulus/pallets/parachain-system/src/lib.rs
@@ -1561,7 +1561,7 @@ impl<T: Config> InspectMessageQueues for Pallet<T> {
 }
 
 #[cfg(feature = "runtime-benchmarks")]
-impl<T: Config> polkadot_runtime_common::xcm_sender::EnsureForParachain for Pallet<T> {
+impl<T: Config> polkadot_runtime_parachains::EnsureForParachain for Pallet<T> {
 	fn ensure(para_id: ParaId) {
 		if let ChannelStatus::Closed = Self::get_channel_status(para_id) {
 			Self::open_outbound_hrmp_channel_for_benchmarks_or_tests(para_id)
diff --git a/cumulus/pallets/xcmp-queue/Cargo.toml b/cumulus/pallets/xcmp-queue/Cargo.toml
index 0d28e169d3030e33ec3a6bd7264c3f53f5343b55..29b2777593c3b29334bec1392ef8f5e87c0dc24d 100644
--- a/cumulus/pallets/xcmp-queue/Cargo.toml
+++ b/cumulus/pallets/xcmp-queue/Cargo.toml
@@ -73,6 +73,7 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/cumulus/parachains/common/Cargo.toml b/cumulus/parachains/common/Cargo.toml
index 1ea2c103f05a1f057e78cceb7044fea4c6d94e21..d6eb5a94e2263aaa021e6c95932e9b04748b7ea7 100644
--- a/cumulus/parachains/common/Cargo.toml
+++ b/cumulus/parachains/common/Cargo.toml
@@ -85,4 +85,5 @@ runtime-benchmarks = [
 	"polkadot-primitives/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs
index c0d42cf2758e9431c87e4187eb42b9ab703f7f54..9dad323aa19c72a03d2ed5229b114fcb9d7c0d1b 100644
--- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs
+++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs
@@ -370,6 +370,8 @@ macro_rules! impl_send_transact_helpers_for_relay_chain {
 						let destination:  $crate::impls::Location = <Self as RelayChain>::child_location_of(recipient);
 						let xcm = $crate::impls::xcm_transact_unpaid_execution(call, $crate::impls::OriginKind::Superuser);
 
+						$crate::impls::dmp::Pallet::<<Self as $crate::impls::Chain>::Runtime>::make_parachain_reachable(recipient);
+
 						// Send XCM `Transact`
 						$crate::impls::assert_ok!(<Self as [<$chain RelayPallet>]>::XcmPallet::send(
 							root_origin,
diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs
index 3ff5ed388a39d93cd088cca879b8b24914184497..8634b82e131f4c2fce4efa38afd00423f099a7bc 100644
--- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs
+++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs
@@ -23,6 +23,7 @@ pub use pallet_message_queue;
 pub use pallet_xcm;
 
 // Polkadot
+pub use polkadot_runtime_parachains::dmp::Pallet as Dmp;
 pub use xcm::{
 	prelude::{
 		AccountId32, All, Asset, AssetId, BuyExecution, DepositAsset, ExpectTransactStatus,
@@ -156,6 +157,8 @@ macro_rules! test_relay_is_trusted_teleporter {
 
 					// Send XCM message from Relay
 					<$sender_relay>::execute_with(|| {
+						$crate::macros::Dmp::<<$sender_relay as $crate::macros::Chain>::Runtime>::make_parachain_reachable(<$receiver_para>::para_id());
+
 						assert_ok!(<$sender_relay as [<$sender_relay Pallet>]>::XcmPallet::limited_teleport_assets(
 							origin.clone(),
 							bx!(para_destination.clone().into()),
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/hybrid_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/hybrid_transfers.rs
index 7bb25d7cec623641005402442f98642be60a2b57..d175847206d61616e59300fb93f90ce87556d567 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/hybrid_transfers.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/hybrid_transfers.rs
@@ -13,6 +13,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use rococo_system_emulated_network::rococo_emulated_chain::rococo_runtime::Dmp;
+
 use super::reserve_transfer::*;
 use crate::{
 	imports::*,
@@ -777,6 +779,8 @@ fn transfer_native_asset_from_relay_to_para_through_asset_hub() {
 			xcm: xcm_on_final_dest,
 		}]);
 
+		Dmp::make_parachain_reachable(AssetHubRococo::para_id());
+
 		// First leg is a teleport, from there a local-reserve-transfer to final dest
 		<Rococo as RococoPallet>::XcmPallet::transfer_assets_using_type_and_then(
 			t.signed_origin,
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs
index 8aad4b392b2c2ab22a0603f6c2e434f3a92a9af9..6039c9baa5c99a0793302cc557943d842d8c0a74 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs
@@ -14,6 +14,7 @@
 // limitations under the License.
 
 use crate::imports::*;
+use rococo_system_emulated_network::rococo_emulated_chain::rococo_runtime::Dmp;
 
 fn relay_to_para_sender_assertions(t: RelayToParaTest) {
 	type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
@@ -486,6 +487,11 @@ pub fn para_to_para_through_hop_receiver_assertions<Hop: Clone>(t: Test<PenpalA,
 }
 
 fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult {
+	let Junction::Parachain(para_id) = *t.args.dest.chain_location().last().unwrap() else {
+		unimplemented!("Destination is not a parachain?")
+	};
+
+	Dmp::make_parachain_reachable(para_id);
 	<Rococo as RococoPallet>::XcmPallet::limited_reserve_transfer_assets(
 		t.signed_origin,
 		bx!(t.args.dest.into()),
@@ -545,6 +551,13 @@ fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> Dispa
 fn para_to_para_through_relay_limited_reserve_transfer_assets(
 	t: ParaToParaThroughRelayTest,
 ) -> DispatchResult {
+	let Junction::Parachain(para_id) = *t.args.dest.chain_location().last().unwrap() else {
+		unimplemented!("Destination is not a parachain?")
+	};
+
+	Rococo::ext_wrapper(|| {
+		Dmp::make_parachain_reachable(para_id);
+	});
 	<PenpalA as PenpalAPallet>::PolkadotXcm::limited_reserve_transfer_assets(
 		t.signed_origin,
 		bx!(t.args.dest.into()),
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs
index 3320392b495d281bf9c127ab299793535362ddcd..2ad9510eb144cd778129dda863349e658419ffbf 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs
@@ -29,6 +29,7 @@ use frame_support::{
 use parachains_common::AccountId;
 use polkadot_runtime_common::impls::VersionedLocatableAsset;
 use rococo_runtime_constants::currency::GRAND;
+use rococo_system_emulated_network::rococo_emulated_chain::rococo_runtime::Dmp;
 use xcm_executor::traits::ConvertLocation;
 
 // Fund Treasury account on Asset Hub from Treasury account on Relay Chain with ROCs.
@@ -64,6 +65,7 @@ fn spend_roc_on_asset_hub() {
 			treasury_balance * 2,
 		));
 
+		Dmp::make_parachain_reachable(1000);
 		let native_asset = Location::here();
 		let asset_hub_location: Location = [Parachain(1000)].into();
 		let treasury_location: Location = (Parent, PalletInstance(18)).into();
@@ -202,6 +204,8 @@ fn create_and_claim_treasury_spend_in_usdt() {
 		// create a conversion rate from `asset_kind` to the native currency.
 		assert_ok!(AssetRate::create(root.clone(), Box::new(asset_kind.clone()), 2.into()));
 
+		Dmp::make_parachain_reachable(1000);
+
 		// create and approve a treasury spend.
 		assert_ok!(Treasury::spend(
 			root,
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/hybrid_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/hybrid_transfers.rs
index 4d6cdd9a94d6b2b37d74c1586dd66986e84fa13a..055fd101b1aa4ee06051d3eb1008fda2b2e23059 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/hybrid_transfers.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/hybrid_transfers.rs
@@ -13,6 +13,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use westend_system_emulated_network::westend_emulated_chain::westend_runtime::Dmp;
+
 use super::reserve_transfer::*;
 use crate::{
 	imports::*,
@@ -778,6 +780,8 @@ fn transfer_native_asset_from_relay_to_para_through_asset_hub() {
 			xcm: xcm_on_final_dest,
 		}]);
 
+		Dmp::make_parachain_reachable(AssetHubWestend::para_id());
+
 		// First leg is a teleport, from there a local-reserve-transfer to final dest
 		<Westend as WestendPallet>::XcmPallet::transfer_assets_using_type_and_then(
 			t.signed_origin,
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs
index 0100e8e34ef3f41c12d78ea95b9f8b7d3ddaa7fd..0e4f68e61055202b49280560575c363c99cf061c 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs
@@ -14,6 +14,7 @@
 // limitations under the License.
 
 use crate::imports::*;
+use westend_system_emulated_network::westend_emulated_chain::westend_runtime::Dmp;
 
 fn relay_to_para_sender_assertions(t: RelayToParaTest) {
 	type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
@@ -486,6 +487,11 @@ pub fn para_to_para_through_hop_receiver_assertions<Hop: Clone>(t: Test<PenpalA,
 }
 
 fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult {
+	let Junction::Parachain(para_id) = *t.args.dest.chain_location().last().unwrap() else {
+		unimplemented!("Destination is not a parachain?")
+	};
+
+	Dmp::make_parachain_reachable(para_id);
 	<Westend as WestendPallet>::XcmPallet::limited_reserve_transfer_assets(
 		t.signed_origin,
 		bx!(t.args.dest.into()),
@@ -532,6 +538,13 @@ fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> Dispa
 fn para_to_para_through_relay_limited_reserve_transfer_assets(
 	t: ParaToParaThroughRelayTest,
 ) -> DispatchResult {
+	let Junction::Parachain(para_id) = *t.args.dest.chain_location().last().unwrap() else {
+		unimplemented!("Destination is not a parachain?")
+	};
+
+	Westend::ext_wrapper(|| {
+		Dmp::make_parachain_reachable(para_id);
+	});
 	<PenpalA as PenpalAPallet>::PolkadotXcm::limited_reserve_transfer_assets(
 		t.signed_origin,
 		bx!(t.args.dest.into()),
diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury.rs
index b70967184387a868b4bd2b49970f8e16d418d62d..6541f9b44167006d8a1a35d9c812470fa192f208 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury.rs
@@ -20,6 +20,7 @@ use emulated_integration_tests_common::{
 };
 use frame_support::traits::fungibles::{Inspect, Mutate};
 use polkadot_runtime_common::impls::VersionedLocatableAsset;
+use westend_system_emulated_network::westend_emulated_chain::westend_runtime::Dmp;
 use xcm_executor::traits::ConvertLocation;
 
 #[test]
@@ -59,6 +60,8 @@ fn create_and_claim_treasury_spend() {
 		// create a conversion rate from `asset_kind` to the native currency.
 		assert_ok!(AssetRate::create(root.clone(), Box::new(asset_kind.clone()), 2.into()));
 
+		Dmp::make_parachain_reachable(1000);
+
 		// create and approve a treasury spend.
 		assert_ok!(Treasury::spend(
 			root,
diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs
index 12f05742a0803f73926c2a1e7d58aa724ed16015..395769eaaea72c779a4ab7d8d5589db45322d9fe 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs
@@ -13,6 +13,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use rococo_system_emulated_network::rococo_emulated_chain::rococo_runtime::Dmp;
+
 use crate::tests::*;
 
 #[test]
@@ -38,6 +40,8 @@ fn send_xcm_from_rococo_relay_to_westend_asset_hub_should_fail_on_not_applicable
 	// Rococo Global Consensus
 	// Send XCM message from Relay Chain to Bridge Hub source Parachain
 	Rococo::execute_with(|| {
+		Dmp::make_parachain_reachable(BridgeHubRococo::para_id());
+
 		assert_ok!(<Rococo as RococoPallet>::XcmPallet::send(
 			sudo_origin,
 			bx!(destination),
diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs
index ae05e4223b073de9b8f8edb7907b15a7a4cf7ed6..51dbc678105eb2a66ca92c443043aa56ade38362 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs
@@ -13,6 +13,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use rococo_westend_system_emulated_network::westend_emulated_chain::westend_runtime::Dmp;
+
 use crate::tests::*;
 
 #[test]
@@ -38,6 +40,8 @@ fn send_xcm_from_westend_relay_to_rococo_asset_hub_should_fail_on_not_applicable
 	// Westend Global Consensus
 	// Send XCM message from Relay Chain to Bridge Hub source Parachain
 	Westend::execute_with(|| {
+		Dmp::make_parachain_reachable(BridgeHubWestend::para_id());
+
 		assert_ok!(<Westend as WestendPallet>::XcmPallet::send(
 			sudo_origin,
 			bx!(destination),
diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs
index 943f8965540d5cb0c17c7a0b1aac8797cbd3ed42..102cecdcf09c672dd0fb4f5de593ed24263dc5c0 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs
@@ -20,6 +20,7 @@ use frame_support::{
 };
 use polkadot_runtime_common::impls::VersionedLocatableAsset;
 use westend_runtime_constants::currency::UNITS;
+use westend_system_emulated_network::westend_emulated_chain::westend_runtime::Dmp;
 use xcm_executor::traits::ConvertLocation;
 
 // Fund Fellowship Treasury from Westend Treasury and spend from Fellowship Treasury.
@@ -57,6 +58,8 @@ fn fellowship_treasury_spend() {
 			treasury_balance * 2,
 		));
 
+		Dmp::make_parachain_reachable(1000);
+
 		let native_asset = Location::here();
 		let asset_hub_location: Location = [Parachain(1000)].into();
 		let treasury_location: Location = (Parent, PalletInstance(37)).into();
diff --git a/cumulus/parachains/integration-tests/emulated/tests/coretime/coretime-rococo/src/tests/coretime_interface.rs b/cumulus/parachains/integration-tests/emulated/tests/coretime/coretime-rococo/src/tests/coretime_interface.rs
new file mode 100644
index 0000000000000000000000000000000000000000..554025e1ecfed070a60bfc44c76b5a06ebc9818e
--- /dev/null
+++ b/cumulus/parachains/integration-tests/emulated/tests/coretime/coretime-rococo/src/tests/coretime_interface.rs
@@ -0,0 +1,240 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::imports::*;
+use frame_support::traits::OnInitialize;
+use pallet_broker::{ConfigRecord, Configuration, CoreAssignment, CoreMask, ScheduleItem};
+use rococo_runtime_constants::system_parachain::coretime::TIMESLICE_PERIOD;
+use rococo_system_emulated_network::rococo_emulated_chain::rococo_runtime::Dmp;
+use sp_runtime::Perbill;
+
+#[test]
+fn transact_hardcoded_weights_are_sane() {
+	// There are three transacts with hardcoded weights sent from the Coretime Chain to the Relay
+	// Chain across the CoretimeInterface which are triggered at various points in the sales cycle.
+	// - Request core count - triggered directly by `start_sales` or `request_core_count`
+	//   extrinsics.
+	// - Request revenue info - triggered when each timeslice is committed.
+	// - Assign core - triggered when an entry is encountered in the workplan for the next
+	//   timeslice.
+
+	// RuntimeEvent aliases to avoid warning from usage of qualified paths in assertions due to
+	// <https://github.com/rust-lang/rust/issues/86935>
+	type CoretimeEvent = <CoretimeRococo as Chain>::RuntimeEvent;
+	type RelayEvent = <Rococo as Chain>::RuntimeEvent;
+
+	Rococo::execute_with(|| {
+		Dmp::make_parachain_reachable(CoretimeRococo::para_id());
+	});
+
+	// Reserve a workload, configure broker and start sales.
+	CoretimeRococo::execute_with(|| {
+		// Hooks don't run in emulated tests - workaround as we need `on_initialize` to tick things
+		// along and have no concept of time passing otherwise.
+		<CoretimeRococo as CoretimeRococoPallet>::Broker::on_initialize(
+			<CoretimeRococo as Chain>::System::block_number(),
+		);
+
+		let coretime_root_origin = <CoretimeRococo as Chain>::RuntimeOrigin::root();
+
+		// Create and populate schedule with the worst case assignment on this core.
+		let mut schedule = Vec::new();
+		for i in 0..80 {
+			schedule.push(ScheduleItem {
+				mask: CoreMask::void().set(i),
+				assignment: CoreAssignment::Task(2000 + i),
+			})
+		}
+
+		assert_ok!(<CoretimeRococo as CoretimeRococoPallet>::Broker::reserve(
+			coretime_root_origin.clone(),
+			schedule.try_into().expect("Vector is within bounds."),
+		));
+
+		// Configure broker and start sales.
+		let config = ConfigRecord {
+			advance_notice: 1,
+			interlude_length: 1,
+			leadin_length: 2,
+			region_length: 1,
+			ideal_bulk_proportion: Perbill::from_percent(40),
+			limit_cores_offered: None,
+			renewal_bump: Perbill::from_percent(2),
+			contribution_timeout: 1,
+		};
+		assert_ok!(<CoretimeRococo as CoretimeRococoPallet>::Broker::configure(
+			coretime_root_origin.clone(),
+			config
+		));
+		assert_ok!(<CoretimeRococo as CoretimeRococoPallet>::Broker::start_sales(
+			coretime_root_origin,
+			100,
+			0
+		));
+		assert_eq!(
+			pallet_broker::Status::<<CoretimeRococo as Chain>::Runtime>::get()
+				.unwrap()
+				.core_count,
+			1
+		);
+
+		assert_expected_events!(
+			CoretimeRococo,
+			vec![
+				CoretimeEvent::Broker(
+					pallet_broker::Event::ReservationMade { .. }
+				) => {},
+				CoretimeEvent::Broker(
+					pallet_broker::Event::CoreCountRequested { core_count: 1 }
+				) => {},
+				CoretimeEvent::ParachainSystem(
+					cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
+				) => {},
+			]
+		);
+	});
+
+	// Check that the request_core_count message was processed successfully. This will fail if the
+	// weights are misconfigured.
+	Rococo::execute_with(|| {
+		Rococo::assert_ump_queue_processed(true, Some(CoretimeRococo::para_id()), None);
+
+		assert_expected_events!(
+			Rococo,
+			vec![
+				RelayEvent::MessageQueue(
+					pallet_message_queue::Event::Processed { success: true, .. }
+				) => {},
+			]
+		);
+	});
+
+	// Keep track of the relay chain block number so we can fast forward while still checking the
+	// right block.
+	let mut block_number_cursor = Rococo::ext_wrapper(<Rococo as Chain>::System::block_number);
+
+	let config = CoretimeRococo::ext_wrapper(|| {
+		Configuration::<<CoretimeRococo as Chain>::Runtime>::get()
+			.expect("Pallet was configured earlier.")
+	});
+
+	// Now run up to the block before the sale is rotated.
+	while block_number_cursor < TIMESLICE_PERIOD - config.advance_notice - 1 {
+		CoretimeRococo::execute_with(|| {
+			// Hooks don't run in emulated tests - workaround.
+			<CoretimeRococo as CoretimeRococoPallet>::Broker::on_initialize(
+				<CoretimeRococo as Chain>::System::block_number(),
+			);
+		});
+
+		Rococo::ext_wrapper(|| {
+			block_number_cursor = <Rococo as Chain>::System::block_number();
+		});
+	}
+
+	// In this block we trigger assign core.
+	CoretimeRococo::execute_with(|| {
+		// Hooks don't run in emulated tests - workaround.
+		<CoretimeRococo as CoretimeRococoPallet>::Broker::on_initialize(
+			<CoretimeRococo as Chain>::System::block_number(),
+		);
+
+		assert_expected_events!(
+			CoretimeRococo,
+			vec![
+				CoretimeEvent::Broker(
+					pallet_broker::Event::SaleInitialized { .. }
+				) => {},
+				CoretimeEvent::Broker(
+					pallet_broker::Event::CoreAssigned { .. }
+				) => {},
+				CoretimeEvent::ParachainSystem(
+					cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
+				) => {},
+			]
+		);
+	});
+
+	// Check that the assign_core message was processed successfully.
+	// This will fail if the weights are misconfigured.
+	Rococo::execute_with(|| {
+		Rococo::assert_ump_queue_processed(true, Some(CoretimeRococo::para_id()), None);
+
+		assert_expected_events!(
+			Rococo,
+			vec![
+				RelayEvent::MessageQueue(
+					pallet_message_queue::Event::Processed { success: true, .. }
+				) => {},
+				RelayEvent::Coretime(
+					polkadot_runtime_parachains::coretime::Event::CoreAssigned { .. }
+				) => {},
+			]
+		);
+	});
+
+	// In this block we trigger request revenue.
+	CoretimeRococo::execute_with(|| {
+		// Hooks don't run in emulated tests - workaround.
+		<CoretimeRococo as CoretimeRococoPallet>::Broker::on_initialize(
+			<CoretimeRococo as Chain>::System::block_number(),
+		);
+
+		assert_expected_events!(
+			CoretimeRococo,
+			vec![
+				CoretimeEvent::ParachainSystem(
+					cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
+				) => {},
+			]
+		);
+	});
+
+	// Check that the request_revenue_info_at message was processed successfully.
+	// This will fail if the weights are misconfigured.
+	Rococo::execute_with(|| {
+		Rococo::assert_ump_queue_processed(true, Some(CoretimeRococo::para_id()), None);
+
+		assert_expected_events!(
+			Rococo,
+			vec![
+				RelayEvent::MessageQueue(
+					pallet_message_queue::Event::Processed { success: true, .. }
+				) => {},
+			]
+		);
+	});
+
+	// Here we receive and process the notify_revenue XCM with zero revenue.
+	CoretimeRococo::execute_with(|| {
+		// Hooks don't run in emulated tests - workaround.
+		<CoretimeRococo as CoretimeRococoPallet>::Broker::on_initialize(
+			<CoretimeRococo as Chain>::System::block_number(),
+		);
+
+		assert_expected_events!(
+			CoretimeRococo,
+			vec![
+				CoretimeEvent::MessageQueue(
+					pallet_message_queue::Event::Processed { success: true, .. }
+				) => {},
+				// Zero revenue in first timeslice so history is immediately dropped.
+				CoretimeEvent::Broker(
+					pallet_broker::Event::HistoryDropped { when: 0, revenue: 0 }
+				) => {},
+			]
+		);
+	});
+}
diff --git a/cumulus/parachains/integration-tests/emulated/tests/coretime/coretime-westend/src/tests/coretime_interface.rs b/cumulus/parachains/integration-tests/emulated/tests/coretime/coretime-westend/src/tests/coretime_interface.rs
new file mode 100644
index 0000000000000000000000000000000000000000..900994b1afc1f62f40b55aad3f7a9c694c2219a9
--- /dev/null
+++ b/cumulus/parachains/integration-tests/emulated/tests/coretime/coretime-westend/src/tests/coretime_interface.rs
@@ -0,0 +1,228 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::imports::*;
+use frame_support::traits::OnInitialize;
+use pallet_broker::{ConfigRecord, Configuration, CoreAssignment, CoreMask, ScheduleItem};
+use sp_runtime::Perbill;
+use westend_runtime_constants::system_parachain::coretime::TIMESLICE_PERIOD;
+use westend_system_emulated_network::westend_emulated_chain::westend_runtime::Dmp;
+
+#[test]
+fn transact_hardcoded_weights_are_sane() {
+	// There are three transacts with hardcoded weights sent from the Coretime Chain to the Relay
+	// Chain across the CoretimeInterface which are triggered at various points in the sales cycle.
+	// - Request core count - triggered directly by `start_sales` or `request_core_count`
+	//   extrinsics.
+	// - Request revenue info - triggered when each timeslice is committed.
+	// - Assign core - triggered when an entry is encountered in the workplan for the next
+	//   timeslice.
+
+	// RuntimeEvent aliases to avoid warning from usage of qualified paths in assertions due to
+	// <https://github.com/rust-lang/rust/issues/86935>
+	type CoretimeEvent = <CoretimeWestend as Chain>::RuntimeEvent;
+	type RelayEvent = <Westend as Chain>::RuntimeEvent;
+
+	Westend::execute_with(|| {
+		Dmp::make_parachain_reachable(CoretimeWestend::para_id());
+	});
+
+	// Reserve a workload, configure broker and start sales.
+	CoretimeWestend::execute_with(|| {
+		// Hooks don't run in emulated tests - workaround as we need `on_initialize` to tick things
+		// along and have no concept of time passing otherwise.
+		<CoretimeWestend as CoretimeWestendPallet>::Broker::on_initialize(
+			<CoretimeWestend as Chain>::System::block_number(),
+		);
+
+		let coretime_root_origin = <CoretimeWestend as Chain>::RuntimeOrigin::root();
+
+		// Create and populate schedule with the worst case assignment on this core.
+		let mut schedule = Vec::new();
+		for i in 0..80 {
+			schedule.push(ScheduleItem {
+				mask: CoreMask::void().set(i),
+				assignment: CoreAssignment::Task(2000 + i),
+			})
+		}
+
+		assert_ok!(<CoretimeWestend as CoretimeWestendPallet>::Broker::reserve(
+			coretime_root_origin.clone(),
+			schedule.try_into().expect("Vector is within bounds."),
+		));
+
+		// Configure broker and start sales.
+		let config = ConfigRecord {
+			advance_notice: 1,
+			interlude_length: 1,
+			leadin_length: 2,
+			region_length: 1,
+			ideal_bulk_proportion: Perbill::from_percent(40),
+			limit_cores_offered: None,
+			renewal_bump: Perbill::from_percent(2),
+			contribution_timeout: 1,
+		};
+		assert_ok!(<CoretimeWestend as CoretimeWestendPallet>::Broker::configure(
+			coretime_root_origin.clone(),
+			config
+		));
+		assert_ok!(<CoretimeWestend as CoretimeWestendPallet>::Broker::start_sales(
+			coretime_root_origin,
+			100,
+			0
+		));
+		assert_eq!(
+			pallet_broker::Status::<<CoretimeWestend as Chain>::Runtime>::get()
+				.unwrap()
+				.core_count,
+			1
+		);
+
+		assert_expected_events!(
+			CoretimeWestend,
+			vec![
+				CoretimeEvent::Broker(
+					pallet_broker::Event::ReservationMade { .. }
+				) => {},
+				CoretimeEvent::Broker(
+					pallet_broker::Event::CoreCountRequested { core_count: 1 }
+				) => {},
+				CoretimeEvent::ParachainSystem(
+					cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
+				) => {},
+			]
+		);
+	});
+
+	// Check that the request_core_count message was processed successfully. This will fail if the
+	// weights are misconfigured.
+	Westend::execute_with(|| {
+		Westend::assert_ump_queue_processed(true, Some(CoretimeWestend::para_id()), None);
+
+		assert_expected_events!(
+			Westend,
+			vec![
+				RelayEvent::MessageQueue(
+					pallet_message_queue::Event::Processed { success: true, .. }
+				) => {},
+			]
+		);
+	});
+
+	// Keep track of the relay chain block number so we can fast forward while still checking the
+	// right block.
+	let mut block_number_cursor = Westend::ext_wrapper(<Westend as Chain>::System::block_number);
+
+	let config = CoretimeWestend::ext_wrapper(|| {
+		Configuration::<<CoretimeWestend as Chain>::Runtime>::get()
+			.expect("Pallet was configured earlier.")
+	});
+
+	// Now run up to the block before the sale is rotated.
+	while block_number_cursor < TIMESLICE_PERIOD - config.advance_notice - 1 {
+		CoretimeWestend::execute_with(|| {
+			// Hooks don't run in emulated tests - workaround.
+			<CoretimeWestend as CoretimeWestendPallet>::Broker::on_initialize(
+				<CoretimeWestend as Chain>::System::block_number(),
+			);
+		});
+
+		Westend::ext_wrapper(|| {
+			block_number_cursor = <Westend as Chain>::System::block_number();
+		});
+	}
+
+	// In this block we trigger assign core.
+	CoretimeWestend::execute_with(|| {
+		// Hooks don't run in emulated tests - workaround.
+		<CoretimeWestend as CoretimeWestendPallet>::Broker::on_initialize(
+			<CoretimeWestend as Chain>::System::block_number(),
+		);
+
+		assert_expected_events!(
+			CoretimeWestend,
+			vec![
+				CoretimeEvent::Broker(
+					pallet_broker::Event::SaleInitialized { .. }
+				) => {},
+				CoretimeEvent::Broker(
+					pallet_broker::Event::CoreAssigned { .. }
+				) => {},
+				CoretimeEvent::ParachainSystem(
+					cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
+				) => {},
+			]
+		);
+	});
+
+	// In this block we trigger request revenue.
+	CoretimeWestend::execute_with(|| {
+		// Hooks don't run in emulated tests - workaround.
+		<CoretimeWestend as CoretimeWestendPallet>::Broker::on_initialize(
+			<CoretimeWestend as Chain>::System::block_number(),
+		);
+
+		assert_expected_events!(
+			CoretimeWestend,
+			vec![
+				CoretimeEvent::ParachainSystem(
+					cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
+				) => {},
+			]
+		);
+	});
+
+	// Check that the assign_core and request_revenue_info_at messages were processed successfully.
+	// This will fail if the weights are misconfigured.
+	Westend::execute_with(|| {
+		Westend::assert_ump_queue_processed(true, Some(CoretimeWestend::para_id()), None);
+
+		assert_expected_events!(
+			Westend,
+			vec![
+				RelayEvent::MessageQueue(
+					pallet_message_queue::Event::Processed { success: true, .. }
+				) => {},
+				RelayEvent::MessageQueue(
+					pallet_message_queue::Event::Processed { success: true, .. }
+				) => {},
+				RelayEvent::Coretime(
+					polkadot_runtime_parachains::coretime::Event::CoreAssigned { .. }
+				) => {},
+			]
+		);
+	});
+
+	// Here we receive and process the notify_revenue XCM with zero revenue.
+	CoretimeWestend::execute_with(|| {
+		// Hooks don't run in emulated tests - workaround.
+		<CoretimeWestend as CoretimeWestendPallet>::Broker::on_initialize(
+			<CoretimeWestend as Chain>::System::block_number(),
+		);
+
+		assert_expected_events!(
+			CoretimeWestend,
+			vec![
+				CoretimeEvent::MessageQueue(
+					pallet_message_queue::Event::Processed { success: true, .. }
+				) => {},
+				// Zero revenue in first timeslice so history is immediately dropped.
+				CoretimeEvent::Broker(
+					pallet_broker::Event::HistoryDropped { when: 0, revenue: 0 }
+				) => {},
+			]
+		);
+	});
+}
diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ea438f80552e283cc0f9c1501d2d204e8bb2e709
--- /dev/null
+++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs
@@ -0,0 +1,550 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::imports::*;
+use frame_support::traits::ProcessMessageError;
+
+use codec::Encode;
+use frame_support::sp_runtime::traits::Dispatchable;
+use parachains_common::AccountId;
+use people_westend_runtime::people::IdentityInfo;
+use westend_runtime::{
+	governance::pallet_custom_origins::Origin::GeneralAdmin as GeneralAdminOrigin, Dmp,
+};
+use westend_system_emulated_network::people_westend_emulated_chain::people_westend_runtime;
+
+use pallet_identity::Data;
+
+use emulated_integration_tests_common::accounts::{ALICE, BOB};
+
+#[test]
+fn relay_commands_add_registrar() {
+	let (origin_kind, origin) = (OriginKind::Superuser, <Westend as Chain>::RuntimeOrigin::root());
+
+	let registrar: AccountId = [1; 32].into();
+	Westend::execute_with(|| {
+		type Runtime = <Westend as Chain>::Runtime;
+		type RuntimeCall = <Westend as Chain>::RuntimeCall;
+		type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+		type PeopleCall = <PeopleWestend as Chain>::RuntimeCall;
+		type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+
+		Dmp::make_parachain_reachable(1004);
+
+		let add_registrar_call =
+			PeopleCall::Identity(pallet_identity::Call::<PeopleRuntime>::add_registrar {
+				account: registrar.into(),
+			});
+
+		let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::send {
+			dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))),
+			message: bx!(VersionedXcm::from(Xcm(vec![
+				UnpaidExecution { weight_limit: Unlimited, check_origin: None },
+				Transact {
+					origin_kind,
+					call: add_registrar_call.encode().into(),
+					fallback_max_weight: None
+				}
+			]))),
+		});
+
+		assert_ok!(xcm_message.dispatch(origin));
+
+		assert_expected_events!(
+			Westend,
+			vec![
+				RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+			]
+		);
+	});
+
+	PeopleWestend::execute_with(|| {
+		type RuntimeEvent = <PeopleWestend as Chain>::RuntimeEvent;
+
+		assert_expected_events!(
+			PeopleWestend,
+			vec![
+				RuntimeEvent::Identity(pallet_identity::Event::RegistrarAdded { .. }) => {},
+				RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {},
+			]
+		);
+	});
+}
+
+#[test]
+fn relay_commands_add_registrar_wrong_origin() {
+	let people_westend_alice = PeopleWestend::account_id_of(ALICE);
+
+	let origins = vec![
+		(
+			OriginKind::SovereignAccount,
+			<Westend as Chain>::RuntimeOrigin::signed(people_westend_alice),
+		),
+		(OriginKind::Xcm, GeneralAdminOrigin.into()),
+	];
+
+	let mut signed_origin = true;
+
+	for (origin_kind, origin) in origins {
+		let registrar: AccountId = [1; 32].into();
+		Westend::execute_with(|| {
+			type Runtime = <Westend as Chain>::Runtime;
+			type RuntimeCall = <Westend as Chain>::RuntimeCall;
+			type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+			type PeopleCall = <PeopleWestend as Chain>::RuntimeCall;
+			type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+
+			Dmp::make_parachain_reachable(1004);
+
+			let add_registrar_call =
+				PeopleCall::Identity(pallet_identity::Call::<PeopleRuntime>::add_registrar {
+					account: registrar.into(),
+				});
+
+			let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::send {
+				dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))),
+				message: bx!(VersionedXcm::from(Xcm(vec![
+					UnpaidExecution { weight_limit: Unlimited, check_origin: None },
+					Transact {
+						origin_kind,
+						call: add_registrar_call.encode().into(),
+						fallback_max_weight: None
+					}
+				]))),
+			});
+
+			assert_ok!(xcm_message.dispatch(origin));
+			assert_expected_events!(
+				Westend,
+				vec![
+					RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+				]
+			);
+		});
+
+		PeopleWestend::execute_with(|| {
+			type RuntimeEvent = <PeopleWestend as Chain>::RuntimeEvent;
+
+			if signed_origin {
+				assert_expected_events!(
+					PeopleWestend,
+					vec![
+						RuntimeEvent::MessageQueue(pallet_message_queue::Event::ProcessingFailed { error: ProcessMessageError::Unsupported, .. }) => {},
+					]
+				);
+			} else {
+				assert_expected_events!(
+					PeopleWestend,
+					vec![
+						RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {},
+					]
+				);
+			}
+		});
+
+		signed_origin = false;
+	}
+}
+
+#[test]
+fn relay_commands_kill_identity() {
+	// To kill an identity, first one must be set
+	PeopleWestend::execute_with(|| {
+		type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+		type PeopleRuntimeEvent = <PeopleWestend as Chain>::RuntimeEvent;
+
+		let people_westend_alice =
+			<PeopleWestend as Chain>::RuntimeOrigin::signed(PeopleWestend::account_id_of(ALICE));
+
+		let identity_info = IdentityInfo {
+			email: Data::Raw(b"test@test.io".to_vec().try_into().unwrap()),
+			..Default::default()
+		};
+		let identity: Box<<PeopleRuntime as pallet_identity::Config>::IdentityInformation> =
+			Box::new(identity_info);
+
+		assert_ok!(<PeopleWestend as PeopleWestendPallet>::Identity::set_identity(
+			people_westend_alice,
+			identity
+		));
+
+		assert_expected_events!(
+			PeopleWestend,
+			vec![
+				PeopleRuntimeEvent::Identity(pallet_identity::Event::IdentitySet { .. }) => {},
+			]
+		);
+	});
+
+	let (origin_kind, origin) = (OriginKind::Superuser, <Westend as Chain>::RuntimeOrigin::root());
+
+	Westend::execute_with(|| {
+		type Runtime = <Westend as Chain>::Runtime;
+		type RuntimeCall = <Westend as Chain>::RuntimeCall;
+		type PeopleCall = <PeopleWestend as Chain>::RuntimeCall;
+		type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+		type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+
+		Dmp::make_parachain_reachable(1004);
+
+		let kill_identity_call =
+			PeopleCall::Identity(pallet_identity::Call::<PeopleRuntime>::kill_identity {
+				target: people_westend_runtime::MultiAddress::Id(PeopleWestend::account_id_of(
+					ALICE,
+				)),
+			});
+
+		let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::send {
+			dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))),
+			message: bx!(VersionedXcm::from(Xcm(vec![
+				UnpaidExecution { weight_limit: Unlimited, check_origin: None },
+				Transact {
+					origin_kind,
+					call: kill_identity_call.encode().into(),
+					fallback_max_weight: None
+				}
+			]))),
+		});
+
+		assert_ok!(xcm_message.dispatch(origin));
+
+		assert_expected_events!(
+			Westend,
+			vec![
+				RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+			]
+		);
+	});
+
+	PeopleWestend::execute_with(|| {
+		type RuntimeEvent = <PeopleWestend as Chain>::RuntimeEvent;
+
+		assert_expected_events!(
+			PeopleWestend,
+			vec![
+				RuntimeEvent::Identity(pallet_identity::Event::IdentityKilled { .. }) => {},
+				RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {},
+			]
+		);
+	});
+}
+
+#[test]
+fn relay_commands_kill_identity_wrong_origin() {
+	let people_westend_alice = PeopleWestend::account_id_of(BOB);
+
+	let origins = vec![
+		(
+			OriginKind::SovereignAccount,
+			<Westend as Chain>::RuntimeOrigin::signed(people_westend_alice),
+		),
+		(OriginKind::Xcm, GeneralAdminOrigin.into()),
+	];
+
+	for (origin_kind, origin) in origins {
+		Westend::execute_with(|| {
+			type Runtime = <Westend as Chain>::Runtime;
+			type RuntimeCall = <Westend as Chain>::RuntimeCall;
+			type PeopleCall = <PeopleWestend as Chain>::RuntimeCall;
+			type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+			type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+
+			Dmp::make_parachain_reachable(1004);
+
+			let kill_identity_call =
+				PeopleCall::Identity(pallet_identity::Call::<PeopleRuntime>::kill_identity {
+					target: people_westend_runtime::MultiAddress::Id(PeopleWestend::account_id_of(
+						ALICE,
+					)),
+				});
+
+			let xcm_message = RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::send {
+				dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))),
+				message: bx!(VersionedXcm::from(Xcm(vec![
+					UnpaidExecution { weight_limit: Unlimited, check_origin: None },
+					Transact {
+						origin_kind,
+						call: kill_identity_call.encode().into(),
+						fallback_max_weight: None
+					}
+				]))),
+			});
+
+			assert_ok!(xcm_message.dispatch(origin));
+			assert_expected_events!(
+				Westend,
+				vec![
+					RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+				]
+			);
+		});
+
+		PeopleWestend::execute_with(|| {
+			assert_expected_events!(PeopleWestend, vec![]);
+		});
+	}
+}
+
+#[test]
+fn relay_commands_add_remove_username_authority() {
+	let people_westend_alice = PeopleWestend::account_id_of(ALICE);
+	let people_westend_bob = PeopleWestend::account_id_of(BOB);
+
+	let (origin_kind, origin, usr) =
+		(OriginKind::Superuser, <Westend as Chain>::RuntimeOrigin::root(), "rootusername");
+
+	// First, add a username authority.
+	Westend::execute_with(|| {
+		type Runtime = <Westend as Chain>::Runtime;
+		type RuntimeCall = <Westend as Chain>::RuntimeCall;
+		type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+		type PeopleCall = <PeopleWestend as Chain>::RuntimeCall;
+		type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+
+		Dmp::make_parachain_reachable(1004);
+
+		let add_username_authority =
+			PeopleCall::Identity(pallet_identity::Call::<PeopleRuntime>::add_username_authority {
+				authority: people_westend_runtime::MultiAddress::Id(people_westend_alice.clone()),
+				suffix: b"suffix1".into(),
+				allocation: 10,
+			});
+
+		let add_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::send {
+			dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))),
+			message: bx!(VersionedXcm::from(Xcm(vec![
+				UnpaidExecution { weight_limit: Unlimited, check_origin: None },
+				Transact {
+					origin_kind,
+					call: add_username_authority.encode().into(),
+					fallback_max_weight: None
+				}
+			]))),
+		});
+
+		assert_ok!(add_authority_xcm_msg.dispatch(origin.clone()));
+
+		assert_expected_events!(
+			Westend,
+			vec![
+				RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+			]
+		);
+	});
+
+	// Check events system-parachain-side
+	PeopleWestend::execute_with(|| {
+		type RuntimeEvent = <PeopleWestend as Chain>::RuntimeEvent;
+
+		assert_expected_events!(
+			PeopleWestend,
+			vec![
+				RuntimeEvent::Identity(pallet_identity::Event::AuthorityAdded { .. }) => {},
+				RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {},
+			]
+		);
+	});
+
+	// Now, use the previously added username authority to concede a username to an account.
+	PeopleWestend::execute_with(|| {
+		type PeopleRuntimeEvent = <PeopleWestend as Chain>::RuntimeEvent;
+		let full_username = [usr.to_owned(), ".suffix1".to_owned()].concat().into_bytes();
+
+		assert_ok!(<PeopleWestend as PeopleWestendPallet>::Identity::set_username_for(
+			<PeopleWestend as Chain>::RuntimeOrigin::signed(people_westend_alice.clone()),
+			people_westend_runtime::MultiAddress::Id(people_westend_bob.clone()),
+			full_username,
+			None,
+			true
+		));
+
+		assert_expected_events!(
+			PeopleWestend,
+			vec![
+				PeopleRuntimeEvent::Identity(pallet_identity::Event::UsernameQueued { .. }) => {},
+			]
+		);
+	});
+
+	// Accept the given username
+	PeopleWestend::execute_with(|| {
+		type PeopleRuntimeEvent = <PeopleWestend as Chain>::RuntimeEvent;
+		let full_username = [usr.to_owned(), ".suffix1".to_owned()].concat().into_bytes();
+
+		assert_ok!(<PeopleWestend as PeopleWestendPallet>::Identity::accept_username(
+			<PeopleWestend as Chain>::RuntimeOrigin::signed(people_westend_bob.clone()),
+			full_username.try_into().unwrap(),
+		));
+
+		assert_expected_events!(
+			PeopleWestend,
+			vec![
+				PeopleRuntimeEvent::Identity(pallet_identity::Event::UsernameSet { .. }) => {},
+			]
+		);
+	});
+
+	// Now, remove the username authority with another priviledged XCM call.
+	Westend::execute_with(|| {
+		type Runtime = <Westend as Chain>::Runtime;
+		type RuntimeCall = <Westend as Chain>::RuntimeCall;
+		type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+		type PeopleCall = <PeopleWestend as Chain>::RuntimeCall;
+		type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+
+		Dmp::make_parachain_reachable(1004);
+
+		let remove_username_authority = PeopleCall::Identity(pallet_identity::Call::<
+			PeopleRuntime,
+		>::remove_username_authority {
+			authority: people_westend_runtime::MultiAddress::Id(people_westend_alice.clone()),
+			suffix: b"suffix1".into(),
+		});
+
+		let remove_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::send {
+			dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))),
+			message: bx!(VersionedXcm::from(Xcm(vec![
+				UnpaidExecution { weight_limit: Unlimited, check_origin: None },
+				Transact {
+					origin_kind,
+					call: remove_username_authority.encode().into(),
+					fallback_max_weight: None
+				}
+			]))),
+		});
+
+		assert_ok!(remove_authority_xcm_msg.dispatch(origin));
+
+		assert_expected_events!(
+			Westend,
+			vec![
+				RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+			]
+		);
+	});
+
+	// Final event check.
+	PeopleWestend::execute_with(|| {
+		type RuntimeEvent = <PeopleWestend as Chain>::RuntimeEvent;
+
+		assert_expected_events!(
+			PeopleWestend,
+			vec![
+				RuntimeEvent::Identity(pallet_identity::Event::AuthorityRemoved { .. }) => {},
+				RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => {},
+			]
+		);
+	});
+}
+
+#[test]
+fn relay_commands_add_remove_username_authority_wrong_origin() {
+	let people_westend_alice = PeopleWestend::account_id_of(ALICE);
+
+	let origins = vec![
+		(
+			OriginKind::SovereignAccount,
+			<Westend as Chain>::RuntimeOrigin::signed(people_westend_alice.clone()),
+		),
+		(OriginKind::Xcm, GeneralAdminOrigin.into()),
+	];
+
+	for (origin_kind, origin) in origins {
+		Westend::execute_with(|| {
+			type Runtime = <Westend as Chain>::Runtime;
+			type RuntimeCall = <Westend as Chain>::RuntimeCall;
+			type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+			type PeopleCall = <PeopleWestend as Chain>::RuntimeCall;
+			type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+
+			Dmp::make_parachain_reachable(1004);
+
+			let add_username_authority = PeopleCall::Identity(pallet_identity::Call::<
+				PeopleRuntime,
+			>::add_username_authority {
+				authority: people_westend_runtime::MultiAddress::Id(people_westend_alice.clone()),
+				suffix: b"suffix1".into(),
+				allocation: 10,
+			});
+
+			let add_authority_xcm_msg = RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::send {
+				dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))),
+				message: bx!(VersionedXcm::from(Xcm(vec![
+					UnpaidExecution { weight_limit: Unlimited, check_origin: None },
+					Transact {
+						origin_kind,
+						call: add_username_authority.encode().into(),
+						fallback_max_weight: None
+					}
+				]))),
+			});
+
+			assert_ok!(add_authority_xcm_msg.dispatch(origin.clone()));
+			assert_expected_events!(
+				Westend,
+				vec![
+					RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+				]
+			);
+		});
+
+		// Check events system-parachain-side
+		PeopleWestend::execute_with(|| {
+			assert_expected_events!(PeopleWestend, vec![]);
+		});
+
+		Westend::execute_with(|| {
+			type Runtime = <Westend as Chain>::Runtime;
+			type RuntimeCall = <Westend as Chain>::RuntimeCall;
+			type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
+			type PeopleCall = <PeopleWestend as Chain>::RuntimeCall;
+			type PeopleRuntime = <PeopleWestend as Chain>::Runtime;
+
+			let remove_username_authority = PeopleCall::Identity(pallet_identity::Call::<
+				PeopleRuntime,
+			>::remove_username_authority {
+				authority: people_westend_runtime::MultiAddress::Id(people_westend_alice.clone()),
+				suffix: b"suffix1".into(),
+			});
+
+			Dmp::make_parachain_reachable(1004);
+
+			let remove_authority_xcm_msg =
+				RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::send {
+					dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))),
+					message: bx!(VersionedXcm::from(Xcm(vec![
+						UnpaidExecution { weight_limit: Unlimited, check_origin: None },
+						Transact {
+							origin_kind: OriginKind::SovereignAccount,
+							call: remove_username_authority.encode().into(),
+							fallback_max_weight: None,
+						}
+					]))),
+				});
+
+			assert_ok!(remove_authority_xcm_msg.dispatch(origin));
+			assert_expected_events!(
+				Westend,
+				vec![
+					RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
+				]
+			);
+		});
+
+		PeopleWestend::execute_with(|| {
+			assert_expected_events!(PeopleWestend, vec![]);
+		});
+	}
+}
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
index 2c18385969563a0fa8602cfe3c0a13f17ec5aa95..293ff590a39259c36962016d43c9b325f8cbfc02 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml
@@ -133,6 +133,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
index 278cedef3f11a6b2c40eefcafa4cefa60bd04f2a..64e2b6e762fb80b495eb96ca48bd04fe2c154f54 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml
@@ -135,6 +135,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
diff --git a/cumulus/parachains/runtimes/assets/common/Cargo.toml b/cumulus/parachains/runtimes/assets/common/Cargo.toml
index 6c5ef1e999396b8eb288f60aa1dc24b204027ac6..7aa94cd453b648bbcbe5da7187ac038eeafdfa3f 100644
--- a/cumulus/parachains/runtimes/assets/common/Cargo.toml
+++ b/cumulus/parachains/runtimes/assets/common/Cargo.toml
@@ -59,4 +59,5 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
index 80750ca00c7b6938cee85b344b169570fd8a6deb..44e6dc79f6e2588a288ba6b71bfc90b8529e0dae 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
@@ -254,6 +254,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml
index 072532222e8df25bbf74e390285628d95eaf5f53..081e849644937446cc0f68abc02ebcc6c3517b15 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml
@@ -246,6 +246,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml
index c9009cd4f0be38ca1cc2c0dc01409a3dba14d9d8..68105d4a4fdaf8a8da0ec8d969af4c7bbbf55406 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml
+++ b/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml
@@ -39,4 +39,5 @@ runtime-benchmarks = [
 	"pallet-message-queue/runtime-benchmarks",
 	"snowbridge-core/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
index 2a177d398e0030bf383fd2812b3cd1bbac20b4e8..3564673adcf6ef1c963debc29b93929014a324cc 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml
@@ -127,6 +127,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"cumulus-pallet-aura-ext/try-runtime",
diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml
index 66b55e0c5334c4454ee06d64263492c9da9f8cee..b6bc8437795a554c22a89fa329b08520b0286239 100644
--- a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml
@@ -163,6 +163,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
index 5170f67804983d00b52f90eaf7b298ea5cb2b9d4..fb904e37f9e5b9992e633e67ed4dfff85667049d 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml
@@ -170,6 +170,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
index d859702915b12e92e3a32f94fe22e327d0622eda..19aadf53ea7feb9257b4df82d59294ec17f2808e 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml
@@ -167,6 +167,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml b/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml
index cadb9fe661a01b0bf5ce49381cf95e3ea53bfaa7..3dc51fcb036e6acb46dd897f27bda19bd91040c5 100644
--- a/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml
@@ -70,6 +70,7 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 std = [
 	"codec/std",
diff --git a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
index 230ca5e041e8b189eec994af9408d3ba8b023458..d7886c13cd25047869c4bd4c19d484b9e7834185 100644
--- a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml
@@ -164,6 +164,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
index dcc83eef3190227cd827b4e40986145af6cdf939..e805b8020f46a519b152a9428618a388ab0df70e 100644
--- a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
+++ b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml
@@ -164,6 +164,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml
index e8a9293dad8687d3f532b2792c7dc9785aa868b1..c30a75a2588f6e970570ffc2547912cb464f1d9c 100644
--- a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml
+++ b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml
@@ -165,6 +165,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 try-runtime = [
diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml
index 6f9b34a8cfa32e4c3fa9d18bdcc09b8befdd1e52..4353c2845e382e6efa03134fd49bf1d7ea2d316a 100644
--- a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml
+++ b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml
@@ -127,6 +127,7 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 # A feature that should be enabled when the runtime should be built for on-chain
diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml
index 8c0f723d3f5c3464d7a3a9e3ac303b728c067eed..8bb56ee9da1cab8463003500beca88ccaf58540d 100644
--- a/cumulus/polkadot-parachain/Cargo.toml
+++ b/cumulus/polkadot-parachain/Cargo.toml
@@ -85,6 +85,7 @@ runtime-benchmarks = [
 	"people-rococo-runtime/runtime-benchmarks",
 	"people-westend-runtime/runtime-benchmarks",
 	"rococo-parachain-runtime/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"polkadot-parachain-lib/try-runtime",
diff --git a/cumulus/primitives/core/Cargo.toml b/cumulus/primitives/core/Cargo.toml
index d4ebdf8c2eb464223e1762e0e797750c009785a3..33db62e900de41bc2822e687d8408a9e8f701dbb 100644
--- a/cumulus/primitives/core/Cargo.toml
+++ b/cumulus/primitives/core/Cargo.toml
@@ -37,4 +37,5 @@ runtime-benchmarks = [
 	"polkadot-parachain-primitives/runtime-benchmarks",
 	"polkadot-primitives/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/cumulus/primitives/utility/Cargo.toml b/cumulus/primitives/utility/Cargo.toml
index ee3de4cd67506a55fcd703c52fd98be3dfdf846a..34294a754bb038c2a0b4abc86562087704b65284 100644
--- a/cumulus/primitives/utility/Cargo.toml
+++ b/cumulus/primitives/utility/Cargo.toml
@@ -44,4 +44,5 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml
index 3123594c1ae474784d62d598d570075238de7a2b..7fa089c81a2868256cecae8181ca471f1af28012 100644
--- a/polkadot/node/service/Cargo.toml
+++ b/polkadot/node/service/Cargo.toml
@@ -251,6 +251,7 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"westend-runtime?/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-system/try-runtime",
diff --git a/polkadot/parachain/src/primitives.rs b/polkadot/parachain/src/primitives.rs
index c5757928c3fc2f86fdd6ddb779856f0f39db70f7..1f2f9e2e9cdc7068a623db6469c935833dbedab0 100644
--- a/polkadot/parachain/src/primitives.rs
+++ b/polkadot/parachain/src/primitives.rs
@@ -57,6 +57,8 @@ impl HeadData {
 	}
 }
 
+impl codec::EncodeLike<HeadData> for alloc::vec::Vec<u8> {}
+
 /// Parachain validation code.
 #[derive(
 	PartialEq,
@@ -154,6 +156,9 @@ pub struct BlockData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec
 #[cfg_attr(feature = "std", derive(derive_more::Display))]
 pub struct Id(u32);
 
+impl codec::EncodeLike<u32> for Id {}
+impl codec::EncodeLike<Id> for u32 {}
+
 impl TypeId for Id {
 	const TYPE_ID: [u8; 4] = *b"para";
 }
diff --git a/polkadot/runtime/common/Cargo.toml b/polkadot/runtime/common/Cargo.toml
index fda53d237416c8655c0fc5670a0e85f4d9e43e05..7c77b58f5331b5b660243d77aa17e1aae5d66834 100644
--- a/polkadot/runtime/common/Cargo.toml
+++ b/polkadot/runtime/common/Cargo.toml
@@ -133,6 +133,7 @@ runtime-benchmarks = [
 	"sp-staking/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-election-provider-support/try-runtime",
diff --git a/polkadot/runtime/common/src/identity_migrator.rs b/polkadot/runtime/common/src/identity_migrator.rs
index 126c886280e6ed713d81c93f5afedbb69b03a1b5..e3835b692526e5cac1a8a541f91a85675e4fa5f1 100644
--- a/polkadot/runtime/common/src/identity_migrator.rs
+++ b/polkadot/runtime/common/src/identity_migrator.rs
@@ -160,12 +160,22 @@ pub trait OnReapIdentity<AccountId> {
 	/// - `bytes`: The byte size of `IdentityInfo`.
 	/// - `subs`: The number of sub-accounts they had.
 	fn on_reap_identity(who: &AccountId, bytes: u32, subs: u32) -> DispatchResult;
+
+	/// Ensure that identity reaping will be succesful in benchmarking.
+	///
+	/// Should setup the state in a way that the same call ot `[Self::on_reap_identity]` will be
+	/// successful.
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_identity_reaping(who: &AccountId, bytes: u32, subs: u32);
 }
 
 impl<AccountId> OnReapIdentity<AccountId> for () {
 	fn on_reap_identity(_who: &AccountId, _bytes: u32, _subs: u32) -> DispatchResult {
 		Ok(())
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_identity_reaping(_: &AccountId, _: u32, _: u32) {}
 }
 
 #[cfg(feature = "runtime-benchmarks")]
@@ -219,6 +229,12 @@ mod benchmarks {
 		}
 		Identity::<T>::set_subs(target_origin.clone(), subs.clone())?;
 
+		T::ReapIdentityHandler::ensure_successful_identity_reaping(
+			&target,
+			info.encoded_size() as u32,
+			subs.len() as u32,
+		);
+
 		// add registrars and provide judgements
 		let registrar_origin = T::RegistrarOrigin::try_successful_origin()
 			.expect("RegistrarOrigin has no successful origin required for the benchmark");
diff --git a/polkadot/runtime/common/src/paras_sudo_wrapper.rs b/polkadot/runtime/common/src/paras_sudo_wrapper.rs
index af93c70b4783f717a2adddd0f0f34365ae27d954..4309931fe815eb6286de4522aebd47be642837f8 100644
--- a/polkadot/runtime/common/src/paras_sudo_wrapper.rs
+++ b/polkadot/runtime/common/src/paras_sudo_wrapper.rs
@@ -48,6 +48,8 @@ pub mod pallet {
 		/// A DMP message couldn't be sent because it exceeds the maximum size allowed for a
 		/// downward message.
 		ExceedsMaxMessageSize,
+		/// A DMP message couldn't be sent because the destination is unreachable.
+		Unroutable,
 		/// Could not schedule para cleanup.
 		CouldntCleanup,
 		/// Not a parathread (on-demand parachain).
@@ -152,6 +154,7 @@ pub mod pallet {
 			{
 				dmp::QueueDownwardMessageError::ExceedsMaxMessageSize =>
 					Error::<T>::ExceedsMaxMessageSize.into(),
+				dmp::QueueDownwardMessageError::Unroutable => Error::<T>::Unroutable.into(),
 			})
 		}
 
diff --git a/polkadot/runtime/common/src/xcm_sender.rs b/polkadot/runtime/common/src/xcm_sender.rs
index 37fe7f0b59e979a7812bbbf4d7f9e7cb7541c386..bdd407fd11cf0afee271f35d1e0306974424e4f0 100644
--- a/polkadot/runtime/common/src/xcm_sender.rs
+++ b/polkadot/runtime/common/src/xcm_sender.rs
@@ -138,6 +138,13 @@ where
 			.map(|()| hash)
 			.map_err(|_| SendError::Transport(&"Error placing into DMP queue"))
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(location: Option<Location>) {
+		if let Some((0, [Parachain(id)])) = location.as_ref().map(|l| l.unpack()) {
+			dmp::Pallet::<T>::make_parachain_reachable(*id);
+		}
+	}
 }
 
 impl<T: dmp::Config, W, P> InspectMessageQueues for ChildParachainRouter<T, W, P> {
@@ -190,7 +197,7 @@ impl<
 		ExistentialDeposit: Get<Option<Asset>>,
 		PriceForDelivery: PriceForMessageDelivery<Id = ParaId>,
 		Parachain: Get<ParaId>,
-		ToParachainHelper: EnsureForParachain,
+		ToParachainHelper: polkadot_runtime_parachains::EnsureForParachain,
 	> xcm_builder::EnsureDelivery
 	for ToParachainDeliveryHelper<
 		XcmConfig,
@@ -219,6 +226,9 @@ impl<
 			return (None, None)
 		}
 
+		// allow more initialization for target parachain
+		ToParachainHelper::ensure(Parachain::get());
+
 		let mut fees_mode = None;
 		if !XcmConfig::FeeManager::is_waived(Some(origin_ref), fee_reason) {
 			// if not waived, we need to set up accounts for paying and receiving fees
@@ -238,9 +248,6 @@ impl<
 				XcmConfig::AssetTransactor::deposit_asset(&fee, &origin_ref, None).unwrap();
 			}
 
-			// allow more initialization for target parachain
-			ToParachainHelper::ensure(Parachain::get());
-
 			// expected worst case - direct withdraw
 			fees_mode = Some(FeesMode { jit_withdraw: true });
 		}
@@ -248,18 +255,6 @@ impl<
 	}
 }
 
-/// Ensure more initialization for `ParaId`. (e.g. open HRMP channels, ...)
-#[cfg(feature = "runtime-benchmarks")]
-pub trait EnsureForParachain {
-	fn ensure(para_id: ParaId);
-}
-#[cfg(feature = "runtime-benchmarks")]
-impl EnsureForParachain for () {
-	fn ensure(_: ParaId) {
-		// doing nothing
-	}
-}
-
 #[cfg(test)]
 mod tests {
 	use super::*;
@@ -349,6 +344,8 @@ mod tests {
 				c.max_downward_message_size = u32::MAX;
 			});
 
+			dmp::Pallet::<crate::integration_tests::Test>::make_parachain_reachable(5555);
+
 			// Check that the good message is validated:
 			assert_ok!(<Router as SendXcm>::validate(
 				&mut Some(dest.into()),
diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml
index fd3d96792b7f97a5a897d9fdf853bc5d6d164df8..c7a2af312259ae366435aa36ae9b566c241ce68e 100644
--- a/polkadot/runtime/parachains/Cargo.toml
+++ b/polkadot/runtime/parachains/Cargo.toml
@@ -133,6 +133,7 @@ runtime-benchmarks = [
 	"sp-std",
 	"static_assertions",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/polkadot/runtime/parachains/src/coretime/benchmarking.rs b/polkadot/runtime/parachains/src/coretime/benchmarking.rs
index 6d593f1954ff1500fd59ae5d178e038dd38e01b5..49e3d8a88c0158f09aa3a4d8e98a969ca907be44 100644
--- a/polkadot/runtime/parachains/src/coretime/benchmarking.rs
+++ b/polkadot/runtime/parachains/src/coretime/benchmarking.rs
@@ -43,6 +43,8 @@ mod benchmarks {
 			.unwrap();
 		on_demand::Revenue::<T>::put(rev);
 
+		crate::paras::Heads::<T>::insert(ParaId::from(T::BrokerId::get()), vec![1, 2, 3]);
+
 		<T as on_demand::Config>::Currency::make_free_balance_be(
 			&<on_demand::Pallet<T>>::account_id(),
 			minimum_balance * (mhr * (mhr + 1)).into(),
diff --git a/polkadot/runtime/parachains/src/dmp.rs b/polkadot/runtime/parachains/src/dmp.rs
index 03580e11b8e9cbe7dce4c9e375741ec3677bd9fe..3c9cf8004186527bc999f1eccc71325b81bf5af1 100644
--- a/polkadot/runtime/parachains/src/dmp.rs
+++ b/polkadot/runtime/parachains/src/dmp.rs
@@ -44,7 +44,7 @@
 
 use crate::{
 	configuration::{self, HostConfiguration},
-	initializer, FeeTracker,
+	initializer, paras, FeeTracker,
 };
 use alloc::vec::Vec;
 use core::fmt;
@@ -72,12 +72,15 @@ const MESSAGE_SIZE_FEE_BASE: FixedU128 = FixedU128::from_rational(1, 1000); // 0
 pub enum QueueDownwardMessageError {
 	/// The message being sent exceeds the configured max message size.
 	ExceedsMaxMessageSize,
+	/// The destination is unknown.
+	Unroutable,
 }
 
 impl From<QueueDownwardMessageError> for SendError {
 	fn from(err: QueueDownwardMessageError) -> Self {
 		match err {
 			QueueDownwardMessageError::ExceedsMaxMessageSize => SendError::ExceedsMaxMessageSize,
+			QueueDownwardMessageError::Unroutable => SendError::Unroutable,
 		}
 	}
 }
@@ -116,7 +119,7 @@ pub mod pallet {
 	pub struct Pallet<T>(_);
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + configuration::Config {}
+	pub trait Config: frame_system::Config + configuration::Config + paras::Config {}
 
 	/// The downward messages addressed for a certain para.
 	#[pallet::storage]
@@ -200,6 +203,11 @@ impl<T: Config> Pallet<T> {
 			return Err(QueueDownwardMessageError::ExceedsMaxMessageSize)
 		}
 
+		// If the head exists, we assume the parachain is legit and exists.
+		if !paras::Heads::<T>::contains_key(para) {
+			return Err(QueueDownwardMessageError::Unroutable)
+		}
+
 		Ok(())
 	}
 
@@ -217,14 +225,7 @@ impl<T: Config> Pallet<T> {
 		msg: DownwardMessage,
 	) -> Result<(), QueueDownwardMessageError> {
 		let serialized_len = msg.len() as u32;
-		if serialized_len > config.max_downward_message_size {
-			return Err(QueueDownwardMessageError::ExceedsMaxMessageSize)
-		}
-
-		// Hard limit on Queue size
-		if Self::dmq_length(para) > Self::dmq_max_length(config.max_downward_message_size) {
-			return Err(QueueDownwardMessageError::ExceedsMaxMessageSize)
-		}
+		Self::can_queue_downward_message(config, &para, &msg)?;
 
 		let inbound =
 			InboundDownwardMessage { msg, sent_at: frame_system::Pallet::<T>::block_number() };
@@ -336,6 +337,15 @@ impl<T: Config> Pallet<T> {
 	) -> Vec<InboundDownwardMessage<BlockNumberFor<T>>> {
 		DownwardMessageQueues::<T>::get(&recipient)
 	}
+
+	/// Make the parachain reachable for downward messages.
+	///
+	/// Only useable in benchmarks or tests.
+	#[cfg(any(feature = "runtime-benchmarks", feature = "std"))]
+	pub fn make_parachain_reachable(para: impl Into<ParaId>) {
+		let para = para.into();
+		crate::paras::Heads::<T>::insert(para, para.encode());
+	}
 }
 
 impl<T: Config> FeeTracker for Pallet<T> {
@@ -359,3 +369,10 @@ impl<T: Config> FeeTracker for Pallet<T> {
 		})
 	}
 }
+
+#[cfg(feature = "runtime-benchmarks")]
+impl<T: Config> crate::EnsureForParachain for Pallet<T> {
+	fn ensure(para: ParaId) {
+		Self::make_parachain_reachable(para);
+	}
+}
diff --git a/polkadot/runtime/parachains/src/dmp/tests.rs b/polkadot/runtime/parachains/src/dmp/tests.rs
index de15159581252aa29775addda7797d84abc4d115..617c9488bd2a22c713f188ff89993253374848f4 100644
--- a/polkadot/runtime/parachains/src/dmp/tests.rs
+++ b/polkadot/runtime/parachains/src/dmp/tests.rs
@@ -61,6 +61,12 @@ fn queue_downward_message(
 	Dmp::queue_downward_message(&configuration::ActiveConfig::<Test>::get(), para_id, msg)
 }
 
+fn register_paras(paras: &[ParaId]) {
+	paras.iter().for_each(|p| {
+		Dmp::make_parachain_reachable(*p);
+	});
+}
+
 #[test]
 fn clean_dmp_works() {
 	let a = ParaId::from(1312);
@@ -68,6 +74,8 @@ fn clean_dmp_works() {
 	let c = ParaId::from(123);
 
 	new_test_ext(default_genesis_config()).execute_with(|| {
+		register_paras(&[a, b, c]);
+
 		// enqueue downward messages to A, B and C.
 		queue_downward_message(a, vec![1, 2, 3]).unwrap();
 		queue_downward_message(b, vec![4, 5, 6]).unwrap();
@@ -89,6 +97,8 @@ fn dmq_length_and_head_updated_properly() {
 	let b = ParaId::from(228);
 
 	new_test_ext(default_genesis_config()).execute_with(|| {
+		register_paras(&[a, b]);
+
 		assert_eq!(Dmp::dmq_length(a), 0);
 		assert_eq!(Dmp::dmq_length(b), 0);
 
@@ -101,11 +111,30 @@ fn dmq_length_and_head_updated_properly() {
 	});
 }
 
+#[test]
+fn dmq_fail_if_para_does_not_exist() {
+	let a = ParaId::from(1312);
+
+	new_test_ext(default_genesis_config()).execute_with(|| {
+		assert_eq!(Dmp::dmq_length(a), 0);
+
+		assert!(matches!(
+			queue_downward_message(a, vec![1, 2, 3]),
+			Err(QueueDownwardMessageError::Unroutable)
+		));
+
+		assert_eq!(Dmp::dmq_length(a), 0);
+		assert!(Dmp::dmq_mqc_head(a).is_zero());
+	});
+}
+
 #[test]
 fn dmp_mqc_head_fixture() {
 	let a = ParaId::from(2000);
 
 	new_test_ext(default_genesis_config()).execute_with(|| {
+		register_paras(&[a]);
+
 		run_to_block(2, None);
 		assert!(Dmp::dmq_mqc_head(a).is_zero());
 		queue_downward_message(a, vec![1, 2, 3]).unwrap();
@@ -125,6 +154,8 @@ fn check_processed_downward_messages() {
 	let a = ParaId::from(1312);
 
 	new_test_ext(default_genesis_config()).execute_with(|| {
+		register_paras(&[a]);
+
 		let block_number = System::block_number();
 
 		// processed_downward_messages=0 is allowed when the DMQ is empty.
@@ -150,6 +181,8 @@ fn check_processed_downward_messages_advancement_rule() {
 	let a = ParaId::from(1312);
 
 	new_test_ext(default_genesis_config()).execute_with(|| {
+		register_paras(&[a]);
+
 		let block_number = System::block_number();
 
 		run_to_block(block_number + 1, None);
@@ -170,6 +203,8 @@ fn dmq_pruning() {
 	let a = ParaId::from(1312);
 
 	new_test_ext(default_genesis_config()).execute_with(|| {
+		register_paras(&[a]);
+
 		assert_eq!(Dmp::dmq_length(a), 0);
 
 		queue_downward_message(a, vec![1, 2, 3]).unwrap();
@@ -194,6 +229,8 @@ fn queue_downward_message_critical() {
 	genesis.configuration.config.max_downward_message_size = 7;
 
 	new_test_ext(genesis).execute_with(|| {
+		register_paras(&[a]);
+
 		let smol = [0; 3].to_vec();
 		let big = [0; 8].to_vec();
 
@@ -215,6 +252,8 @@ fn verify_dmq_mqc_head_is_externally_accessible() {
 	let a = ParaId::from(2020);
 
 	new_test_ext(default_genesis_config()).execute_with(|| {
+		register_paras(&[a]);
+
 		let head = sp_io::storage::get(&well_known_keys::dmq_mqc_head(a));
 		assert_eq!(head, None);
 
@@ -235,9 +274,12 @@ fn verify_dmq_mqc_head_is_externally_accessible() {
 #[test]
 fn verify_fee_increase_and_decrease() {
 	let a = ParaId::from(123);
+
 	let mut genesis = default_genesis_config();
 	genesis.configuration.config.max_downward_message_size = 16777216;
 	new_test_ext(genesis).execute_with(|| {
+		register_paras(&[a]);
+
 		let initial = InitialFactor::get();
 		assert_eq!(DeliveryFeeFactor::<Test>::get(a), initial);
 
@@ -287,6 +329,8 @@ fn verify_fee_factor_reaches_high_value() {
 	let mut genesis = default_genesis_config();
 	genesis.configuration.config.max_downward_message_size = 51200;
 	new_test_ext(genesis).execute_with(|| {
+		register_paras(&[a]);
+
 		let max_messages =
 			Dmp::dmq_max_length(ActiveConfig::<Test>::get().max_downward_message_size);
 		let mut total_fee_factor = FixedU128::from_float(1.0);
diff --git a/polkadot/runtime/parachains/src/lib.rs b/polkadot/runtime/parachains/src/lib.rs
index f1162e1cc2154a66db7aa02e465eab9934130769..e86ca359929a2f54a471a9b93f9cf0b32ec23ef5 100644
--- a/polkadot/runtime/parachains/src/lib.rs
+++ b/polkadot/runtime/parachains/src/lib.rs
@@ -115,3 +115,19 @@ pub fn schedule_code_upgrade<T: paras::Config>(
 pub fn set_current_head<T: paras::Config>(id: ParaId, new_head: HeadData) {
 	paras::Pallet::<T>::set_current_head(id, new_head)
 }
+
+/// Ensure more initialization for `ParaId` when benchmarking. (e.g. open HRMP channels, ...)
+#[cfg(feature = "runtime-benchmarks")]
+pub trait EnsureForParachain {
+	fn ensure(para_id: ParaId);
+}
+
+#[cfg(feature = "runtime-benchmarks")]
+#[impl_trait_for_tuples::impl_for_tuples(30)]
+impl EnsureForParachain for Tuple {
+	fn ensure(para: ParaId) {
+		for_tuples!( #(
+			Tuple::ensure(para);
+		)* );
+	}
+}
diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml
index dc4335a308e1282bd7350522cb2b1216fc209b9c..f2860882b43f422a1d3b96f90e643bdb6ae68f06 100644
--- a/polkadot/runtime/rococo/Cargo.toml
+++ b/polkadot/runtime/rococo/Cargo.toml
@@ -264,6 +264,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-executive/try-runtime",
diff --git a/polkadot/runtime/rococo/src/impls.rs b/polkadot/runtime/rococo/src/impls.rs
index f01440ea02bc7c15377c732d22041e60d3425d66..cac9ee792cd2198bae1a1207f1a6c9c267f383dc 100644
--- a/polkadot/runtime/rococo/src/impls.rs
+++ b/polkadot/runtime/rococo/src/impls.rs
@@ -176,4 +176,9 @@ where
 		)?;
 		Ok(())
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_identity_reaping(_: &AccountId, _: u32, _: u32) {
+		crate::Dmp::make_parachain_reachable(1004);
+	}
 }
diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index bfc1e25339bb2f9e9ab7eeb79b1eacf83d56c55d..f7ce6de8fffdffb32be3847d1751e00ea0a51904 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -2395,14 +2395,14 @@ sp_api::impl_runtime_apis! {
 						ExistentialDepositAsset,
 						xcm_config::PriceForChildParachainDelivery,
 						AssetHubParaId,
-						(),
+						Dmp,
 					>,
 					polkadot_runtime_common::xcm_sender::ToParachainDeliveryHelper<
 						XcmConfig,
 						ExistentialDepositAsset,
 						xcm_config::PriceForChildParachainDelivery,
 						RandomParaId,
-						(),
+						Dmp,
 					>
 				);
 
@@ -2461,7 +2461,7 @@ sp_api::impl_runtime_apis! {
 					ExistentialDepositAsset,
 					xcm_config::PriceForChildParachainDelivery,
 					AssetHubParaId,
-					(),
+					Dmp,
 				>;
 				fn valid_destination() -> Result<Location, BenchmarkError> {
 					Ok(AssetHub::get())
diff --git a/polkadot/runtime/test-runtime/Cargo.toml b/polkadot/runtime/test-runtime/Cargo.toml
index 237643ec029159895c194d8bbdc9eeb82a1556d6..717ddb8a744a917593ee2b346e5b9fe063930ab6 100644
--- a/polkadot/runtime/test-runtime/Cargo.toml
+++ b/polkadot/runtime/test-runtime/Cargo.toml
@@ -152,4 +152,5 @@ runtime-benchmarks = [
 	"sp-staking/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml
index 7f468fd1f5a3cab50cf355982615364ebc491915..7bd476419f7b9cc6a011c8271862c6ab78061d0c 100644
--- a/polkadot/runtime/westend/Cargo.toml
+++ b/polkadot/runtime/westend/Cargo.toml
@@ -285,6 +285,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-election-provider-support/try-runtime",
diff --git a/polkadot/runtime/westend/src/impls.rs b/polkadot/runtime/westend/src/impls.rs
index ac3f9e679f8d3d5d7b1409a858598cc866f7c415..6f1c5e0e3b336a5bbe5a887dedc6d305a98097dd 100644
--- a/polkadot/runtime/westend/src/impls.rs
+++ b/polkadot/runtime/westend/src/impls.rs
@@ -176,4 +176,9 @@ where
 		)?;
 		Ok(())
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_identity_reaping(_: &AccountId, _: u32, _: u32) {
+		crate::Dmp::make_parachain_reachable(1004);
+	}
 }
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index cb546a910f76620e8e6b94fc1fc67a6c70bc62ff..760e878d64755932fef98d071ff627ad860b96e2 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -2566,14 +2566,14 @@ sp_api::impl_runtime_apis! {
 						ExistentialDepositAsset,
 						xcm_config::PriceForChildParachainDelivery,
 						AssetHubParaId,
-						(),
+						Dmp,
 					>,
 					polkadot_runtime_common::xcm_sender::ToParachainDeliveryHelper<
 						xcm_config::XcmConfig,
 						ExistentialDepositAsset,
 						xcm_config::PriceForChildParachainDelivery,
 						RandomParaId,
-						(),
+						Dmp,
 					>
 				);
 
@@ -2639,7 +2639,7 @@ sp_api::impl_runtime_apis! {
 					ExistentialDepositAsset,
 					xcm_config::PriceForChildParachainDelivery,
 					AssetHubParaId,
-					(),
+					Dmp,
 				>;
 				fn valid_destination() -> Result<Location, BenchmarkError> {
 					Ok(AssetHub::get())
diff --git a/polkadot/xcm/Cargo.toml b/polkadot/xcm/Cargo.toml
index ed5a4b83c7968913e697401b7be2249fe2672474..781b9f68485079f2cb0714cdc5f041d1c99114cb 100644
--- a/polkadot/xcm/Cargo.toml
+++ b/polkadot/xcm/Cargo.toml
@@ -48,3 +48,4 @@ json-schema = [
 	"dep:schemars",
 	"sp-weights/json-schema",
 ]
+runtime-benchmarks = ["sp-runtime/runtime-benchmarks"]
diff --git a/polkadot/xcm/pallet-xcm-benchmarks/Cargo.toml b/polkadot/xcm/pallet-xcm-benchmarks/Cargo.toml
index abe2641956903914c46ba882df5d548fc22173a3..2d25ff7e0798808658e19b6c3269c522986fbf70 100644
--- a/polkadot/xcm/pallet-xcm-benchmarks/Cargo.toml
+++ b/polkadot/xcm/pallet-xcm-benchmarks/Cargo.toml
@@ -57,4 +57,5 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/benchmarking.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/benchmarking.rs
index 6ce49074a6e2b1fa02dd0f1fbe4f90db1058e560..4faf3ed935d78b1d84f3bfc34cd97f4d6f3423a5 100644
--- a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/benchmarking.rs
+++ b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/benchmarking.rs
@@ -231,6 +231,13 @@ benchmarks_instance_pallet! {
 		let dest_account = T::AccountIdConverter::convert_location(&dest_location).unwrap();
 		assert!(T::TransactAsset::balance(&dest_account).is_zero());
 
+		// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
+		let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
+			&Default::default(),
+			&dest_location,
+			FeeReason::ChargeFees,
+		);
+
 		let mut executor = new_executor::<T>(Default::default());
 		executor.set_holding(holding.into());
 		let instruction = Instruction::<XcmCallOf<T>>::DepositAsset {
@@ -257,6 +264,13 @@ benchmarks_instance_pallet! {
 		let dest_account = T::AccountIdConverter::convert_location(&dest_location).unwrap();
 		assert!(T::TransactAsset::balance(&dest_account).is_zero());
 
+		// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
+		let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
+			&Default::default(),
+			&dest_location,
+			FeeReason::ChargeFees,
+		);
+
 		let mut executor = new_executor::<T>(Default::default());
 		executor.set_holding(holding.into());
 		let instruction = Instruction::<XcmCallOf<T>>::DepositReserveAsset {
@@ -281,12 +295,20 @@ benchmarks_instance_pallet! {
 
 		// Checked account starts at zero
 		assert!(T::CheckedAccount::get().map_or(true, |(c, _)| T::TransactAsset::balance(&c).is_zero()));
+		let dest_location =  T::valid_destination()?;
+
+		// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
+		let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
+			&Default::default(),
+			&dest_location,
+			FeeReason::ChargeFees,
+		);
 
 		let mut executor = new_executor::<T>(Default::default());
 		executor.set_holding(holding.into());
 		let instruction = Instruction::<XcmCallOf<T>>::InitiateTeleport {
 			assets: asset.into(),
-			dest: T::valid_destination()?,
+			dest: dest_location,
 			xcm: Xcm::new(),
 		};
 		let xcm = Xcm(vec![instruction]);
diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs
index 40a7da58a687c186664404e0a00734b457b60e51..c382f59733ad9da66c520c6a64c04f8308545919 100644
--- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs
+++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs
@@ -293,6 +293,7 @@ benchmarks! {
 		let mut executor = new_executor::<T>(origin.clone());
 		let instruction = Instruction::SubscribeVersion { query_id, max_response_weight };
 		let xcm = Xcm(vec![instruction]);
+		T::DeliveryHelper::ensure_successful_delivery(&origin, &origin, FeeReason::QueryPallet);
 	} : {
 		executor.bench_process(xcm)?;
 	} verify {
@@ -303,6 +304,9 @@ benchmarks! {
 		use xcm_executor::traits::VersionChangeNotifier;
 		// First we need to subscribe to notifications.
 		let (origin, _) = T::transact_origin_and_runtime_call()?;
+
+		T::DeliveryHelper::ensure_successful_delivery(&origin, &origin, FeeReason::QueryPallet);
+
 		let query_id = Default::default();
 		let max_response_weight = Default::default();
 		<T::XcmConfig as xcm_executor::Config>::SubscriptionService::start(
diff --git a/polkadot/xcm/pallet-xcm/Cargo.toml b/polkadot/xcm/pallet-xcm/Cargo.toml
index d3030511df56396530ff66d87786125ac041ae56..890c9f0733345470328578487da88c4cbced86f4 100644
--- a/polkadot/xcm/pallet-xcm/Cargo.toml
+++ b/polkadot/xcm/pallet-xcm/Cargo.toml
@@ -63,6 +63,7 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
 	"xcm-runtime-apis/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs
index d09c81bf434e2ce843b55fc5b05baee121e562c8..f5c78a935093eba608ceeda19357eae89f09de3c 100644
--- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs
+++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs
@@ -96,6 +96,13 @@ benchmarks! {
 		)?
 		.into();
 		let versioned_msg = VersionedXcm::from(msg);
+
+		// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
+		T::DeliveryHelper::ensure_successful_delivery(
+			&Default::default(),
+			&versioned_dest.clone().try_into().unwrap(),
+			FeeReason::ChargeFees,
+		);
 	}: _<RuntimeOrigin<T>>(send_origin, Box::new(versioned_dest), Box::new(versioned_msg))
 
 	teleport_assets {
@@ -164,7 +171,7 @@ benchmarks! {
 		}
 
 		// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
-		let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
+		T::DeliveryHelper::ensure_successful_delivery(
 			&origin_location,
 			&destination,
 			FeeReason::ChargeFees,
@@ -227,6 +234,13 @@ benchmarks! {
 		let versioned_beneficiary: VersionedLocation =
 			AccountId32 { network: None, id: recipient.into() }.into();
 		let versioned_assets: VersionedAssets = assets.into();
+
+		// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
+		T::DeliveryHelper::ensure_successful_delivery(
+			&Default::default(),
+			&versioned_dest.clone().try_into().unwrap(),
+			FeeReason::ChargeFees,
+		);
 	}: _<RuntimeOrigin<T>>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0, WeightLimit::Unlimited)
 	verify {
 		// run provided verification function
@@ -259,6 +273,14 @@ benchmarks! {
 			BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
 		)?
 		.into();
+
+		// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
+		T::DeliveryHelper::ensure_successful_delivery(
+			&Default::default(),
+			&versioned_loc.clone().try_into().unwrap(),
+			FeeReason::ChargeFees,
+		);
+
 	}: _(RawOrigin::Root, Box::new(versioned_loc))
 
 	force_unsubscribe_version_notify {
@@ -266,6 +288,14 @@ benchmarks! {
 			BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
 		)?;
 		let versioned_loc: VersionedLocation = loc.clone().into();
+
+		// Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...)
+		T::DeliveryHelper::ensure_successful_delivery(
+			&Default::default(),
+			&versioned_loc.clone().try_into().unwrap(),
+			FeeReason::ChargeFees,
+		);
+
 		let _ = crate::Pallet::<T>::request_version_notify(loc);
 	}: _(RawOrigin::Root, Box::new(versioned_loc))
 
diff --git a/polkadot/xcm/src/v4/traits.rs b/polkadot/xcm/src/v4/traits.rs
index c4eec522ed03946d8f31a26d2d0dfcb8c2ca3dd0..448d869c19a953ebf702f1c16631aefe8d02c582 100644
--- a/polkadot/xcm/src/v4/traits.rs
+++ b/polkadot/xcm/src/v4/traits.rs
@@ -246,6 +246,10 @@ pub trait SendXcm {
 
 	/// Actually carry out the delivery operation for a previously validated message sending.
 	fn deliver(ticket: Self::Ticket) -> result::Result<XcmHash, SendError>;
+
+	/// Ensure `[Self::delivery]` is successful for the given `location` when called in benchmarks.
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(_location: Option<Location>) {}
 }
 
 #[impl_trait_for_tuples::impl_for_tuples(30)]
@@ -286,6 +290,13 @@ impl SendXcm for Tuple {
 		)* );
 		Err(SendError::Unroutable)
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(location: Option<Location>) {
+		for_tuples!( #(
+			return Tuple::ensure_successful_delivery(location.clone());
+		)* );
+	}
 }
 
 /// Convenience function for using a `SendXcm` implementation. Just interprets the `dest` and wraps
diff --git a/polkadot/xcm/src/v5/traits.rs b/polkadot/xcm/src/v5/traits.rs
new file mode 100644
index 0000000000000000000000000000000000000000..79d3285614287fd98e7cbc8013dd2f45e209c4e5
--- /dev/null
+++ b/polkadot/xcm/src/v5/traits.rs
@@ -0,0 +1,537 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Cross-Consensus Message format data structures.
+
+pub use crate::v3::{Error as OldError, SendError, XcmHash};
+use codec::{Decode, Encode};
+use core::result;
+use scale_info::TypeInfo;
+
+pub use sp_weights::Weight;
+
+use super::*;
+
+/// Error codes used in XCM. The first errors codes have explicit indices and are part of the XCM
+/// format. Those trailing are merely part of the XCM implementation; there is no expectation that
+/// they will retain the same index over time.
+#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)]
+#[scale_info(replace_segment("staging_xcm", "xcm"))]
+#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
+pub enum Error {
+	// Errors that happen due to instructions being executed. These alone are defined in the
+	// XCM specification.
+	/// An arithmetic overflow happened.
+	#[codec(index = 0)]
+	Overflow,
+	/// The instruction is intentionally unsupported.
+	#[codec(index = 1)]
+	Unimplemented,
+	/// Origin Register does not contain a value value for a reserve transfer notification.
+	#[codec(index = 2)]
+	UntrustedReserveLocation,
+	/// Origin Register does not contain a value value for a teleport notification.
+	#[codec(index = 3)]
+	UntrustedTeleportLocation,
+	/// `MultiLocation` value too large to descend further.
+	#[codec(index = 4)]
+	LocationFull,
+	/// `MultiLocation` value ascend more parents than known ancestors of local location.
+	#[codec(index = 5)]
+	LocationNotInvertible,
+	/// The Origin Register does not contain a valid value for instruction.
+	#[codec(index = 6)]
+	BadOrigin,
+	/// The location parameter is not a valid value for the instruction.
+	#[codec(index = 7)]
+	InvalidLocation,
+	/// The given asset is not handled.
+	#[codec(index = 8)]
+	AssetNotFound,
+	/// An asset transaction (like withdraw or deposit) failed (typically due to type conversions).
+	#[codec(index = 9)]
+	FailedToTransactAsset(#[codec(skip)] &'static str),
+	/// An asset cannot be withdrawn, potentially due to lack of ownership, availability or rights.
+	#[codec(index = 10)]
+	NotWithdrawable,
+	/// An asset cannot be deposited under the ownership of a particular location.
+	#[codec(index = 11)]
+	LocationCannotHold,
+	/// Attempt to send a message greater than the maximum supported by the transport protocol.
+	#[codec(index = 12)]
+	ExceedsMaxMessageSize,
+	/// The given message cannot be translated into a format supported by the destination.
+	#[codec(index = 13)]
+	DestinationUnsupported,
+	/// Destination is routable, but there is some issue with the transport mechanism.
+	#[codec(index = 14)]
+	Transport(#[codec(skip)] &'static str),
+	/// Destination is known to be unroutable.
+	#[codec(index = 15)]
+	Unroutable,
+	/// Used by `ClaimAsset` when the given claim could not be recognized/found.
+	#[codec(index = 16)]
+	UnknownClaim,
+	/// Used by `Transact` when the functor cannot be decoded.
+	#[codec(index = 17)]
+	FailedToDecode,
+	/// Used by `Transact` to indicate that the given weight limit could be breached by the
+	/// functor.
+	#[codec(index = 18)]
+	MaxWeightInvalid,
+	/// Used by `BuyExecution` when the Holding Register does not contain payable fees.
+	#[codec(index = 19)]
+	NotHoldingFees,
+	/// Used by `BuyExecution` when the fees declared to purchase weight are insufficient.
+	#[codec(index = 20)]
+	TooExpensive,
+	/// Used by the `Trap` instruction to force an error intentionally. Its code is included.
+	#[codec(index = 21)]
+	Trap(u64),
+	/// Used by `ExpectAsset`, `ExpectError` and `ExpectOrigin` when the expectation was not true.
+	#[codec(index = 22)]
+	ExpectationFalse,
+	/// The provided pallet index was not found.
+	#[codec(index = 23)]
+	PalletNotFound,
+	/// The given pallet's name is different to that expected.
+	#[codec(index = 24)]
+	NameMismatch,
+	/// The given pallet's version has an incompatible version to that expected.
+	#[codec(index = 25)]
+	VersionIncompatible,
+	/// The given operation would lead to an overflow of the Holding Register.
+	#[codec(index = 26)]
+	HoldingWouldOverflow,
+	/// The message was unable to be exported.
+	#[codec(index = 27)]
+	ExportError,
+	/// `MultiLocation` value failed to be reanchored.
+	#[codec(index = 28)]
+	ReanchorFailed,
+	/// No deal is possible under the given constraints.
+	#[codec(index = 29)]
+	NoDeal,
+	/// Fees were required which the origin could not pay.
+	#[codec(index = 30)]
+	FeesNotMet,
+	/// Some other error with locking.
+	#[codec(index = 31)]
+	LockError,
+	/// The state was not in a condition where the operation was valid to make.
+	#[codec(index = 32)]
+	NoPermission,
+	/// The universal location of the local consensus is improper.
+	#[codec(index = 33)]
+	Unanchored,
+	/// An asset cannot be deposited, probably because (too much of) it already exists.
+	#[codec(index = 34)]
+	NotDepositable,
+	/// Too many assets matched the given asset filter.
+	#[codec(index = 35)]
+	TooManyAssets,
+
+	// Errors that happen prior to instructions being executed. These fall outside of the XCM
+	// spec.
+	/// XCM version not able to be handled.
+	UnhandledXcmVersion,
+	/// Execution of the XCM would potentially result in a greater weight used than weight limit.
+	WeightLimitReached(Weight),
+	/// The XCM did not pass the barrier condition for execution.
+	///
+	/// The barrier condition differs on different chains and in different circumstances, but
+	/// generally it means that the conditions surrounding the message were not such that the chain
+	/// considers the message worth spending time executing. Since most chains lift the barrier to
+	/// execution on appropriate payment, presentation of an NFT voucher, or based on the message
+	/// origin, it means that none of those were the case.
+	Barrier,
+	/// The weight of an XCM message is not computable ahead of execution.
+	WeightNotComputable,
+	/// Recursion stack limit reached
+	// TODO(https://github.com/paritytech/polkadot-sdk/issues/6199): This should have a fixed index since
+	// we use it in `FrameTransactionalProcessor` // which is used in instructions.
+	// Or we should create a different error for that.
+	ExceedsStackLimit,
+}
+
+impl TryFrom<OldError> for Error {
+	type Error = ();
+	fn try_from(old_error: OldError) -> result::Result<Error, ()> {
+		use OldError::*;
+		Ok(match old_error {
+			Overflow => Self::Overflow,
+			Unimplemented => Self::Unimplemented,
+			UntrustedReserveLocation => Self::UntrustedReserveLocation,
+			UntrustedTeleportLocation => Self::UntrustedTeleportLocation,
+			LocationFull => Self::LocationFull,
+			LocationNotInvertible => Self::LocationNotInvertible,
+			BadOrigin => Self::BadOrigin,
+			InvalidLocation => Self::InvalidLocation,
+			AssetNotFound => Self::AssetNotFound,
+			FailedToTransactAsset(s) => Self::FailedToTransactAsset(s),
+			NotWithdrawable => Self::NotWithdrawable,
+			LocationCannotHold => Self::LocationCannotHold,
+			ExceedsMaxMessageSize => Self::ExceedsMaxMessageSize,
+			DestinationUnsupported => Self::DestinationUnsupported,
+			Transport(s) => Self::Transport(s),
+			Unroutable => Self::Unroutable,
+			UnknownClaim => Self::UnknownClaim,
+			FailedToDecode => Self::FailedToDecode,
+			MaxWeightInvalid => Self::MaxWeightInvalid,
+			NotHoldingFees => Self::NotHoldingFees,
+			TooExpensive => Self::TooExpensive,
+			Trap(i) => Self::Trap(i),
+			ExpectationFalse => Self::ExpectationFalse,
+			PalletNotFound => Self::PalletNotFound,
+			NameMismatch => Self::NameMismatch,
+			VersionIncompatible => Self::VersionIncompatible,
+			HoldingWouldOverflow => Self::HoldingWouldOverflow,
+			ExportError => Self::ExportError,
+			ReanchorFailed => Self::ReanchorFailed,
+			NoDeal => Self::NoDeal,
+			FeesNotMet => Self::FeesNotMet,
+			LockError => Self::LockError,
+			NoPermission => Self::NoPermission,
+			Unanchored => Self::Unanchored,
+			NotDepositable => Self::NotDepositable,
+			UnhandledXcmVersion => Self::UnhandledXcmVersion,
+			WeightLimitReached(weight) => Self::WeightLimitReached(weight),
+			Barrier => Self::Barrier,
+			WeightNotComputable => Self::WeightNotComputable,
+			ExceedsStackLimit => Self::ExceedsStackLimit,
+		})
+	}
+}
+
+impl MaxEncodedLen for Error {
+	fn max_encoded_len() -> usize {
+		// TODO: max_encoded_len doesn't quite work here as it tries to take notice of the fields
+		// marked `codec(skip)`. We can hard-code it with the right answer for now.
+		1
+	}
+}
+
+impl From<SendError> for Error {
+	fn from(e: SendError) -> Self {
+		match e {
+			SendError::NotApplicable | SendError::Unroutable | SendError::MissingArgument =>
+				Error::Unroutable,
+			SendError::Transport(s) => Error::Transport(s),
+			SendError::DestinationUnsupported => Error::DestinationUnsupported,
+			SendError::ExceedsMaxMessageSize => Error::ExceedsMaxMessageSize,
+			SendError::Fees => Error::FeesNotMet,
+		}
+	}
+}
+
+pub type Result = result::Result<(), Error>;
+
+/// Outcome of an XCM execution.
+#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)]
+pub enum Outcome {
+	/// Execution completed successfully; given weight was used.
+	Complete { used: Weight },
+	/// Execution started, but did not complete successfully due to the given error; given weight
+	/// was used.
+	Incomplete { used: Weight, error: Error },
+	/// Execution did not start due to the given error.
+	Error { error: Error },
+}
+
+impl Outcome {
+	pub fn ensure_complete(self) -> Result {
+		match self {
+			Outcome::Complete { .. } => Ok(()),
+			Outcome::Incomplete { error, .. } => Err(error),
+			Outcome::Error { error, .. } => Err(error),
+		}
+	}
+	pub fn ensure_execution(self) -> result::Result<Weight, Error> {
+		match self {
+			Outcome::Complete { used, .. } => Ok(used),
+			Outcome::Incomplete { used, .. } => Ok(used),
+			Outcome::Error { error, .. } => Err(error),
+		}
+	}
+	/// How much weight was used by the XCM execution attempt.
+	pub fn weight_used(&self) -> Weight {
+		match self {
+			Outcome::Complete { used, .. } => *used,
+			Outcome::Incomplete { used, .. } => *used,
+			Outcome::Error { .. } => Weight::zero(),
+		}
+	}
+}
+
+impl From<Error> for Outcome {
+	fn from(error: Error) -> Self {
+		Self::Error { error }
+	}
+}
+
+pub trait PreparedMessage {
+	fn weight_of(&self) -> Weight;
+}
+
+/// Type of XCM message executor.
+pub trait ExecuteXcm<Call> {
+	type Prepared: PreparedMessage;
+	fn prepare(message: Xcm<Call>) -> result::Result<Self::Prepared, Xcm<Call>>;
+	fn execute(
+		origin: impl Into<Location>,
+		pre: Self::Prepared,
+		id: &mut XcmHash,
+		weight_credit: Weight,
+	) -> Outcome;
+	fn prepare_and_execute(
+		origin: impl Into<Location>,
+		message: Xcm<Call>,
+		id: &mut XcmHash,
+		weight_limit: Weight,
+		weight_credit: Weight,
+	) -> Outcome {
+		let pre = match Self::prepare(message) {
+			Ok(x) => x,
+			Err(_) => return Outcome::Error { error: Error::WeightNotComputable },
+		};
+		let xcm_weight = pre.weight_of();
+		if xcm_weight.any_gt(weight_limit) {
+			return Outcome::Error { error: Error::WeightLimitReached(xcm_weight) }
+		}
+		Self::execute(origin, pre, id, weight_credit)
+	}
+
+	/// Deduct some `fees` to the sovereign account of the given `location` and place them as per
+	/// the convention for fees.
+	fn charge_fees(location: impl Into<Location>, fees: Assets) -> Result;
+}
+
+pub enum Weightless {}
+impl PreparedMessage for Weightless {
+	fn weight_of(&self) -> Weight {
+		unreachable!()
+	}
+}
+
+impl<C> ExecuteXcm<C> for () {
+	type Prepared = Weightless;
+	fn prepare(message: Xcm<C>) -> result::Result<Self::Prepared, Xcm<C>> {
+		Err(message)
+	}
+	fn execute(_: impl Into<Location>, _: Self::Prepared, _: &mut XcmHash, _: Weight) -> Outcome {
+		unreachable!()
+	}
+	fn charge_fees(_location: impl Into<Location>, _fees: Assets) -> Result {
+		Err(Error::Unimplemented)
+	}
+}
+
+pub trait Reanchorable: Sized {
+	/// Type to return in case of an error.
+	type Error: Debug;
+
+	/// Mutate `self` so that it represents the same location from the point of view of `target`.
+	/// The context of `self` is provided as `context`.
+	///
+	/// Does not modify `self` in case of overflow.
+	fn reanchor(
+		&mut self,
+		target: &Location,
+		context: &InteriorLocation,
+	) -> core::result::Result<(), ()>;
+
+	/// Consume `self` and return a new value representing the same location from the point of view
+	/// of `target`. The context of `self` is provided as `context`.
+	///
+	/// Returns the original `self` in case of overflow.
+	fn reanchored(
+		self,
+		target: &Location,
+		context: &InteriorLocation,
+	) -> core::result::Result<Self, Self::Error>;
+}
+
+/// Result value when attempting to send an XCM message.
+pub type SendResult<T> = result::Result<(T, Assets), SendError>;
+
+/// Utility for sending an XCM message to a given location.
+///
+/// These can be amalgamated in tuples to form sophisticated routing systems. In tuple format, each
+/// router might return `NotApplicable` to pass the execution to the next sender item. Note that
+/// each `NotApplicable` might alter the destination and the XCM message for to the next router.
+///
+/// # Example
+/// ```rust
+/// # use codec::Encode;
+/// # use staging_xcm::v5::{prelude::*, Weight};
+/// # use staging_xcm::VersionedXcm;
+/// # use std::convert::Infallible;
+///
+/// /// A sender that only passes the message through and does nothing.
+/// struct Sender1;
+/// impl SendXcm for Sender1 {
+///     type Ticket = Infallible;
+///     fn validate(_: &mut Option<Location>, _: &mut Option<Xcm<()>>) -> SendResult<Infallible> {
+///         Err(SendError::NotApplicable)
+///     }
+///     fn deliver(_: Infallible) -> Result<XcmHash, SendError> {
+///         unreachable!()
+///     }
+/// }
+///
+/// /// A sender that accepts a message that has two junctions, otherwise stops the routing.
+/// struct Sender2;
+/// impl SendXcm for Sender2 {
+///     type Ticket = ();
+///     fn validate(destination: &mut Option<Location>, message: &mut Option<Xcm<()>>) -> SendResult<()> {
+///         match destination.as_ref().ok_or(SendError::MissingArgument)?.unpack() {
+///             (0, [j1, j2]) => Ok(((), Assets::new())),
+///             _ => Err(SendError::Unroutable),
+///         }
+///     }
+///     fn deliver(_: ()) -> Result<XcmHash, SendError> {
+///         Ok([0; 32])
+///     }
+/// }
+///
+/// /// A sender that accepts a message from a parent, passing through otherwise.
+/// struct Sender3;
+/// impl SendXcm for Sender3 {
+///     type Ticket = ();
+///     fn validate(destination: &mut Option<Location>, message: &mut Option<Xcm<()>>) -> SendResult<()> {
+///         match destination.as_ref().ok_or(SendError::MissingArgument)?.unpack() {
+///             (1, []) => Ok(((), Assets::new())),
+///             _ => Err(SendError::NotApplicable),
+///         }
+///     }
+///     fn deliver(_: ()) -> Result<XcmHash, SendError> {
+///         Ok([0; 32])
+///     }
+/// }
+///
+/// // A call to send via XCM. We don't really care about this.
+/// # fn main() {
+/// let call: Vec<u8> = ().encode();
+/// let message = Xcm(vec![Instruction::Transact {
+///     origin_kind: OriginKind::Superuser,
+///     call: call.into(),
+///     fallback_max_weight: None,
+/// }]);
+/// let message_hash = message.using_encoded(sp_io::hashing::blake2_256);
+///
+/// // Sender2 will block this.
+/// assert!(send_xcm::<(Sender1, Sender2, Sender3)>(Parent.into(), message.clone()).is_err());
+///
+/// // Sender3 will catch this.
+/// assert!(send_xcm::<(Sender1, Sender3)>(Parent.into(), message.clone()).is_ok());
+/// # }
+/// ```
+pub trait SendXcm {
+	/// Intermediate value which connects the two phases of the send operation.
+	type Ticket;
+
+	/// Check whether the given `_message` is deliverable to the given `_destination` and if so
+	/// determine the cost which will be paid by this chain to do so, returning a `Validated` token
+	/// which can be used to enact delivery.
+	///
+	/// The `destination` and `message` must be `Some` (or else an error will be returned) and they
+	/// may only be consumed if the `Err` is not `NotApplicable`.
+	///
+	/// If it is not a destination which can be reached with this type but possibly could by others,
+	/// then this *MUST* return `NotApplicable`. Any other error will cause the tuple
+	/// implementation to exit early without trying other type fields.
+	fn validate(
+		destination: &mut Option<Location>,
+		message: &mut Option<Xcm<()>>,
+	) -> SendResult<Self::Ticket>;
+
+	/// Actually carry out the delivery operation for a previously validated message sending.
+	fn deliver(ticket: Self::Ticket) -> result::Result<XcmHash, SendError>;
+
+	/// Ensure `[Self::delivery]` is successful for the given `location` when called in benchmarks.
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(_location: Option<Location>) {}
+}
+
+#[impl_trait_for_tuples::impl_for_tuples(30)]
+impl SendXcm for Tuple {
+	for_tuples! { type Ticket = (#( Option<Tuple::Ticket> ),* ); }
+
+	fn validate(
+		destination: &mut Option<Location>,
+		message: &mut Option<Xcm<()>>,
+	) -> SendResult<Self::Ticket> {
+		let mut maybe_cost: Option<Assets> = None;
+		let one_ticket: Self::Ticket = (for_tuples! { #(
+			if maybe_cost.is_some() {
+				None
+			} else {
+				match Tuple::validate(destination, message) {
+					Err(SendError::NotApplicable) => None,
+					Err(e) => { return Err(e) },
+					Ok((v, c)) => {
+						maybe_cost = Some(c);
+						Some(v)
+					},
+				}
+			}
+		),* });
+		if let Some(cost) = maybe_cost {
+			Ok((one_ticket, cost))
+		} else {
+			Err(SendError::NotApplicable)
+		}
+	}
+
+	fn deliver(one_ticket: Self::Ticket) -> result::Result<XcmHash, SendError> {
+		for_tuples!( #(
+			if let Some(validated) = one_ticket.Tuple {
+				return Tuple::deliver(validated);
+			}
+		)* );
+		Err(SendError::Unroutable)
+	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(location: Option<Location>) {
+		for_tuples!( #(
+			return Tuple::ensure_successful_delivery(location.clone());
+		)* );
+	}
+}
+
+/// Convenience function for using a `SendXcm` implementation. Just interprets the `dest` and wraps
+/// both in `Some` before passing them as mutable references into `T::send_xcm`.
+pub fn validate_send<T: SendXcm>(dest: Location, msg: Xcm<()>) -> SendResult<T::Ticket> {
+	T::validate(&mut Some(dest), &mut Some(msg))
+}
+
+/// Convenience function for using a `SendXcm` implementation. Just interprets the `dest` and wraps
+/// both in `Some` before passing them as mutable references into `T::send_xcm`.
+///
+/// Returns either `Ok` with the price of the delivery, or `Err` with the reason why the message
+/// could not be sent.
+///
+/// Generally you'll want to validate and get the price first to ensure that the sender can pay it
+/// before actually doing the delivery.
+pub fn send_xcm<T: SendXcm>(
+	dest: Location,
+	msg: Xcm<()>,
+) -> result::Result<(XcmHash, Assets), SendError> {
+	let (ticket, price) = T::validate(&mut Some(dest), &mut Some(msg))?;
+	let hash = T::deliver(ticket)?;
+	Ok((hash, price))
+}
diff --git a/polkadot/xcm/xcm-builder/Cargo.toml b/polkadot/xcm/xcm-builder/Cargo.toml
index 5c63bd74d8b85d1003424d6177849bd67b58ce82..5c414fb68caefc26c23531b717c2c0988f2bd52f 100644
--- a/polkadot/xcm/xcm-builder/Cargo.toml
+++ b/polkadot/xcm/xcm-builder/Cargo.toml
@@ -47,6 +47,7 @@ runtime-benchmarks = [
 	"polkadot-parachain-primitives/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 std = [
 	"codec/std",
diff --git a/polkadot/xcm/xcm-builder/src/pay.rs b/polkadot/xcm/xcm-builder/src/pay.rs
index 978c6870cdaf1e65ffc74adb175fd2e80ba53031..0093051290b74bcda97721944361d2af562ed738 100644
--- a/polkadot/xcm/xcm-builder/src/pay.rs
+++ b/polkadot/xcm/xcm-builder/src/pay.rs
@@ -70,8 +70,8 @@ impl<
 		Router: SendXcm,
 		Querier: QueryHandler,
 		Timeout: Get<Querier::BlockNumber>,
-		Beneficiary: Clone,
-		AssetKind,
+		Beneficiary: Clone + core::fmt::Debug,
+		AssetKind: core::fmt::Debug,
 		AssetKindToLocatableAsset: TryConvert<AssetKind, LocatableAssetId>,
 		BeneficiaryRefToLocation: for<'a> TryConvert<&'a Beneficiary, Location>,
 	> Pay
@@ -144,10 +144,9 @@ impl<
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn ensure_successful(_: &Self::Beneficiary, _: Self::AssetKind, _: Self::Balance) {
-		// We cannot generally guarantee this will go through successfully since we don't have any
-		// control over the XCM transport layers. We just assume that the benchmark environment
-		// will be sending it somewhere sensible.
+	fn ensure_successful(_: &Self::Beneficiary, asset_kind: Self::AssetKind, _: Self::Balance) {
+		let locatable = AssetKindToLocatableAsset::try_convert(asset_kind).unwrap();
+		Router::ensure_successful_delivery(Some(locatable.location));
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
diff --git a/polkadot/xcm/xcm-builder/src/routing.rs b/polkadot/xcm/xcm-builder/src/routing.rs
index d82cc0641ec406c9fbcfedc8f679b47766459875..fd7546b02aa78a1c99b8f8ed04ef52a23433179e 100644
--- a/polkadot/xcm/xcm-builder/src/routing.rs
+++ b/polkadot/xcm/xcm-builder/src/routing.rs
@@ -60,6 +60,11 @@ impl<Inner: SendXcm> SendXcm for WithUniqueTopic<Inner> {
 		Inner::deliver(ticket)?;
 		Ok(unique_id)
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(location: Option<Location>) {
+		Inner::ensure_successful_delivery(location);
+	}
 }
 impl<Inner: InspectMessageQueues> InspectMessageQueues for WithUniqueTopic<Inner> {
 	fn clear_messages() {
@@ -114,6 +119,11 @@ impl<Inner: SendXcm, TopicSource: SourceTopic> SendXcm for WithTopicSource<Inner
 		Inner::deliver(ticket)?;
 		Ok(unique_id)
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(location: Option<Location>) {
+		Inner::ensure_successful_delivery(location);
+	}
 }
 
 /// Trait for a type which ensures all requirements for successful delivery with XCM transport
@@ -211,4 +221,9 @@ impl<Inner: SendXcm> SendXcm for EnsureDecodableXcm<Inner> {
 	fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
 		Inner::deliver(ticket)
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(location: Option<Location>) {
+		Inner::ensure_successful_delivery(location);
+	}
 }
diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/pay.rs b/polkadot/xcm/xcm-builder/src/tests/pay/pay.rs
index 062faee2abd96a07afda49883adf86e9b2107e5a..b4718edc6c9889cf8c5b248a2a97dd19c3b5eac5 100644
--- a/polkadot/xcm/xcm-builder/src/tests/pay/pay.rs
+++ b/polkadot/xcm/xcm-builder/src/tests/pay/pay.rs
@@ -22,7 +22,7 @@ use frame_support::{assert_ok, traits::tokens::Pay};
 
 /// Type representing both a location and an asset that is held at that location.
 /// The id of the held asset is relative to the location where it is being held.
-#[derive(Encode, Decode, Clone, PartialEq, Eq)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
 pub struct AssetKind {
 	destination: Location,
 	asset_id: AssetId,
diff --git a/polkadot/xcm/xcm-builder/src/universal_exports.rs b/polkadot/xcm/xcm-builder/src/universal_exports.rs
index aae8438c78d2e1685c323faf38d89b0a52578cad..6b3c3adf737dbb6e938d59383c5100041c493d52 100644
--- a/polkadot/xcm/xcm-builder/src/universal_exports.rs
+++ b/polkadot/xcm/xcm-builder/src/universal_exports.rs
@@ -95,6 +95,9 @@ impl<Exporter: ExportXcm, UniversalLocation: Get<InteriorLocation>> SendXcm
 	fn deliver(ticket: Exporter::Ticket) -> Result<XcmHash, SendError> {
 		Exporter::deliver(ticket)
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(_: Option<Location>) {}
 }
 
 pub trait ExporterFor {
@@ -261,6 +264,11 @@ impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorLocat
 	fn deliver(validation: Self::Ticket) -> Result<XcmHash, SendError> {
 		Router::deliver(validation)
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(location: Option<Location>) {
+		Router::ensure_successful_delivery(location);
+	}
 }
 
 /// Implementation of `SendXcm` which wraps the message inside an `ExportMessage` instruction
@@ -361,6 +369,11 @@ impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorLocat
 	fn deliver(ticket: Router::Ticket) -> Result<XcmHash, SendError> {
 		Router::deliver(ticket)
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn ensure_successful_delivery(location: Option<Location>) {
+		Router::ensure_successful_delivery(location);
+	}
 }
 
 impl<Bridges, Router, UniversalLocation> InspectMessageQueues
@@ -613,6 +626,9 @@ mod tests {
 		fn deliver(_ticket: Self::Ticket) -> Result<XcmHash, SendError> {
 			Ok([0; 32])
 		}
+
+		#[cfg(feature = "runtime-benchmarks")]
+		fn ensure_successful_delivery(_: Option<Location>) {}
 	}
 	impl<Filter: Contains<(NetworkId, InteriorLocation)>> ExportXcm for OkFor<Filter> {
 		type Ticket = ();
diff --git a/polkadot/xcm/xcm-executor/Cargo.toml b/polkadot/xcm/xcm-executor/Cargo.toml
index 755016a491701769d2fc1803753fef2d6fc503b3..88bbd94bcc68167a39de9867f969daae4ce386ea 100644
--- a/polkadot/xcm/xcm-executor/Cargo.toml
+++ b/polkadot/xcm/xcm-executor/Cargo.toml
@@ -30,6 +30,7 @@ runtime-benchmarks = [
 	"frame-benchmarking/runtime-benchmarks",
 	"frame-support/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 std = [
 	"codec/std",
diff --git a/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml b/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml
index 0045295deb0f59228d8418d6f31fb6ae0c756688..a27b62be533b24ba1b0cd7089b8b865cae00e0ae 100644
--- a/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml
+++ b/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml
@@ -13,14 +13,17 @@ workspace = true
 [dependencies]
 codec = { workspace = true, default-features = true }
 frame-support.workspace = true
+frame-system.workspace = true
 futures = { workspace = true }
 pallet-transaction-payment.workspace = true
 pallet-transaction-payment.default-features = true
+pallet-sudo.workspace = true
 pallet-xcm.workspace = true
 pallet-xcm.default-features = true
 polkadot-test-client.workspace = true
 polkadot-test-runtime.workspace = true
 polkadot-test-service.workspace = true
+polkadot-runtime-parachains.workspace = true
 sp-consensus.workspace = true
 sp-consensus.default-features = true
 sp-keyring.workspace = true
@@ -38,4 +41,4 @@ sp-core.default-features = true
 
 [features]
 default = ["std"]
-std = ["frame-support/std", "sp-runtime/std", "xcm/std"]
+std = ["sp-runtime/std", "xcm/std"]
diff --git a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
index 6f44cc0a75d55267426f3044d369ec30fce8b550..5098a6e6042f5779655de83b615f44cec2b56d89 100644
--- a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
+++ b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
@@ -376,6 +376,26 @@ fn deposit_reserve_asset_works_for_any_xcm_sender() {
 
 	let mut block_builder = client.init_polkadot_block_builder();
 
+	// Make the para available, so that `DMP` doesn't reject the XCM because the para is unknown.
+	let make_para_available =
+		construct_extrinsic(
+			&client,
+			polkadot_test_runtime::RuntimeCall::Sudo(pallet_sudo::Call::sudo {
+				call: Box::new(polkadot_test_runtime::RuntimeCall::System(
+					frame_system::Call::set_storage {
+						items: vec![(
+							polkadot_runtime_parachains::paras::Heads::<
+								polkadot_test_runtime::Runtime,
+							>::hashed_key_for(2000u32),
+							vec![1, 2, 3],
+						)],
+					},
+				)),
+			}),
+			sp_keyring::Sr25519Keyring::Alice,
+			0,
+		);
+
 	// Simulate execution of an incoming XCM message at the reserve chain
 	let execute = construct_extrinsic(
 		&client,
@@ -384,9 +404,12 @@ fn deposit_reserve_asset_works_for_any_xcm_sender() {
 			max_weight: Weight::from_parts(1_000_000_000, 1024 * 1024),
 		}),
 		sp_keyring::Sr25519Keyring::Alice,
-		0,
+		1,
 	);
 
+	block_builder
+		.push_polkadot_extrinsic(make_para_available)
+		.expect("pushes extrinsic");
 	block_builder.push_polkadot_extrinsic(execute).expect("pushes extrinsic");
 
 	let block = block_builder.build().expect("Finalizes the block").block;
diff --git a/polkadot/xcm/xcm-runtime-apis/Cargo.toml b/polkadot/xcm/xcm-runtime-apis/Cargo.toml
index 820f6b943cab075aace77e292520c0f893592d61..400e250caa9ea13ba57d6f6bdb863150b8e70a1c 100644
--- a/polkadot/xcm/xcm-runtime-apis/Cargo.toml
+++ b/polkadot/xcm/xcm-runtime-apis/Cargo.toml
@@ -46,4 +46,5 @@ std = [
 runtime-benchmarks = [
 	"frame-support/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/polkadot/xcm/xcm-simulator/example/Cargo.toml b/polkadot/xcm/xcm-simulator/example/Cargo.toml
index 33347e749078f9d92cb0f474f833a503f9de99fb..cb3bbcb9fc33a586804939002af048c297ff0346 100644
--- a/polkadot/xcm/xcm-simulator/example/Cargo.toml
+++ b/polkadot/xcm/xcm-simulator/example/Cargo.toml
@@ -64,4 +64,5 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml b/polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml
index 2168af5dbf2a976f4b4d68f0a0915c0d7691ed30..2e3e9af5e9947729673b4779998d34f5db574777 100644
--- a/polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml
+++ b/polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml
@@ -75,6 +75,7 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 
 [[bin]]
diff --git a/prdoc/pr_6604.prdoc b/prdoc/pr_6604.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..dc198287ff679ac7b03d2239eae1f4dd80f71c9e
--- /dev/null
+++ b/prdoc/pr_6604.prdoc
@@ -0,0 +1,106 @@
+title: 'dmp: Check that the para exist before delivering a message'
+doc:
+- audience: Runtime Dev
+  description: |
+    Ensure that a para exists before trying to deliver a message to it. 
+    Besides that `ensure_successful_delivery` function is added to `SendXcm`. This function
+    should be used by benchmarks to ensure that the delivery of a Xcm will work in the benchmark.
+crates:
+- name: polkadot-runtime-parachains
+  bump: major
+- name: polkadot-runtime-common
+  bump: major
+- name: polkadot-parachain-primitives
+  bump: major
+- name: rococo-runtime
+  bump: major
+- name: westend-runtime
+  bump: major
+- name: pallet-xcm-benchmarks
+  bump: major
+- name: pallet-xcm
+  bump: major
+- name: cumulus-pallet-parachain-system
+  bump: major
+- name: staging-xcm
+  bump: major
+- name: staging-xcm-builder
+  bump: major
+- name: bridge-runtime-common
+  bump: major
+- name: pallet-xcm-bridge-hub-router
+  bump: major
+- name: pallet-xcm-bridge-hub
+  bump: major
+- name: snowbridge-pallet-inbound-queue
+  bump: major
+- name: snowbridge-pallet-system
+  bump: major
+- name: snowbridge-core
+  bump: major
+- name: snowbridge-router-primitives
+  bump: major
+- name: snowbridge-runtime-common
+  bump: major
+- name: snowbridge-runtime-test-common
+  bump: major
+- name: cumulus-pallet-dmp-queue
+  bump: major
+- name: cumulus-pallet-xcmp-queue
+  bump: major
+- name: parachains-common
+  bump: major
+- name: asset-hub-rococo-runtime
+  bump: major
+- name: asset-hub-westend-runtime
+  bump: major
+- name: assets-common
+  bump: major
+- name: bridge-hub-rococo-runtime
+  bump: major
+- name: bridge-hub-westend-runtime
+  bump: major
+- name: bridge-hub-common
+  bump: major
+- name: collectives-westend-runtime
+  bump: major
+- name: contracts-rococo-runtime
+  bump: major
+- name: coretime-rococo-runtime
+  bump: major
+- name: coretime-westend-runtime
+  bump: major
+- name: glutton-westend-runtime
+  bump: major
+- name: people-rococo-runtime
+  bump: major
+- name: people-westend-runtime
+  bump: major
+- name: penpal-runtime
+  bump: major
+- name: rococo-parachain-runtime
+  bump: major
+- name: polkadot-parachain-bin
+  bump: major
+- name: cumulus-primitives-core
+  bump: major
+- name: cumulus-primitives-utility
+  bump: major
+- name: polkadot-service
+  bump: major
+- name: staging-xcm-executor
+  bump: major
+- name: xcm-runtime-apis
+  bump: major
+- name: xcm-simulator-example
+  bump: major
+- name: pallet-contracts
+  bump: major
+- name: pallet-contracts-mock-network
+  bump: major
+- name: pallet-revive
+  bump: major
+- name: pallet-revive-mock-network
+  bump: major
+- name: polkadot-sdk
+  bump: major
diff --git a/substrate/frame/contracts/Cargo.toml b/substrate/frame/contracts/Cargo.toml
index e69247e30271d4229c3dc1442d925bf5f0841fcc..f230c96dd0ed3230b9c4e66270d7b0fe97f978af 100644
--- a/substrate/frame/contracts/Cargo.toml
+++ b/substrate/frame/contracts/Cargo.toml
@@ -110,6 +110,7 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"wasm-instrument",
 	"xcm-builder/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/substrate/frame/contracts/mock-network/Cargo.toml b/substrate/frame/contracts/mock-network/Cargo.toml
index a46417189ecf460dd921d914f93310470afe74db..ddfb5c620256ce3604a0329dc3b09f7153f88df8 100644
--- a/substrate/frame/contracts/mock-network/Cargo.toml
+++ b/substrate/frame/contracts/mock-network/Cargo.toml
@@ -102,4 +102,5 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/substrate/frame/revive/Cargo.toml b/substrate/frame/revive/Cargo.toml
index 2629eacb8b2afb4f8926a97ac9c2dd6b0fc40611..2fca7c35b98fa175e52a4b7dbabd73daaeb52e9b 100644
--- a/substrate/frame/revive/Cargo.toml
+++ b/substrate/frame/revive/Cargo.toml
@@ -103,6 +103,7 @@ runtime-benchmarks = [
 	"pallet-balances/runtime-benchmarks",
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
 try-runtime = [
 	"frame-support/try-runtime",
diff --git a/substrate/frame/revive/mock-network/Cargo.toml b/substrate/frame/revive/mock-network/Cargo.toml
index c4acc2d131ce454c8e433f105c72ec5bd4d24a68..a211b523b23159f24d36fa0b03161e7241d44905 100644
--- a/substrate/frame/revive/mock-network/Cargo.toml
+++ b/substrate/frame/revive/mock-network/Cargo.toml
@@ -98,4 +98,5 @@ runtime-benchmarks = [
 	"sp-runtime/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"xcm-executor/runtime-benchmarks",
+	"xcm/runtime-benchmarks",
 ]
diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml
index 3e9c3e85437ffe65d93f6d3f242e3a3c5f844027..2112301c381f958ad993eaf7b0d77f60224278e2 100644
--- a/umbrella/Cargo.toml
+++ b/umbrella/Cargo.toml
@@ -359,6 +359,7 @@ runtime-benchmarks = [
 	"staging-node-inspect?/runtime-benchmarks",
 	"staging-xcm-builder?/runtime-benchmarks",
 	"staging-xcm-executor?/runtime-benchmarks",
+	"staging-xcm?/runtime-benchmarks",
 	"xcm-runtime-apis?/runtime-benchmarks",
 ]
 try-runtime = [