diff --git a/Cargo.lock b/Cargo.lock
index 950b4e0889a177dcd8b26c35adb38f85b14d116b..d9791ec0147fd2b1b761a0ab5599d0711565d0e7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -22323,10 +22323,12 @@ dependencies = [
  "pallet-transaction-payment",
  "pallet-xcm",
  "parity-scale-codec",
+ "polkadot-service",
  "polkadot-test-client",
  "polkadot-test-runtime",
  "polkadot-test-service",
  "sp-consensus",
+ "sp-core",
  "sp-keyring",
  "sp-runtime",
  "sp-state-machine",
diff --git a/polkadot/node/test/service/src/chain_spec.rs b/polkadot/node/test/service/src/chain_spec.rs
index 0295090b9521551533d012addeda064595dbeac3..4cc387317c3f0f15990825ee377e07ae82925073 100644
--- a/polkadot/node/test/service/src/chain_spec.rs
+++ b/polkadot/node/test/service/src/chain_spec.rs
@@ -169,6 +169,7 @@ fn polkadot_testnet_genesis(
 				paras_availability_period: 4,
 				no_show_slots: 10,
 				minimum_validation_upgrade_delay: 5,
+				max_downward_message_size: 1024,
 				..Default::default()
 			},
 		}
diff --git a/polkadot/runtime/test-runtime/src/xcm_config.rs b/polkadot/runtime/test-runtime/src/xcm_config.rs
index a81d35f4d788f1628cf20cf5cbd0e366828101ff..a48bca17e9ff988da3d0ca4601003f3f6d96a71d 100644
--- a/polkadot/runtime/test-runtime/src/xcm_config.rs
+++ b/polkadot/runtime/test-runtime/src/xcm_config.rs
@@ -16,14 +16,16 @@
 
 use frame_support::{
 	parameter_types,
-	traits::{Everything, Nothing},
+	traits::{Everything, Get, Nothing},
 	weights::Weight,
 };
 use frame_system::EnsureRoot;
+use polkadot_runtime_parachains::FeeTracker;
+use runtime_common::xcm_sender::{ChildParachainRouter, PriceForMessageDelivery};
 use xcm::latest::prelude::*;
 use xcm_builder::{
 	AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor,
-	SignedAccountId32AsNative, SignedToAccountId32,
+	SignedAccountId32AsNative, SignedToAccountId32, WithUniqueTopic,
 };
 use xcm_executor::{
 	traits::{TransactAsset, WeightTrader},
@@ -36,6 +38,8 @@ parameter_types! {
 	pub const MaxInstructions: u32 = 100;
 	pub const MaxAssetsIntoHolding: u32 = 16;
 	pub const UniversalLocation: xcm::latest::InteriorLocation = xcm::latest::Junctions::Here;
+	pub TokenLocation: Location = Here.into_location();
+	pub FeeAssetId: AssetId = AssetId(TokenLocation::get());
 }
 
 /// Type to convert an `Origin` type value into a `Location` value which represents an interior
@@ -45,17 +49,43 @@ pub type LocalOriginToLocation = (
 	SignedToAccountId32<crate::RuntimeOrigin, crate::AccountId, AnyNetwork>,
 );
 
-pub struct DoNothingRouter;
-impl SendXcm for DoNothingRouter {
-	type Ticket = ();
-	fn validate(_dest: &mut Option<Location>, _msg: &mut Option<Xcm<()>>) -> SendResult<()> {
-		Ok(((), Assets::new()))
-	}
-	fn deliver(_: ()) -> Result<XcmHash, SendError> {
-		Ok([0; 32])
+/// Implementation of [`PriceForMessageDelivery`], returning a different price
+/// based on whether a message contains a reanchored asset or not.
+/// This implementation ensures that messages with non-reanchored assets return higher
+/// prices than messages with reanchored assets.
+/// Useful for `deposit_reserve_asset_works_for_any_xcm_sender` integration test.
+pub struct TestDeliveryPrice<A, F>(sp_std::marker::PhantomData<(A, F)>);
+impl<A: Get<AssetId>, F: FeeTracker> PriceForMessageDelivery for TestDeliveryPrice<A, F> {
+	type Id = F::Id;
+
+	fn price_for_delivery(_: Self::Id, msg: &Xcm<()>) -> Assets {
+		let base_fee: super::Balance = 1_000_000;
+
+		let parents = msg.iter().find_map(|xcm| match xcm {
+			ReserveAssetDeposited(assets) => {
+				let AssetId(location) = &assets.inner().first().unwrap().id;
+				Some(location.parents)
+			},
+			_ => None,
+		});
+
+		// If no asset is found, price defaults to `base_fee`.
+		let amount = base_fee
+			.saturating_add(base_fee.saturating_mul(parents.unwrap_or(0) as super::Balance));
+
+		(A::get(), amount).into()
 	}
 }
 
+pub type PriceForChildParachainDelivery = TestDeliveryPrice<FeeAssetId, super::Dmp>;
+
+/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our
+/// individual routers.
+pub type XcmRouter = WithUniqueTopic<
+	// Only one router so far - use DMP to communicate with child parachains.
+	ChildParachainRouter<super::Runtime, super::Xcm, PriceForChildParachainDelivery>,
+>;
+
 pub type Barrier = AllowUnpaidExecutionFrom<Everything>;
 
 pub struct DummyAssetTransactor;
@@ -99,7 +129,7 @@ type OriginConverter = (
 pub struct XcmConfig;
 impl xcm_executor::Config for XcmConfig {
 	type RuntimeCall = super::RuntimeCall;
-	type XcmSender = DoNothingRouter;
+	type XcmSender = XcmRouter;
 	type AssetTransactor = DummyAssetTransactor;
 	type OriginConverter = OriginConverter;
 	type IsReserve = ();
@@ -133,7 +163,7 @@ impl pallet_xcm::Config for crate::Runtime {
 	type UniversalLocation = UniversalLocation;
 	type SendXcmOrigin = EnsureXcmOrigin<crate::RuntimeOrigin, LocalOriginToLocation>;
 	type Weigher = FixedWeightBounds<BaseXcmWeight, crate::RuntimeCall, MaxInstructions>;
-	type XcmRouter = DoNothingRouter;
+	type XcmRouter = XcmRouter;
 	type XcmExecuteFilter = Everything;
 	type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>;
 	type XcmTeleportFilter = Everything;
diff --git a/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml b/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml
index cafe12dc587f883a31ac3539aced38e8de29a89e..1e572e6210a27a7469f827bbe5d076c01c84f032 100644
--- a/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml
+++ b/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml
@@ -20,6 +20,7 @@ pallet-xcm = { path = "../../pallet-xcm" }
 polkadot-test-client = { path = "../../../node/test/client" }
 polkadot-test-runtime = { path = "../../../runtime/test-runtime" }
 polkadot-test-service = { path = "../../../node/test/service" }
+polkadot-service = { path = "../../../node/service" }
 sp-consensus = { path = "../../../../substrate/primitives/consensus/common" }
 sp-keyring = { path = "../../../../substrate/primitives/keyring" }
 sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false }
@@ -27,6 +28,7 @@ sp-state-machine = { path = "../../../../substrate/primitives/state-machine" }
 xcm = { package = "staging-xcm", path = "../..", default-features = false }
 xcm-executor = { package = "staging-xcm-executor", path = ".." }
 sp-tracing = { path = "../../../../substrate/primitives/tracing" }
+sp-core = { path = "../../../../substrate/primitives/core" }
 
 [features]
 default = ["std"]
diff --git a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
index 79d6cb1c411b12da2a9f6b81a01b93a44c97ebe9..da7fc0d97825f24e1eea91e441cecef11a136e5f 100644
--- a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
+++ b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs
@@ -19,12 +19,14 @@
 
 use codec::Encode;
 use frame_support::{dispatch::GetDispatchInfo, weights::Weight};
+use polkadot_service::chain_spec::get_account_id_from_seed;
 use polkadot_test_client::{
 	BlockBuilderExt, ClientBlockImportExt, DefaultTestClientBuilderExt, InitPolkadotBlockBuilder,
 	TestClientBuilder, TestClientBuilderExt,
 };
 use polkadot_test_runtime::{pallet_test_notifier, xcm_config::XcmConfig};
 use polkadot_test_service::construct_extrinsic;
+use sp_core::sr25519;
 use sp_runtime::traits::Block;
 use sp_state_machine::InspectState;
 use xcm::{latest::prelude::*, VersionedResponse, VersionedXcm};
@@ -323,3 +325,84 @@ fn query_response_elicits_handler() {
 		)));
 	});
 }
+
+/// Simulates a cross-chain message from Parachain to Parachain through Relay Chain
+/// that deposits assets into the reserve of the destination.
+/// Regression test for `DepostiReserveAsset` changes in
+/// <https://github.com/paritytech/polkadot-sdk/pull/3340>
+#[test]
+fn deposit_reserve_asset_works_for_any_xcm_sender() {
+	sp_tracing::try_init_simple();
+	let mut client = TestClientBuilder::new().build();
+
+	// Init values for the simulated origin Parachain
+	let amount_to_send: u128 = 1_000_000_000_000;
+	let assets: Assets = (Parent, amount_to_send).into();
+	let fee_asset_item = 0;
+	let max_assets = assets.len() as u32;
+	let fees = assets.get(fee_asset_item as usize).unwrap().clone();
+	let weight_limit = Unlimited;
+	let reserve = Location::parent();
+	let dest = Location::new(1, [Parachain(2000)]);
+	let beneficiary_id = get_account_id_from_seed::<sr25519::Public>("Alice");
+	let beneficiary = Location::new(0, [AccountId32 { network: None, id: beneficiary_id.into() }]);
+
+	// spends up to half of fees for execution on reserve and other half for execution on
+	// destination
+	let fee1 = amount_to_send.saturating_div(2);
+	let fee2 = amount_to_send.saturating_sub(fee1);
+	let fees_half_1 = Asset::from((fees.id.clone(), Fungible(fee1)));
+	let fees_half_2 = Asset::from((fees.id.clone(), Fungible(fee2)));
+
+	let reserve_context = <XcmConfig as xcm_executor::Config>::UniversalLocation::get();
+	// identifies fee item as seen by `reserve` - to be used at reserve chain
+	let reserve_fees = fees_half_1.reanchored(&reserve, &reserve_context).unwrap();
+	// identifies fee item as seen by `dest` - to be used at destination chain
+	let dest_fees = fees_half_2.reanchored(&dest, &reserve_context).unwrap();
+	// identifies assets as seen by `reserve` - to be used at reserve chain
+	let assets_reanchored = assets.reanchored(&reserve, &reserve_context).unwrap();
+	// identifies `dest` as seen by `reserve`
+	let dest = dest.reanchored(&reserve, &reserve_context).unwrap();
+	// xcm to be executed at dest
+	let xcm_on_dest = Xcm(vec![
+		BuyExecution { fees: dest_fees, weight_limit: weight_limit.clone() },
+		DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary },
+	]);
+	// xcm to be executed at reserve
+	let msg = Xcm(vec![
+		WithdrawAsset(assets_reanchored),
+		ClearOrigin,
+		BuyExecution { fees: reserve_fees, weight_limit },
+		DepositReserveAsset { assets: Wild(AllCounted(max_assets)), dest, xcm: xcm_on_dest },
+	]);
+
+	let mut block_builder = client.init_polkadot_block_builder();
+
+	// Simulate execution of an incoming XCM message at the reserve chain
+	let execute = construct_extrinsic(
+		&client,
+		polkadot_test_runtime::RuntimeCall::Xcm(pallet_xcm::Call::execute {
+			message: Box::new(VersionedXcm::from(msg)),
+			max_weight: Weight::from_parts(1_000_000_000, 1024 * 1024),
+		}),
+		sp_keyring::Sr25519Keyring::Alice,
+		0,
+	);
+
+	block_builder.push_polkadot_extrinsic(execute).expect("pushes extrinsic");
+
+	let block = block_builder.build().expect("Finalizes the block").block;
+	let block_hash = block.hash();
+
+	futures::executor::block_on(client.import(sp_consensus::BlockOrigin::Own, block))
+		.expect("imports the block");
+
+	client.state_at(block_hash).expect("state should exist").inspect_state(|| {
+		assert!(polkadot_test_runtime::System::events().iter().any(|r| matches!(
+			r.event,
+			polkadot_test_runtime::RuntimeEvent::Xcm(pallet_xcm::Event::Attempted {
+				outcome: Outcome::Complete { .. }
+			}),
+		)));
+	});
+}
diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs
index b26779f3ae9da206d76823027dc193dc771cc215..c61e1e1d15bcd8fd78ffe47c415abeaf8c1cb4cd 100644
--- a/polkadot/xcm/xcm-executor/src/lib.rs
+++ b/polkadot/xcm/xcm-executor/src/lib.rs
@@ -826,9 +826,9 @@ impl<Config: config::Config> XcmExecutor<Config> {
 					// be weighed
 					let to_weigh = self.holding.saturating_take(assets.clone());
 					self.holding.subsume_assets(to_weigh.clone());
-
+					let to_weigh_reanchored = Self::reanchored(to_weigh, &dest, None);
 					let mut message_to_weigh =
-						vec![ReserveAssetDeposited(to_weigh.into()), ClearOrigin];
+						vec![ReserveAssetDeposited(to_weigh_reanchored), ClearOrigin];
 					message_to_weigh.extend(xcm.0.clone().into_iter());
 					let (_, fee) =
 						validate_send::<Config::XcmSender>(dest.clone(), Xcm(message_to_weigh))?;