diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs
index f9041ecd81bac1b383b65ea8920920ff95e14419..0662077b19d03ba86dbfc0f320ae39f438719b7c 100644
--- a/polkadot/xcm/src/v3/multiasset.rs
+++ b/polkadot/xcm/src/v3/multiasset.rs
@@ -825,7 +825,9 @@ impl MultiAssets {
 
 	/// Prepend a `MultiLocation` to any concrete asset items, giving it a new root location.
 	pub fn prepend_with(&mut self, prefix: &MultiLocation) -> Result<(), ()> {
-		self.0.iter_mut().try_for_each(|i| i.prepend_with(prefix))
+		self.0.iter_mut().try_for_each(|i| i.prepend_with(prefix))?;
+		self.0.sort();
+		Ok(())
 	}
 
 	/// Mutate the location of the asset identifier if concrete, giving it the same location
@@ -1213,8 +1215,73 @@ mod tests {
 			vec![asset_1.clone(), asset_2.clone(), asset_3.clone()].into();
 		assert_eq!(assets.clone(), vec![asset_1.clone(), asset_2.clone(), asset_3.clone()].into());
 
+		// decoding respects limits and sorting
+		assert!(assets
+			.using_encoded(|mut enc| MultiAssets::decode(&mut enc).map(|_| ()))
+			.is_ok());
+
 		assert!(assets.reanchor(&dest, reanchor_context).is_ok());
-		assert_eq!(assets, vec![asset_2_reanchored, asset_3_reanchored, asset_1_reanchored].into());
+		assert_eq!(assets.0, vec![asset_2_reanchored, asset_3_reanchored, asset_1_reanchored]);
+
+		// decoding respects limits and sorting
+		assert!(assets
+			.using_encoded(|mut enc| MultiAssets::decode(&mut enc).map(|_| ()))
+			.is_ok());
+	}
+
+	#[test]
+	fn prepend_preserves_sorting() {
+		use super::*;
+		use alloc::vec;
+
+		let prefix = MultiLocation::new(0, X1(Parachain(1000)));
+
+		let asset_1: MultiAsset =
+			(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1))), 10).into();
+		let mut asset_1_prepended = asset_1.clone();
+		assert!(asset_1_prepended.prepend_with(&prefix).is_ok());
+		// changes interior X2->X3
+		assert_eq!(
+			asset_1_prepended,
+			(MultiLocation::new(0, X3(Parachain(1000), PalletInstance(50), GeneralIndex(1))), 10)
+				.into()
+		);
+
+		let asset_2: MultiAsset =
+			(MultiLocation::new(1, X2(PalletInstance(50), GeneralIndex(1))), 10).into();
+		let mut asset_2_prepended = asset_2.clone();
+		assert!(asset_2_prepended.prepend_with(&prefix).is_ok());
+		// changes parent
+		assert_eq!(
+			asset_2_prepended,
+			(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1))), 10).into()
+		);
+
+		let asset_3: MultiAsset =
+			(MultiLocation::new(2, X2(PalletInstance(50), GeneralIndex(1))), 10).into();
+		let mut asset_3_prepended = asset_3.clone();
+		assert!(asset_3_prepended.prepend_with(&prefix).is_ok());
+		// changes parent
+		assert_eq!(
+			asset_3_prepended,
+			(MultiLocation::new(1, X2(PalletInstance(50), GeneralIndex(1))), 10).into()
+		);
+
+		// `From` impl does sorting.
+		let mut assets: MultiAssets = vec![asset_1, asset_2, asset_3].into();
+		// decoding respects limits and sorting
+		assert!(assets
+			.using_encoded(|mut enc| MultiAssets::decode(&mut enc).map(|_| ()))
+			.is_ok());
+
+		// let's do `prepend_with`
+		assert!(assets.prepend_with(&prefix).is_ok());
+		assert_eq!(assets.0, vec![asset_2_prepended, asset_1_prepended, asset_3_prepended]);
+
+		// decoding respects limits and sorting
+		assert!(assets
+			.using_encoded(|mut enc| MultiAssets::decode(&mut enc).map(|_| ()))
+			.is_ok());
 	}
 
 	#[test]
diff --git a/polkadot/xcm/src/v4/asset.rs b/polkadot/xcm/src/v4/asset.rs
index bdff0c272306aced0fbf5f2372a70d66ac37e841..8abd8f9f8fd0f0bdc5b5f77c065e1ff775b55e1e 100644
--- a/polkadot/xcm/src/v4/asset.rs
+++ b/polkadot/xcm/src/v4/asset.rs
@@ -723,7 +723,9 @@ impl Assets {
 
 	/// Prepend a `Location` to any concrete asset items, giving it a new root location.
 	pub fn prepend_with(&mut self, prefix: &Location) -> Result<(), ()> {
-		self.0.iter_mut().try_for_each(|i| i.prepend_with(prefix))
+		self.0.iter_mut().try_for_each(|i| i.prepend_with(prefix))?;
+		self.0.sort();
+		Ok(())
 	}
 
 	/// Return a reference to an item at a specific index or `None` if it doesn't exist.
@@ -1035,8 +1037,61 @@ mod tests {
 		let mut assets: Assets = vec![asset_1.clone(), asset_2.clone(), asset_3.clone()].into();
 		assert_eq!(assets.clone(), vec![asset_1.clone(), asset_2.clone(), asset_3.clone()].into());
 
+		// decoding respects limits and sorting
+		assert!(assets.using_encoded(|mut enc| Assets::decode(&mut enc).map(|_| ())).is_ok());
+
 		assert!(assets.reanchor(&dest, &reanchor_context).is_ok());
-		assert_eq!(assets, vec![asset_2_reanchored, asset_3_reanchored, asset_1_reanchored].into());
+		assert_eq!(assets.0, vec![asset_2_reanchored, asset_3_reanchored, asset_1_reanchored]);
+
+		// decoding respects limits and sorting
+		assert!(assets.using_encoded(|mut enc| Assets::decode(&mut enc).map(|_| ())).is_ok());
+	}
+
+	#[test]
+	fn prepend_preserves_sorting() {
+		use super::*;
+		use alloc::vec;
+
+		let prefix = Location::new(0, [Parachain(1000)]);
+
+		let asset_1: Asset = (Location::new(0, [PalletInstance(50), GeneralIndex(1)]), 10).into();
+		let mut asset_1_prepended = asset_1.clone();
+		assert!(asset_1_prepended.prepend_with(&prefix).is_ok());
+		// changes interior X2->X3
+		assert_eq!(
+			asset_1_prepended,
+			(Location::new(0, [Parachain(1000), PalletInstance(50), GeneralIndex(1)]), 10).into()
+		);
+
+		let asset_2: Asset = (Location::new(1, [PalletInstance(50), GeneralIndex(1)]), 10).into();
+		let mut asset_2_prepended = asset_2.clone();
+		assert!(asset_2_prepended.prepend_with(&prefix).is_ok());
+		// changes parent
+		assert_eq!(
+			asset_2_prepended,
+			(Location::new(0, [PalletInstance(50), GeneralIndex(1)]), 10).into()
+		);
+
+		let asset_3: Asset = (Location::new(2, [PalletInstance(50), GeneralIndex(1)]), 10).into();
+		let mut asset_3_prepended = asset_3.clone();
+		assert!(asset_3_prepended.prepend_with(&prefix).is_ok());
+		// changes parent
+		assert_eq!(
+			asset_3_prepended,
+			(Location::new(1, [PalletInstance(50), GeneralIndex(1)]), 10).into()
+		);
+
+		// `From` impl does sorting.
+		let mut assets: Assets = vec![asset_1, asset_2, asset_3].into();
+		// decoding respects limits and sorting
+		assert!(assets.using_encoded(|mut enc| Assets::decode(&mut enc).map(|_| ())).is_ok());
+
+		// let's do `prepend_with`
+		assert!(assets.prepend_with(&prefix).is_ok());
+		assert_eq!(assets.0, vec![asset_2_prepended, asset_1_prepended, asset_3_prepended]);
+
+		// decoding respects limits and sorting
+		assert!(assets.using_encoded(|mut enc| Assets::decode(&mut enc).map(|_| ())).is_ok());
 	}
 
 	#[test]