diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs
index a7a658f060176c45753fd20ddc9f2ad8e623693b..a4900a71539a5827dad95ce40c7660381aad085c 100644
--- a/polkadot/xcm/src/v3/multiasset.rs
+++ b/polkadot/xcm/src/v3/multiasset.rs
@@ -406,7 +406,7 @@ pub struct MultiAsset {
 	/// The overall asset identity (aka *class*, in the case of a non-fungible).
 	pub id: AssetId,
 	/// The fungibility of the asset, which contains either the amount (in the case of a fungible
-	/// asset) or the *instance ID`, the secondary asset identifier.
+	/// asset) or the *instance ID*, the secondary asset identifier.
 	pub fun: Fungibility,
 }
 
diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs
index 984ace84dc69a4491d81ad76d60f42054b813679..e3f91040963840d2b29ceaa30fc1a8e373de4817 100644
--- a/polkadot/xcm/xcm-builder/src/lib.rs
+++ b/polkadot/xcm/xcm-builder/src/lib.rs
@@ -33,8 +33,9 @@ pub use location_conversion::{
 	Account32Hash, AccountId32Aliases, AccountKey20Aliases, AliasesIntoAccountId32,
 	ChildParachainConvertsVia, DescribeAccountId32Terminal, DescribeAccountIdTerminal,
 	DescribeAccountKey20Terminal, DescribeAllTerminal, DescribeFamily, DescribeLocation,
-	DescribePalletTerminal, DescribeTerminus, GlobalConsensusParachainConvertsFor,
-	HashedDescription, ParentIsPreset, SiblingParachainConvertsVia,
+	DescribePalletTerminal, DescribeTerminus, GlobalConsensusConvertsFor,
+	GlobalConsensusParachainConvertsFor, HashedDescription, ParentIsPreset,
+	SiblingParachainConvertsVia,
 };
 
 mod origin_conversion;
diff --git a/polkadot/xcm/xcm-builder/src/location_conversion.rs b/polkadot/xcm/xcm-builder/src/location_conversion.rs
index 3a95884328a1874d1a85808e26f4140e53a11fd4..ccc3cc040e61428221e48e53565dca6f648316ec 100644
--- a/polkadot/xcm/xcm-builder/src/location_conversion.rs
+++ b/polkadot/xcm/xcm-builder/src/location_conversion.rs
@@ -345,6 +345,42 @@ impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 20]> + Into<[u8; 20]>
 	}
 }
 
+/// Converts a location which is a top-level relay chain (which provides its own consensus) into a 32-byte `AccountId`.
+///
+/// This will always result in the *same account ID* being returned for the same Relay-chain, regardless of the relative security of
+/// this Relay-chain compared to the local chain.
+///
+/// Note: No distinction is made between the cases when the given `UniversalLocation` lies within
+/// the same consensus system (i.e. is itself or a parent) and when it is a foreign consensus
+/// system.
+pub struct GlobalConsensusConvertsFor<UniversalLocation, AccountId>(
+	PhantomData<(UniversalLocation, AccountId)>,
+);
+impl<UniversalLocation: Get<InteriorMultiLocation>, AccountId: From<[u8; 32]> + Clone>
+	ConvertLocation<AccountId> for GlobalConsensusConvertsFor<UniversalLocation, AccountId>
+{
+	fn convert_location(location: &MultiLocation) -> Option<AccountId> {
+		let universal_source = UniversalLocation::get();
+		log::trace!(
+			target: "xcm::location_conversion",
+			"GlobalConsensusConvertsFor universal_source: {:?}, location: {:?}",
+			universal_source, location,
+		);
+		let (remote_network, remote_location) =
+			ensure_is_remote(universal_source, *location).ok()?;
+
+		match remote_location {
+			Here => Some(AccountId::from(Self::from_params(&remote_network))),
+			_ => None,
+		}
+	}
+}
+impl<UniversalLocation, AccountId> GlobalConsensusConvertsFor<UniversalLocation, AccountId> {
+	fn from_params(network: &NetworkId) -> [u8; 32] {
+		(b"glblcnsnss_", network).using_encoded(blake2_256)
+	}
+}
+
 /// Converts a location which is a top-level parachain (i.e. a parachain held on a
 /// Relay-chain which provides its own consensus) into a 32-byte `AccountId`.
 ///
@@ -473,6 +509,105 @@ mod tests {
 		assert_eq!(inverted, Err(()));
 	}
 
+	#[test]
+	fn global_consensus_converts_for_works() {
+		parameter_types! {
+			pub UniversalLocationInNetwork1: InteriorMultiLocation = X2(GlobalConsensus(ByGenesis([1; 32])), Parachain(1234));
+			pub UniversalLocationInNetwork2: InteriorMultiLocation = X2(GlobalConsensus(ByGenesis([2; 32])), Parachain(1234));
+		}
+		let network_1 = UniversalLocationInNetwork1::get().global_consensus().expect("NetworkId");
+		let network_2 = UniversalLocationInNetwork2::get().global_consensus().expect("NetworkId");
+		let network_3 = ByGenesis([3; 32]);
+		let network_4 = ByGenesis([4; 32]);
+		let network_5 = ByGenesis([5; 32]);
+
+		let test_data = vec![
+			(MultiLocation::parent(), false),
+			(MultiLocation::new(0, Here), false),
+			(MultiLocation::new(0, X1(GlobalConsensus(network_1))), false),
+			(MultiLocation::new(1, X1(GlobalConsensus(network_1))), false),
+			(MultiLocation::new(2, X1(GlobalConsensus(network_1))), false),
+			(MultiLocation::new(0, X1(GlobalConsensus(network_2))), false),
+			(MultiLocation::new(1, X1(GlobalConsensus(network_2))), false),
+			(MultiLocation::new(2, X1(GlobalConsensus(network_2))), true),
+			(MultiLocation::new(0, X2(GlobalConsensus(network_2), Parachain(1000))), false),
+			(MultiLocation::new(1, X2(GlobalConsensus(network_2), Parachain(1000))), false),
+			(MultiLocation::new(2, X2(GlobalConsensus(network_2), Parachain(1000))), false),
+		];
+
+		for (location, expected_result) in test_data {
+			let result =
+				GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
+					&location,
+				);
+			match result {
+				Some(account) => {
+					assert_eq!(
+						true, expected_result,
+						"expected_result: {}, but conversion passed: {:?}, location: {:?}",
+						expected_result, account, location
+					);
+					match &location {
+						MultiLocation { interior: X1(GlobalConsensus(network)), .. } =>
+							assert_eq!(
+								account,
+								GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::from_params(network),
+								"expected_result: {}, but conversion passed: {:?}, location: {:?}", expected_result, account, location
+							),
+						_ => panic!("expected_result: {}, conversion passed: {:?}, but MultiLocation does not match expected pattern, location: {:?}", expected_result, account, location)
+					}
+				},
+				None => {
+					assert_eq!(
+						false, expected_result,
+						"expected_result: {} - but conversion failed, location: {:?}",
+						expected_result, location
+					);
+				},
+			}
+		}
+
+		// all success
+		let res_1_gc_network_3 =
+			GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
+				&MultiLocation::new(2, X1(GlobalConsensus(network_3))),
+			)
+			.expect("conversion is ok");
+		let res_2_gc_network_3 =
+			GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
+				&MultiLocation::new(2, X1(GlobalConsensus(network_3))),
+			)
+			.expect("conversion is ok");
+		let res_1_gc_network_4 =
+			GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
+				&MultiLocation::new(2, X1(GlobalConsensus(network_4))),
+			)
+			.expect("conversion is ok");
+		let res_2_gc_network_4 =
+			GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
+				&MultiLocation::new(2, X1(GlobalConsensus(network_4))),
+			)
+			.expect("conversion is ok");
+		let res_1_gc_network_5 =
+			GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
+				&MultiLocation::new(2, X1(GlobalConsensus(network_5))),
+			)
+			.expect("conversion is ok");
+		let res_2_gc_network_5 =
+			GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
+				&MultiLocation::new(2, X1(GlobalConsensus(network_5))),
+			)
+			.expect("conversion is ok");
+
+		assert_ne!(res_1_gc_network_3, res_1_gc_network_4);
+		assert_ne!(res_1_gc_network_4, res_1_gc_network_5);
+		assert_ne!(res_1_gc_network_3, res_1_gc_network_5);
+
+		assert_eq!(res_1_gc_network_3, res_2_gc_network_3);
+		assert_eq!(res_1_gc_network_4, res_2_gc_network_4);
+		assert_eq!(res_1_gc_network_5, res_2_gc_network_5);
+	}
+
 	#[test]
 	fn global_consensus_parachain_converts_for_works() {
 		parameter_types! {