diff --git a/substrate/primitives/state-machine/src/testing.rs b/substrate/primitives/state-machine/src/testing.rs
index 78fec43cd7ec798c936fecddd69f058e888a62b2..eefd6b1fbde93844329b3eb80367bced3c292087 100644
--- a/substrate/primitives/state-machine/src/testing.rs
+++ b/substrate/primitives/state-machine/src/testing.rs
@@ -164,9 +164,17 @@ where
 	///
 	/// This can be used as a fast way to restore the storage state from a backup because the trie
 	/// does not need to be computed.
-	pub fn from_raw_snapshot(&mut self, raw_storage: Vec<(H::Out, Vec<u8>)>, storage_root: H::Out) {
-		for (k, v) in raw_storage {
-			self.backend.backend_storage_mut().emplace(k, hash_db::EMPTY_PREFIX, v);
+	pub fn from_raw_snapshot(
+		&mut self,
+		raw_storage: Vec<(H::Out, (Vec<u8>, i32))>,
+		storage_root: H::Out,
+	) {
+		for (k, (v, ref_count)) in raw_storage {
+			// Each time .emplace is called the internal MemoryDb ref count increments.
+			// Repeatedly call emplace to initialise the ref count to the correct value.
+			for _ in 0..ref_count {
+				self.backend.backend_storage_mut().emplace(k, hash_db::EMPTY_PREFIX, v.clone());
+			}
 		}
 		self.backend.set_root(storage_root);
 	}
@@ -176,14 +184,13 @@ where
 	/// Useful for backing up the storage in a format that can be quickly re-loaded.
 	///
 	/// Note: This DB will be inoperable after this call.
-	pub fn into_raw_snapshot(mut self) -> (Vec<(H::Out, Vec<u8>)>, H::Out) {
+	pub fn into_raw_snapshot(mut self) -> (Vec<(H::Out, (Vec<u8>, i32))>, H::Out) {
 		let raw_key_values = self
 			.backend
 			.backend_storage_mut()
 			.drain()
 			.into_iter()
-			.map(|(k, v)| (k, v.0))
-			.collect::<Vec<(H::Out, Vec<u8>)>>();
+			.collect::<Vec<(H::Out, (Vec<u8>, i32))>>();
 
 		(raw_key_values, *self.backend.root())
 	}
@@ -402,6 +409,28 @@ mod tests {
 		original_ext.insert_child(child_info.clone(), b"cattytown".to_vec(), b"is_dark".to_vec());
 		original_ext.insert_child(child_info.clone(), b"doggytown".to_vec(), b"is_sunny".to_vec());
 
+		// Call emplace on one of the keys to increment the MemoryDb refcount, so we can check
+		// that it is intact in the recovered_ext.
+		let keys = original_ext.backend.backend_storage_mut().keys();
+		let expected_ref_count = 5;
+		let ref_count_key = keys.into_iter().next().unwrap().0;
+		for _ in 0..expected_ref_count - 1 {
+			original_ext.backend.backend_storage_mut().emplace(
+				ref_count_key,
+				hash_db::EMPTY_PREFIX,
+				// We can use anything for the 'value' because it does not affect behavior when
+				// emplacing an existing key.
+				(&[0u8; 32]).to_vec(),
+			);
+		}
+		let refcount = original_ext
+			.backend
+			.backend_storage()
+			.raw(&ref_count_key, hash_db::EMPTY_PREFIX)
+			.unwrap()
+			.1;
+		assert_eq!(refcount, expected_ref_count);
+
 		// Drain the raw storage and root.
 		let root = *original_ext.backend.root();
 		let (raw_storage, storage_root) = original_ext.into_raw_snapshot();
@@ -428,6 +457,15 @@ mod tests {
 			recovered_ext.backend.child_storage(&child_info, b"doggytown").unwrap(),
 			Some(b"is_sunny".to_vec())
 		);
+
+		// Check the refcount of the key with > 1 refcount is correct.
+		let refcount = recovered_ext
+			.backend
+			.backend_storage()
+			.raw(&ref_count_key, hash_db::EMPTY_PREFIX)
+			.unwrap()
+			.1;
+		assert_eq!(refcount, expected_ref_count);
 	}
 
 	#[test]
diff --git a/substrate/utils/frame/remote-externalities/src/lib.rs b/substrate/utils/frame/remote-externalities/src/lib.rs
index 42df99137b2ded632805236ff04e8ef20f7c88c6..7cd3d3750aebc72d3f720c257dbece9ce983c1ef 100644
--- a/substrate/utils/frame/remote-externalities/src/lib.rs
+++ b/substrate/utils/frame/remote-externalities/src/lib.rs
@@ -21,7 +21,7 @@
 //! based chain, or a local state snapshot file.
 
 use async_recursion::async_recursion;
-use codec::{Decode, Encode};
+use codec::{Compact, Decode, Encode};
 use indicatif::{ProgressBar, ProgressStyle};
 use jsonrpsee::{
 	core::params::ArrayParams,
@@ -54,18 +54,61 @@ use tokio_retry::{strategy::FixedInterval, Retry};
 type KeyValue = (StorageKey, StorageData);
 type TopKeyValues = Vec<KeyValue>;
 type ChildKeyValues = Vec<(ChildInfo, Vec<KeyValue>)>;
+type SnapshotVersion = Compact<u16>;
 
 const LOG_TARGET: &str = "remote-ext";
 const DEFAULT_HTTP_ENDPOINT: &str = "https://rpc.polkadot.io:443";
+const SNAPSHOT_VERSION: SnapshotVersion = Compact(2);
+
 /// The snapshot that we store on disk.
 #[derive(Decode, Encode)]
 struct Snapshot<B: BlockT> {
+	snapshot_version: SnapshotVersion,
 	state_version: StateVersion,
 	block_hash: B::Hash,
-	raw_storage: Vec<(H256, Vec<u8>)>,
+	// <Vec<Key, (Value, MemoryDbRefCount)>>
+	raw_storage: Vec<(H256, (Vec<u8>, i32))>,
 	storage_root: H256,
 }
 
+impl<B: BlockT> Snapshot<B> {
+	pub fn new(
+		state_version: StateVersion,
+		block_hash: B::Hash,
+		raw_storage: Vec<(H256, (Vec<u8>, i32))>,
+		storage_root: H256,
+	) -> Self {
+		Self {
+			snapshot_version: SNAPSHOT_VERSION,
+			state_version,
+			block_hash,
+			raw_storage,
+			storage_root,
+		}
+	}
+
+	fn load(path: &PathBuf) -> Result<Snapshot<B>, &'static str> {
+		let bytes = fs::read(path).map_err(|_| "fs::read failed.")?;
+		// The first item in the SCALE encoded struct bytes is the snapshot version. We decode and
+		// check that first, before proceeding to decode the rest of the snapshot.
+		let maybe_version: Result<SnapshotVersion, _> = Decode::decode(&mut &*bytes);
+		match maybe_version {
+			Ok(snapshot_version) => {
+				if snapshot_version != SNAPSHOT_VERSION {
+					return Err(
+						"Unsupported snapshot version detected. Please create a new snapshot.",
+					)
+				}
+				match Decode::decode(&mut &*bytes) {
+					Ok(snapshot) => return Ok(snapshot),
+					Err(_) => Err("Decode failed"),
+				}
+			},
+			Err(_) => Err("Decode failed"),
+		}
+	}
+}
+
 /// An externalities that acts exactly the same as [`sp_io::TestExternalities`] but has a few extra
 /// bits and pieces to it, and can be loaded remotely.
 pub struct RemoteExternalities<B: BlockT> {
@@ -908,15 +951,14 @@ where
 		// If we need to save a snapshot, save the raw storage and root hash to the snapshot.
 		if let Some(path) = self.as_online().state_snapshot.clone().map(|c| c.path) {
 			let (raw_storage, storage_root) = pending_ext.into_raw_snapshot();
-			let snapshot = Snapshot::<B> {
+			let snapshot = Snapshot::<B>::new(
 				state_version,
-				block_hash: self
-					.as_online()
+				self.as_online()
 					.at
 					.expect("set to `Some` in `init_remote_client`; must be called before; qed"),
-				raw_storage: raw_storage.clone(),
+				raw_storage.clone(),
 				storage_root,
-			};
+			);
 			let encoded = snapshot.encode();
 			log::info!(
 				target: LOG_TARGET,
@@ -939,12 +981,6 @@ where
 		Ok(pending_ext)
 	}
 
-	fn load_snapshot(&mut self, path: PathBuf) -> Result<Snapshot<B>, &'static str> {
-		info!(target: LOG_TARGET, "loading data from snapshot {:?}", path);
-		let bytes = fs::read(path).map_err(|_| "fs::read failed.")?;
-		Decode::decode(&mut &*bytes).map_err(|_| "decode failed")
-	}
-
 	async fn do_load_remote(&mut self) -> Result<RemoteExternalities<B>, &'static str> {
 		self.init_remote_client().await?;
 		let block_hash = self.as_online().at_expected();
@@ -958,8 +994,9 @@ where
 	) -> Result<RemoteExternalities<B>, &'static str> {
 		let mut sp = Spinner::with_timer(Spinners::Dots, "Loading snapshot...".into());
 		let start = Instant::now();
-		let Snapshot { block_hash, state_version, raw_storage, storage_root } =
-			self.load_snapshot(config.state_snapshot.path.clone())?;
+		info!(target: LOG_TARGET, "Loading snapshot from {:?}", &config.state_snapshot.path);
+		let Snapshot { snapshot_version: _, block_hash, state_version, raw_storage, storage_root } =
+			Snapshot::<B>::load(&config.state_snapshot.path)?;
 
 		let mut inner_ext = TestExternalities::new_with_code_and_state(
 			Default::default(),
diff --git a/substrate/utils/frame/remote-externalities/test_data/proxy_test b/substrate/utils/frame/remote-externalities/test_data/proxy_test
index f749531a8a9d767b14e1869bbfa16c390cacfa68..de8105ee152df9e6f0970243f7789d37c1461734 100644
Binary files a/substrate/utils/frame/remote-externalities/test_data/proxy_test and b/substrate/utils/frame/remote-externalities/test_data/proxy_test differ